Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 589ca45936 | |||
| 0cff07101c |
@@ -10,11 +10,10 @@ Libraries bundled along with binaries for Windows (MSVC14), available as a submo
|
|||||||
| **[zlib](http://www.zlib.net)** | 1.28 | [zlib License](http://www.zlib.net/zlib_license.html) |
|
| **[zlib](http://www.zlib.net)** | 1.28 | [zlib License](http://www.zlib.net/zlib_license.html) |
|
||||||
| **[libpng](http://www.libpng.org/pub/png/libpng.html)** | 1.6.19 | [libpng License](http://www.libpng.org/pub/png/src/libpng-LICENSE.txt) |
|
| **[libpng](http://www.libpng.org/pub/png/libpng.html)** | 1.6.19 | [libpng License](http://www.libpng.org/pub/png/src/libpng-LICENSE.txt) |
|
||||||
| **[Xerces-C++](https://xerces.apache.org/xerces-c)** | 3.1.2 | [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
| **[Xerces-C++](https://xerces.apache.org/xerces-c)** | 3.1.2 | [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) |
|
||||||
| **[ImGui](https://github.com/ocornut/imgui)** | 2015-12-12 | [MIT License](https://github.com/ocornut/imgui/blob/de3a154f3801de22c8e0bd2aeabf663a70c05972/LICENSE) |
|
|
||||||
|
|
||||||
#### External libraries
|
#### External libraries
|
||||||
Libraries that are too big to be bundled with the project.
|
Libraries that are too big to be bundled with the project.
|
||||||
|
|
||||||
| Project | Version | License | Root folder environment variable (Windows) |
|
| Project | Version | License | Root folder environment variable (Windows) |
|
||||||
| ---------------------------------------------------------- | ----------- | --------------------------------------------------------------------------- | ------------------------------------------ |
|
| ---------------------------------------------------------- | ----------- | --------------------------------------------------------------------------- | ------------------------------------------ |
|
||||||
| **[Boost](http://www.boost.org)** | 1.60.0+ | [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt) | BOOST_ROOT |
|
| **[Boost](http://www.boost.org)** | 1.59.0+ | [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt) | BOOST_ROOT |
|
||||||
|
|||||||
+1
-1
Submodule assets updated: 673d4a4e4c...b37468222e
+1
-1
Submodule deps updated: 1ae6ba5b12...1b478d3159
@@ -1,59 +0,0 @@
|
|||||||
#ifndef Collision_h__
|
|
||||||
#define Collision_h__
|
|
||||||
|
|
||||||
//NOTE: Collision.h needs to be #included before <GLFW/glfw3.h>,
|
|
||||||
//because Collision #includes "RawModel.h", which has "Texture.h", which has "OpenGL.h" which must be #included first
|
|
||||||
//or you will get "fatal error C1189: #error: gl.h included before glew.h"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "Core/Ray.h"
|
|
||||||
#include "Core/AABB.h"
|
|
||||||
#include "Engine/Rendering/RawModel.h"
|
|
||||||
#include "Core/Entity.h"
|
|
||||||
|
|
||||||
class World;
|
|
||||||
struct ComponentWrapper;
|
|
||||||
|
|
||||||
namespace Collision
|
|
||||||
{
|
|
||||||
//Return true if the ray hits the box.
|
|
||||||
bool RayAABBIntr(const Ray& ray, const AABB& box);
|
|
||||||
bool RayVsAABB(const Ray& ray, const AABB& box);
|
|
||||||
//Return true if the ray hits the box, also outputs distance from ray origin to intersection point in [outDistance].
|
|
||||||
bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance);
|
|
||||||
|
|
||||||
//Return true if the ray hits any of the triangles in the model. Stops checking when a hit is detected.
|
|
||||||
bool RayVsModel(const Ray& ray,
|
|
||||||
const std::vector<RawModel::Vertex>& modelVertices,
|
|
||||||
const std::vector<unsigned int>& modelIndices);
|
|
||||||
//Return true if the ray hits any of the triangles in the model.
|
|
||||||
//Also returns the position of the intersection point. Will loop through all the whole model indices.
|
|
||||||
bool RayVsModel(const Ray& ray,
|
|
||||||
const std::vector<RawModel::Vertex>& modelVertices,
|
|
||||||
const std::vector<unsigned int>& modelIndices,
|
|
||||||
glm::vec3& outHitPosition);
|
|
||||||
//Return true if the ray hits any of the triangles in the model.
|
|
||||||
//Also returns the distance from the ray origin to the closest
|
|
||||||
//intersection point, and the barycentric u,v-coordinates. Will loop through all the whole model indices.
|
|
||||||
bool RayVsModel(const Ray& ray,
|
|
||||||
const std::vector<RawModel::Vertex>& modelVertices,
|
|
||||||
const std::vector<unsigned int>& modelIndices,
|
|
||||||
float& outDistance,
|
|
||||||
float& outUCoord,
|
|
||||||
float& outVCoord);
|
|
||||||
|
|
||||||
//Return true if the boxes are intersecting.
|
|
||||||
bool AABBVsAABB(const AABB& a, const AABB& b);
|
|
||||||
//Return true if the boxes are intersecting.
|
|
||||||
//Also outputs the minimum translation that box [a] would need in order to resolve collision.
|
|
||||||
bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation);
|
|
||||||
bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon = 0.0001f);
|
|
||||||
|
|
||||||
//Returns true if the entity has a boundingbox. Outputs the aabb in [outBox].
|
|
||||||
bool GetEntityBox(World* world, EntityID entity, AABB& outBox, bool forceBoxFromModel = false);
|
|
||||||
bool GetEntityBox(World* world, ComponentWrapper& AABBComponent, AABB& outBox);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#ifndef CollisionSystem_h__
|
|
||||||
#define CollisionSystem_h__
|
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
#include <glm/common.hpp>
|
|
||||||
|
|
||||||
#include "Common.h"
|
|
||||||
#include "Core/System.h"
|
|
||||||
#include "Core/EventBroker.h"
|
|
||||||
#include "Core/EKeyUp.h"
|
|
||||||
|
|
||||||
class CollisionSystem : public PureSystem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CollisionSystem(EventBroker* eventBroker)
|
|
||||||
: PureSystem(eventBroker, "AABB")
|
|
||||||
, zPress(false)
|
|
||||||
{
|
|
||||||
//TODO: Debug stuff, remove later.
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void UpdateComponent(World* world, ComponentWrapper& cAABB, double dt) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool zPress;
|
|
||||||
EventRelay<CollisionSystem, Events::KeyUp> m_EKeyUp;
|
|
||||||
bool OnKeyUp(const Events::KeyUp &event);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#ifndef Events_TriggerEnter_h__
|
|
||||||
#define Events_TriggerEnter_h__
|
|
||||||
|
|
||||||
#include "../Core/EventBroker.h"
|
|
||||||
#include "../Core/Entity.h"
|
|
||||||
|
|
||||||
namespace Events
|
|
||||||
{
|
|
||||||
|
|
||||||
/** Thrown once, when an entity is only touching a trigger. */
|
|
||||||
struct TriggerTouch : Event
|
|
||||||
{
|
|
||||||
/** The id of the entity that touches the trigger. */
|
|
||||||
EntityID Entity;
|
|
||||||
/** The id of the trigger entity. */
|
|
||||||
EntityID Trigger;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Thrown once, when an entity has completely left a trigger. */
|
|
||||||
struct TriggerLeave : Event
|
|
||||||
{
|
|
||||||
/** The id of the entity that left the trigger. */
|
|
||||||
EntityID Entity;
|
|
||||||
/** The id of the trigger entity. */
|
|
||||||
EntityID Trigger;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Thrown once, when an entity is completely contained inside a trigger. */
|
|
||||||
struct TriggerEnter : Event
|
|
||||||
{
|
|
||||||
/** The id of the entity that entered the trigger. */
|
|
||||||
EntityID Entity;
|
|
||||||
/** The id of the trigger entity. */
|
|
||||||
EntityID Trigger;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#ifndef TriggerSystem_h__
|
|
||||||
#define TriggerSystem_h__
|
|
||||||
|
|
||||||
#include <glm/common.hpp>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#include "Core/System.h"
|
|
||||||
#include "Core/EventBroker.h"
|
|
||||||
#include "ETrigger.h"
|
|
||||||
|
|
||||||
class AABB;
|
|
||||||
|
|
||||||
class TriggerSystem : public PureSystem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TriggerSystem(EventBroker* eventBroker)
|
|
||||||
: PureSystem(eventBroker, "Trigger")
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual void UpdateComponent(World* world, ComponentWrapper& collision, double dt) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesTouchingTrigger;
|
|
||||||
std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesCompletelyInTrigger;
|
|
||||||
|
|
||||||
//True if leave event was thrown.
|
|
||||||
bool throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& triggerSet, EntityID pId, EntityID tId);
|
|
||||||
template<typename Event>
|
|
||||||
void publish(EntityID pId, EntityID tId)
|
|
||||||
{
|
|
||||||
Event e;
|
|
||||||
e.Trigger = tId;
|
|
||||||
e.Entity = pId;
|
|
||||||
m_EventBroker->Publish(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -5,4 +5,3 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "Core/Util/Logging.h"
|
#include "Core/Util/Logging.h"
|
||||||
#include "Core/Util/IfDebug.h"
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#ifndef AABB_h__
|
|
||||||
#define AABB_h__
|
|
||||||
|
|
||||||
#include "../GLM.h"
|
|
||||||
|
|
||||||
class AABB
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AABB() = default;
|
|
||||||
//No checks are made. Values in minPos must be less than values in maxPos, i.e. min.x < max.x, etc.
|
|
||||||
AABB(const glm::vec3& minPos, const glm::vec3& maxPos);
|
|
||||||
AABB(const glm::vec4& minPos, const glm::vec4& maxPos);
|
|
||||||
//No checks are made. Size must consist of non-negative numbers.
|
|
||||||
virtual void CreateFromCenter(const glm::vec3& center, const glm::vec3& size);
|
|
||||||
virtual ~AABB();
|
|
||||||
|
|
||||||
const glm::vec3& MinCorner() const { return m_MinCorner; }
|
|
||||||
const glm::vec3& MaxCorner() const { return m_MaxCorner; }
|
|
||||||
const glm::vec3& Center() const { return m_Center; }
|
|
||||||
const glm::vec3 Size() const { return 2.0f * m_HalfSize; }
|
|
||||||
const glm::vec3& HalfSize() const { return m_HalfSize; }
|
|
||||||
private:
|
|
||||||
glm::vec3 m_MinCorner;
|
|
||||||
glm::vec3 m_MaxCorner;
|
|
||||||
glm::vec3 m_Center;
|
|
||||||
glm::vec3 m_HalfSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -20,7 +20,7 @@ public:
|
|||||||
~ComponentPoolForwardIterator() = default;
|
~ComponentPoolForwardIterator() = default;
|
||||||
ComponentPoolForwardIterator& operator=(const ComponentPoolForwardIterator& other) = default;
|
ComponentPoolForwardIterator& operator=(const ComponentPoolForwardIterator& other) = default;
|
||||||
ComponentPoolForwardIterator& operator++();
|
ComponentPoolForwardIterator& operator++();
|
||||||
ComponentPoolForwardIterator operator++(int);
|
ComponentPoolForwardIterator& operator++(int);
|
||||||
bool operator!=(const ComponentPoolForwardIterator& other) const;
|
bool operator!=(const ComponentPoolForwardIterator& other) const;
|
||||||
bool operator==(const ComponentPoolForwardIterator& other) const;
|
bool operator==(const ComponentPoolForwardIterator& other) const;
|
||||||
ComponentWrapper operator*() const;
|
ComponentWrapper operator*() const;
|
||||||
@@ -54,8 +54,6 @@ public:
|
|||||||
ComponentWrapper Allocate(EntityID entity);
|
ComponentWrapper Allocate(EntityID entity);
|
||||||
// Get the component belonging to a specific entity
|
// Get the component belonging to a specific entity
|
||||||
ComponentWrapper GetByEntity(EntityID ent);
|
ComponentWrapper GetByEntity(EntityID ent);
|
||||||
// Returns true if the pool contains a component for the specified entity
|
|
||||||
bool KnowsEntity(EntityID ent);
|
|
||||||
// Delete a component and free its memory
|
// Delete a component and free its memory
|
||||||
void Delete(ComponentWrapper& wrapper);
|
void Delete(ComponentWrapper& wrapper);
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
#ifndef EFileDropped_h__
|
|
||||||
#define EFileDropped_h__
|
|
||||||
|
|
||||||
#include "EventBroker.h"
|
|
||||||
|
|
||||||
namespace Events
|
|
||||||
{
|
|
||||||
|
|
||||||
struct FileDropped : Event
|
|
||||||
{
|
|
||||||
std::string Path;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#ifndef Events_KeyboardChar_h__
|
|
||||||
#define Events_KeyboardChar_h__
|
|
||||||
|
|
||||||
#include "EventBroker.h"
|
|
||||||
|
|
||||||
namespace Events
|
|
||||||
{
|
|
||||||
|
|
||||||
struct KeyboardChar : Event
|
|
||||||
{
|
|
||||||
double Timestamp = 0.f;
|
|
||||||
unsigned int Char = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#ifndef Events_MouseScroll_h__
|
|
||||||
#define Events_MouseScroll_h__
|
|
||||||
|
|
||||||
#include "EventBroker.h"
|
|
||||||
|
|
||||||
namespace Events
|
|
||||||
{
|
|
||||||
|
|
||||||
struct MouseScroll : Event
|
|
||||||
{
|
|
||||||
double DeltaX;
|
|
||||||
double DeltaY;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#ifndef EPlayerDamage_h__
|
|
||||||
#define EPlayerDamage_h__
|
|
||||||
|
|
||||||
#include "EventBroker.h"
|
|
||||||
#include "../Core/Entity.h"
|
|
||||||
|
|
||||||
namespace Events
|
|
||||||
{
|
|
||||||
|
|
||||||
struct PlayerDamage : Event
|
|
||||||
{
|
|
||||||
double DamageAmount;
|
|
||||||
EntityID PlayerDamagedID;
|
|
||||||
//optional TypeOfDamage
|
|
||||||
std::string TypeOfDamage;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#ifndef EPlayerDeath_h__
|
|
||||||
#define EPlayerDeath_h__
|
|
||||||
|
|
||||||
#include "EventBroker.h"
|
|
||||||
#include "../Core/Entity.h"
|
|
||||||
|
|
||||||
namespace Events
|
|
||||||
{
|
|
||||||
|
|
||||||
struct PlayerDeath : Event
|
|
||||||
{
|
|
||||||
//KilledBy,KilledByWhat is optional for now. It might be used later in the playerlog-system
|
|
||||||
EntityID KilledBy;
|
|
||||||
EntityID PlayerID;
|
|
||||||
std::string KilledByWhat;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#ifndef EPlayerHealthPickup_h__
|
|
||||||
#define EPlayerHealthPickup_h__
|
|
||||||
|
|
||||||
#include "EventBroker.h"
|
|
||||||
#include "../Core/Entity.h"
|
|
||||||
|
|
||||||
namespace Events
|
|
||||||
{
|
|
||||||
|
|
||||||
struct PlayerHealthPickup : Event
|
|
||||||
{
|
|
||||||
double HealthAmount;
|
|
||||||
EntityID PlayerHealedID;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -13,8 +13,6 @@
|
|||||||
relay = decltype(relay)(std::bind(handler, this, std::placeholders::_1)); \
|
relay = decltype(relay)(std::bind(handler, this, std::placeholders::_1)); \
|
||||||
m_EventBroker->Subscribe(relay);
|
m_EventBroker->Subscribe(relay);
|
||||||
|
|
||||||
typedef unsigned int EventID;
|
|
||||||
|
|
||||||
class EventBroker;
|
class EventBroker;
|
||||||
|
|
||||||
class BaseEventRelay
|
class BaseEventRelay
|
||||||
@@ -33,7 +31,6 @@ public:
|
|||||||
virtual bool Receive(const std::shared_ptr<Event> event) = 0;
|
virtual bool Receive(const std::shared_ptr<Event> event) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EventID m_EventID;
|
|
||||||
std::string m_ContextTypeName;
|
std::string m_ContextTypeName;
|
||||||
std::string m_EventTypeName;
|
std::string m_EventTypeName;
|
||||||
EventBroker* m_Broker;
|
EventBroker* m_Broker;
|
||||||
@@ -98,7 +95,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_IsProcessing = false;
|
bool m_IsProcessing = false;
|
||||||
EventID m_NextEventID = 0;
|
|
||||||
|
|
||||||
typedef std::string ContextTypeName_t; // typeid(ContextType).name()
|
typedef std::string ContextTypeName_t; // typeid(ContextType).name()
|
||||||
typedef std::string EventTypeName_t; // typeid(EventType).name()
|
typedef std::string EventTypeName_t; // typeid(EventType).name()
|
||||||
@@ -107,14 +103,14 @@ private:
|
|||||||
typedef std::unordered_map<ContextTypeName_t, EventRelays_t> ContextRelays_t;
|
typedef std::unordered_map<ContextTypeName_t, EventRelays_t> ContextRelays_t;
|
||||||
ContextRelays_t m_ContextRelays;
|
ContextRelays_t m_ContextRelays;
|
||||||
std::vector<BaseEventRelay*> m_RelaysToSubscribe;
|
std::vector<BaseEventRelay*> m_RelaysToSubscribe;
|
||||||
std::vector<std::tuple<EventID, ContextTypeName_t, EventTypeName_t>> m_RelaysToUnsubscribe;
|
std::vector<BaseEventRelay*> m_RelaysToUnsubscribe;
|
||||||
|
|
||||||
typedef std::list<std::pair<EventTypeName_t, std::shared_ptr<Event>>> EventQueue_t;
|
typedef std::list<std::pair<EventTypeName_t, std::shared_ptr<Event>>> EventQueue_t;
|
||||||
std::shared_ptr<EventQueue_t> m_EventQueueRead;
|
std::shared_ptr<EventQueue_t> m_EventQueueRead;
|
||||||
std::shared_ptr<EventQueue_t> m_EventQueueWrite;
|
std::shared_ptr<EventQueue_t> m_EventQueueWrite;
|
||||||
|
|
||||||
void subscribeImmediate(BaseEventRelay& relay);
|
void subscribeImmediate(BaseEventRelay& relay);
|
||||||
void unsubscribeImmediate(std::tuple<EventID, ContextTypeName_t, EventTypeName_t> identifier);
|
void unsubscribeImmediate(BaseEventRelay& relay);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename EventType>
|
template <typename EventType>
|
||||||
|
|||||||
@@ -8,15 +8,12 @@
|
|||||||
#include "EventBroker.h"
|
#include "EventBroker.h"
|
||||||
#include "EKeyDown.h"
|
#include "EKeyDown.h"
|
||||||
#include "EKeyUp.h"
|
#include "EKeyUp.h"
|
||||||
#include "EKeyboardChar.h"
|
|
||||||
#include "EMousePress.h"
|
#include "EMousePress.h"
|
||||||
#include "EMouseRelease.h"
|
#include "EMouseRelease.h"
|
||||||
#include "EMouseMove.h"
|
#include "EMouseMove.h"
|
||||||
#include "EMouseScroll.h"
|
|
||||||
#include "ELockMouse.h"
|
#include "ELockMouse.h"
|
||||||
#include "EGamepadAxis.h"
|
#include "EGamepadAxis.h"
|
||||||
#include "EGamepadButton.h"
|
#include "EGamepadButton.h"
|
||||||
#include "EFileDropped.h"
|
|
||||||
|
|
||||||
class InputManager
|
class InputManager
|
||||||
{
|
{
|
||||||
@@ -36,7 +33,6 @@ public:
|
|||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
|
||||||
static const short MAX_GAMEPADS = 4;
|
|
||||||
|
|
||||||
void Update(double dt);
|
void Update(double dt);
|
||||||
|
|
||||||
@@ -53,12 +49,6 @@ private:
|
|||||||
std::array<int, GLFW_KEY_LAST+1> m_LastKeyState;
|
std::array<int, GLFW_KEY_LAST+1> m_LastKeyState;
|
||||||
std::array<int, GLFW_MOUSE_BUTTON_LAST+1> m_CurrentMouseState;
|
std::array<int, GLFW_MOUSE_BUTTON_LAST+1> m_CurrentMouseState;
|
||||||
std::array<int, GLFW_MOUSE_BUTTON_LAST+1> m_LastMouseState;
|
std::array<int, GLFW_MOUSE_BUTTON_LAST+1> m_LastMouseState;
|
||||||
typedef std::array<float, static_cast<int>(Gamepad::Axis::LAST) + 1> GamepadAxisState;
|
|
||||||
std::array<GamepadAxisState, MAX_GAMEPADS> m_CurrentGamepadAxisState;
|
|
||||||
std::array<GamepadAxisState, MAX_GAMEPADS> m_LastGamepadAxisState;
|
|
||||||
typedef std::array<bool, static_cast<int>(Gamepad::Button::LAST) + 1> GamepadButtonState;
|
|
||||||
std::array<GamepadButtonState, MAX_GAMEPADS> m_CurrentGamepadButtonState;
|
|
||||||
std::array<GamepadButtonState, MAX_GAMEPADS> m_LastGamepadButtonState;
|
|
||||||
|
|
||||||
double m_CurrentMouseX, m_CurrentMouseY;
|
double m_CurrentMouseX, m_CurrentMouseY;
|
||||||
double m_LastMouseX, m_LastMouseY;
|
double m_LastMouseX, m_LastMouseY;
|
||||||
@@ -68,12 +58,10 @@ private:
|
|||||||
void PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis);
|
void PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis);
|
||||||
void PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button);
|
void PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button);
|
||||||
|
|
||||||
static std::vector<unsigned int> GLFWCharCallbackQueue;
|
static void GLFWMouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
|
||||||
static void GLFWCharCallback(GLFWwindow* window, unsigned int c);
|
{
|
||||||
static std::vector<std::pair<double, double>> GLFWScrollCallbackQueue;
|
LOG_DEBUG("Click! %i %i %i", button, action, mods);
|
||||||
static void GLFWScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
}
|
||||||
static std::vector<std::string> GLFWDropCallbackQueue;
|
|
||||||
static void GLFWDropCallback(GLFWwindow* window, int count, const char* paths[]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Postfix increment i.e. iter++. Prefer pre-increment (++iter) for efficiency.
|
//Postfix increment i.e. iter++. Prefer pre-increment (++iter) for efficiency.
|
||||||
MemoryPoolForwardIterator operator++(int)
|
MemoryPoolForwardIterator& operator++(int)
|
||||||
{
|
{
|
||||||
MemoryPoolForwardIterator<T> copyIter(*this);
|
MemoryPoolForwardIterator<T> copyIter(*this);
|
||||||
operator++();
|
operator++();
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
#ifndef OctTree_h__
|
|
||||||
#define OctTree_h__
|
|
||||||
|
|
||||||
#include "Core/AABB.h"
|
|
||||||
|
|
||||||
class Ray;
|
|
||||||
|
|
||||||
class OctTree
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct Output
|
|
||||||
{
|
|
||||||
float CollideDistance;
|
|
||||||
};
|
|
||||||
|
|
||||||
OctTree();
|
|
||||||
~OctTree();
|
|
||||||
//For the root OctTree, [octTreeBounds] should be a box containing the entire level.
|
|
||||||
OctTree(const AABB& octTreeBounds, int subDivisions);
|
|
||||||
|
|
||||||
//We cannot copy the OctTree as of now, because of the recursive dynamic allocation.
|
|
||||||
//Define these if the OctTree suddenly needs to be copied, think of the children OctChild* ptrs.
|
|
||||||
OctTree(const OctTree& other) = delete;
|
|
||||||
OctTree(const OctTree&& other) = delete;
|
|
||||||
OctTree& operator= (const OctTree& other) = delete;
|
|
||||||
//Add a dynamic object (one that moves around) into the tree.
|
|
||||||
void AddDynamicObject(const AABB& box);
|
|
||||||
//Add a static object (that does not move) into the tree.
|
|
||||||
void AddStaticObject(const AABB& box);
|
|
||||||
//Get the boxes that are in the same area as the input [box], the boxes are put in [outBoxes].
|
|
||||||
void BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes);
|
|
||||||
//Empty the tree of all objects, static and dynamic.
|
|
||||||
void ClearObjects();
|
|
||||||
//Empty the tree of all dynamic objects. Static objects remain in the tree.
|
|
||||||
void ClearDynamicObjects();
|
|
||||||
|
|
||||||
//Returns true if the ray collides with something in the tree. Result is written to [data].
|
|
||||||
bool RayCollides(const Ray& ray, Output& data);
|
|
||||||
//Returns true if the box collides with something in the tree.
|
|
||||||
//On collision with a box, that box is written to [outBoxIntersected].
|
|
||||||
//Note: More efficient than calling BoxesInSameRegion from outside and testing there.
|
|
||||||
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct OctChild; //Fwd declaration;
|
|
||||||
struct ContainedObject
|
|
||||||
{
|
|
||||||
ContainedObject()
|
|
||||||
: Box(AABB())
|
|
||||||
, Checked(false)
|
|
||||||
{}
|
|
||||||
ContainedObject(AABB box)
|
|
||||||
: Box(box)
|
|
||||||
, Checked(false)
|
|
||||||
{}
|
|
||||||
AABB Box;
|
|
||||||
bool Checked;
|
|
||||||
};
|
|
||||||
OctChild* m_Root;
|
|
||||||
std::vector<ContainedObject> m_StaticObjects;
|
|
||||||
std::vector<ContainedObject> m_DynamicObjects;
|
|
||||||
|
|
||||||
bool m_UpdatedOnce;
|
|
||||||
unsigned int m_BoxID;
|
|
||||||
glm::vec3 m_PrevPos;
|
|
||||||
glm::quat m_PrevOri;
|
|
||||||
|
|
||||||
void falsifyObjectChecks();
|
|
||||||
|
|
||||||
struct OctChild
|
|
||||||
{
|
|
||||||
~OctChild();
|
|
||||||
OctChild(const AABB& octTreeBounds,
|
|
||||||
int subDivisions,
|
|
||||||
std::vector<OctTree::ContainedObject>& staticObjects,
|
|
||||||
std::vector<OctTree::ContainedObject>& dynamicObjects);
|
|
||||||
OctChild(const OctChild& other) = delete;
|
|
||||||
OctChild(const OctChild&& other) = delete;
|
|
||||||
OctChild& operator= (const OctChild& other) = delete;
|
|
||||||
void AddDynamicObject(const AABB& box);
|
|
||||||
void AddStaticObject(const AABB& box);
|
|
||||||
void BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes) const;
|
|
||||||
void ClearObjects();
|
|
||||||
void ClearDynamicObjects();
|
|
||||||
bool RayCollides(const Ray& ray, Output& data) const;
|
|
||||||
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const;
|
|
||||||
|
|
||||||
OctChild* m_Children[8];
|
|
||||||
//Indices into the lists in OctTree.
|
|
||||||
std::vector<int> m_StaticObjIndices;
|
|
||||||
std::vector<int> m_DynamicObjIndices;
|
|
||||||
AABB m_Box;
|
|
||||||
//Reference to the lists in OctTree.
|
|
||||||
std::vector<OctTree::ContainedObject>& m_StaticObjectsRef;
|
|
||||||
std::vector<OctTree::ContainedObject>& m_DynamicObjectsRef;
|
|
||||||
|
|
||||||
inline bool hasChildren() const;
|
|
||||||
int childIndexContainingPoint(const glm::vec3& point) const;
|
|
||||||
std::vector<int> childIndicesContainingBox(const AABB& box) const;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#ifndef Ray_h__
|
|
||||||
#define Ray_h__
|
|
||||||
|
|
||||||
#include "../GLM.h"
|
|
||||||
#include "Common.h"
|
|
||||||
|
|
||||||
class Ray
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Ray(const glm::vec3& origin, const glm::vec3& dir)
|
|
||||||
: m_Origin(origin)
|
|
||||||
, m_Direction(glm::normalize(dir))
|
|
||||||
{
|
|
||||||
DEBUG_IF(true) {
|
|
||||||
if (glm::any(glm::isnan(m_Direction))) {
|
|
||||||
LOG_WARNING("Ray Direction was set to the zero-vector, expect unknown side effects and/or crashes.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const glm::vec3& Origin() const { return m_Origin; }
|
|
||||||
const glm::vec3& Direction() const { return m_Direction; }
|
|
||||||
//Sets the ray origin at parameter.
|
|
||||||
void SetOrigin(const glm::vec3& origin) { m_Origin = origin; }
|
|
||||||
//Normalizes the parameter and sets direction to it.
|
|
||||||
void SetDirection(const glm::vec3& direction) { m_Direction = glm::normalize(direction); }
|
|
||||||
private:
|
|
||||||
glm::vec3 m_Origin;
|
|
||||||
glm::vec3 m_Direction;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // Ray_h__
|
|
||||||
@@ -9,42 +9,17 @@ class System
|
|||||||
{
|
{
|
||||||
friend class SystemPipeline;
|
friend class SystemPipeline;
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
System(EventBroker* eventBroker)
|
System(EventBroker* eventBroker, std::string componentType)
|
||||||
: m_EventBroker(eventBroker)
|
: m_EventBroker(eventBroker)
|
||||||
|
, m_ComponentType(componentType)
|
||||||
{ }
|
{ }
|
||||||
virtual ~System() = default;
|
|
||||||
|
|
||||||
|
virtual void Update(World* world, ComponentWrapper& component, double dt) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string m_ComponentType;
|
||||||
EventBroker* m_EventBroker;
|
EventBroker* m_EventBroker;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PureSystem : public System
|
|
||||||
{
|
|
||||||
friend class SystemPipeline;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
PureSystem(EventBroker* eventBroker, std::string componentType)
|
|
||||||
: System(eventBroker)
|
|
||||||
, m_ComponentType(componentType)
|
|
||||||
{ }
|
|
||||||
virtual ~PureSystem() = default;
|
|
||||||
|
|
||||||
const std::string m_ComponentType;
|
|
||||||
|
|
||||||
virtual void UpdateComponent(World* world, ComponentWrapper& component, double dt) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ImpureSystem : public System
|
|
||||||
{
|
|
||||||
friend class SystemPipeline;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ImpureSystem(EventBroker* eventBroker)
|
|
||||||
: System(eventBroker)
|
|
||||||
{ }
|
|
||||||
virtual ~ImpureSystem() = default;
|
|
||||||
|
|
||||||
virtual void Update(World* world, double dt) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -14,76 +14,45 @@ public:
|
|||||||
{ }
|
{ }
|
||||||
~SystemPipeline()
|
~SystemPipeline()
|
||||||
{
|
{
|
||||||
for (UnorderedSystems& group : m_OrderedSystemGroups) {
|
for (auto& pair : m_Systems) {
|
||||||
for (auto& pair : group.Systems) {
|
for (auto& system : pair.second) {
|
||||||
delete pair.second;
|
delete system;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename... Arguments>
|
template <typename T, typename... Arguments>
|
||||||
//All systems with orderlevel 0 will be updated first, then 1, 2, etc.
|
void AddSystem(Arguments... args)
|
||||||
void AddSystem(int updateOrderLevel, Arguments... args)
|
|
||||||
{
|
{
|
||||||
if (updateOrderLevel + 1 > m_OrderedSystemGroups.size()) {
|
|
||||||
m_OrderedSystemGroups.resize(updateOrderLevel + 1);
|
|
||||||
}
|
|
||||||
UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel];
|
|
||||||
System* system = new T(m_EventBroker, args...);
|
System* system = new T(m_EventBroker, args...);
|
||||||
group.Systems[typeid(T).name()] = system;
|
if (!system->m_ComponentType.empty()) {
|
||||||
|
m_Systems[system->m_ComponentType].push_back(system);
|
||||||
if (std::is_base_of<PureSystem, T>::value) {
|
} else {
|
||||||
PureSystem* pureSystem = static_cast<PureSystem*>(system);
|
LOG_ERROR("Failed to add system \"%s\": Missing component type!", typeid(T).name());
|
||||||
if (!pureSystem->m_ComponentType.empty()) {
|
delete system;
|
||||||
group.PureSystems[pureSystem->m_ComponentType].push_back(pureSystem);
|
|
||||||
} else {
|
|
||||||
LOG_ERROR("Failed to add pure system \"%s\": Missing component type!", typeid(T).name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std::is_base_of<ImpureSystem, T>::value) {
|
|
||||||
ImpureSystem* impureSystem = static_cast<ImpureSystem*>(system);
|
|
||||||
group.ImpureSystems.push_back(impureSystem);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update(World* world, double dt)
|
void Update(World* world, double dt)
|
||||||
{
|
{
|
||||||
for (UnorderedSystems& group : m_OrderedSystemGroups) {
|
for (auto& pair : m_Systems) {
|
||||||
// Process events
|
const std::string& componentName = pair.first;
|
||||||
for (auto& pair : group.Systems) {
|
auto& systems = pair.second;
|
||||||
m_EventBroker->Process(pair.first);
|
const ComponentPool* pool = world->GetComponents(componentName);
|
||||||
|
if (pool == nullptr) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
for (auto& component : *pool) {
|
||||||
// Update
|
for (auto& system : systems) {
|
||||||
for (auto& pair : group.PureSystems) {
|
system->Update(world, component, dt);
|
||||||
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->UpdateComponent(world, component, dt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (auto& system : group.ImpureSystems) {
|
|
||||||
system->Update(world, dt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EventBroker* m_EventBroker;
|
EventBroker* m_EventBroker;
|
||||||
struct UnorderedSystems
|
std::unordered_map<std::string, std::vector<System*>> m_Systems;
|
||||||
{
|
|
||||||
std::map<std::string, System*> Systems;
|
|
||||||
std::map<std::string, std::vector<PureSystem*>> PureSystems;
|
|
||||||
std::vector<ImpureSystem*> ImpureSystems;
|
|
||||||
};
|
|
||||||
std::vector<UnorderedSystems> m_OrderedSystemGroups;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
// Example:
|
|
||||||
// DEBUG_IF(condition) {
|
|
||||||
// // This code is executed only in debug mode and if condition is true.
|
|
||||||
// }
|
|
||||||
// NOTE: condition statement is not executed at all in release mode.
|
|
||||||
#ifndef DEBUG_IF
|
|
||||||
#ifndef DEBUG
|
|
||||||
#define DEBUG_IF(c) if(c)
|
|
||||||
#else
|
|
||||||
#define DEBUG_IF(c) if(false)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -14,35 +14,22 @@ public:
|
|||||||
|
|
||||||
// Create empty entity
|
// Create empty entity
|
||||||
EntityID CreateEntity(EntityID parent = 0);
|
EntityID CreateEntity(EntityID parent = 0);
|
||||||
// Delete entity and all components within
|
|
||||||
void DeleteEntity(EntityID entity);
|
|
||||||
|
|
||||||
// Register a component type and allocate space for it
|
// Register a component type and allocate space for it
|
||||||
void RegisterComponent(ComponentInfo& ci);
|
void RegisterComponent(ComponentInfo& ci);
|
||||||
// Attach a component to an entity and fill it with default values
|
// Attach a component to an entity and fill it with default values
|
||||||
ComponentWrapper AttachComponent(EntityID entity, std::string componentType);
|
ComponentWrapper AttachComponent(EntityID entity, std::string componentType);
|
||||||
// Check if an entity has a component
|
|
||||||
bool HasComponent(EntityID entity, std::string componentType);
|
|
||||||
// Get a component of an entity
|
// Get a component of an entity
|
||||||
ComponentWrapper GetComponent(EntityID entity, std::string componentType);
|
ComponentWrapper GetComponent(EntityID entity, std::string componentType);
|
||||||
// Delete a component off an entity
|
|
||||||
void DeleteComponent(EntityID entity, std::string componentType);
|
|
||||||
// Get all components of the specified type
|
// Get all components of the specified type
|
||||||
const ComponentPool* GetComponents(std::string componentType);
|
const ComponentPool* GetComponents(std::string componentType);
|
||||||
// Get entity parent
|
// Get entity parent
|
||||||
EntityID GetParent(EntityID entity);
|
EntityID GetParent(EntityID entity);
|
||||||
// Change the parent of an entity
|
|
||||||
void SetParent(EntityID entity, EntityID parent);
|
|
||||||
// Get all component pools
|
|
||||||
const std::unordered_map<std::string, ComponentPool*>& GetComponentPools() const { return m_ComponentPools; }
|
|
||||||
// Get the entity children map
|
|
||||||
const std::unordered_multimap<EntityID, EntityID>& GetEntityChildren() const { return m_EntityChildren; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EntityID m_CurrentEntityID = 1;
|
EntityID m_CurrentEntityID = 1;
|
||||||
|
|
||||||
std::unordered_map<EntityID, EntityID> m_EntityParents;
|
std::unordered_map<EntityID, EntityID> m_EntityParents;
|
||||||
// TODO: This should be a more effective structure
|
|
||||||
std::unordered_multimap<EntityID, EntityID> m_EntityChildren;
|
std::unordered_multimap<EntityID, EntityID> m_EntityChildren;
|
||||||
std::unordered_map<std::string, ComponentPool*> m_ComponentPools;
|
std::unordered_map<std::string, ComponentPool*> m_ComponentPools;
|
||||||
|
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
#include <imgui/imgui.h>
|
|
||||||
#include <glm/gtx/common.hpp>
|
|
||||||
#include <boost/filesystem/path.hpp>
|
|
||||||
#include "../Core/System.h"
|
|
||||||
#include "../Core/EMousePress.h"
|
|
||||||
#include "../Core/EMouseRelease.h"
|
|
||||||
#include "../Core/EMouseMove.h"
|
|
||||||
#include "../Core/ConfigFile.h"
|
|
||||||
#include "../Input/EInputCommand.h"
|
|
||||||
#include "../Rendering/IRenderer.h"
|
|
||||||
#include "../Rendering/EPicking.h"
|
|
||||||
#include "../Core/EFileDropped.h"
|
|
||||||
#include "../Rendering/RenderQueueFactory.h"
|
|
||||||
|
|
||||||
class EditorSystem : public ImpureSystem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
EditorSystem(EventBroker* eventBroker, IRenderer* renderer);
|
|
||||||
|
|
||||||
virtual void Update(World* world, double dt) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
IRenderer* m_Renderer;
|
|
||||||
World* m_World = nullptr;
|
|
||||||
|
|
||||||
bool m_Enabled;
|
|
||||||
bool m_Visible;
|
|
||||||
std::vector<glm::vec2> m_PickingQueue;
|
|
||||||
|
|
||||||
enum class WidgetMode
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Translate,
|
|
||||||
Rotate,
|
|
||||||
Scale
|
|
||||||
} m_WidgetMode = WidgetMode::None;
|
|
||||||
|
|
||||||
enum class WidgetSpace
|
|
||||||
{
|
|
||||||
Local,
|
|
||||||
Global
|
|
||||||
} m_WidgetSpace = WidgetSpace::Global;
|
|
||||||
|
|
||||||
EntityID m_Widget = 0;
|
|
||||||
EntityID m_WidgetX = 0;
|
|
||||||
EntityID m_WidgetPlaneX = 0;
|
|
||||||
EntityID m_WidgetY = 0;
|
|
||||||
EntityID m_WidgetPlaneY = 0;
|
|
||||||
EntityID m_WidgetZ = 0;
|
|
||||||
EntityID m_WidgetPlaneZ = 0;
|
|
||||||
EntityID m_WidgetOrigin = 0;
|
|
||||||
glm::vec3 m_WidgetCurrentAxis;
|
|
||||||
float m_WidgetPickingDepth = 0.f;
|
|
||||||
|
|
||||||
EntityID m_Selection = 0;
|
|
||||||
EntityID m_LastSelection = 0;
|
|
||||||
glm::vec3 m_Position;
|
|
||||||
std::string m_LastDroppedFile;
|
|
||||||
|
|
||||||
EventRelay<EditorSystem, Events::InputCommand> m_EInputCommand;
|
|
||||||
bool OnInputCommand(const Events::InputCommand& e);
|
|
||||||
EventRelay<EditorSystem, Events::MouseRelease> m_EMouseRelease;
|
|
||||||
bool OnMouseRelease(const Events::MouseRelease& e);
|
|
||||||
EventRelay<EditorSystem, Events::MousePress> m_EMousePress;
|
|
||||||
bool OnMousePress(const Events::MousePress& e);
|
|
||||||
EventRelay<EditorSystem, Events::MouseMove> m_EMouseMove;
|
|
||||||
bool OnMouseMove(const Events::MouseMove& e);
|
|
||||||
EventRelay<EditorSystem, Events::Picking> m_EPicking;
|
|
||||||
bool OnPicking(const Events::Picking& e);
|
|
||||||
EventRelay<EditorSystem, Events::FileDropped> m_EFileDropped;
|
|
||||||
bool OnFileDropped(const Events::FileDropped& e);
|
|
||||||
|
|
||||||
void updateWidget();
|
|
||||||
void setWidgetMode(WidgetMode newMode);
|
|
||||||
void setWidgetSpace(WidgetSpace space);
|
|
||||||
void drawUI(World* world, double dt);
|
|
||||||
bool createDeleteButton(std::string componentType);
|
|
||||||
void changeParent(EntityID entity, EntityID newParent);
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef XboxControllerInputHandler_h__
|
||||||
|
#define XboxControllerInputHandler_h__
|
||||||
|
|
||||||
|
#include "InputHandler.h"
|
||||||
|
#include "Core/EKeyDown.h"
|
||||||
|
#include "Core/EKeyUp.h"
|
||||||
|
|
||||||
|
struct _XINPUT_STATE;
|
||||||
|
typedef _XINPUT_STATE XINPUT_STATE;
|
||||||
|
|
||||||
|
class XboxControllerInputHandler : public InputHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XboxControllerInputHandler(EventBroker* eventBroker, InputProxy* inputProxy);
|
||||||
|
|
||||||
|
|
||||||
|
bool BindOrigin(std::string origin, std::string command, float value) override;
|
||||||
|
|
||||||
|
void Update(double dt) override;
|
||||||
|
|
||||||
|
virtual float GetCommandValue(std::string command) override;
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, int> m_OriginButtons;
|
||||||
|
std::unordered_map<std::string, int> m_OriginAxes;
|
||||||
|
std::unordered_map<int, std::tuple<std::string, float>> m_ButtonBindings; // GLFW_KEY... -> command string & value
|
||||||
|
std::unordered_map<int, std::tuple<std::string, float>> m_AxisBindings; // GLFW_KEY... -> command string & value
|
||||||
|
std::unordered_map<std::string, float> m_CommandValues;
|
||||||
|
|
||||||
|
static const short MAX_GAMEPADS = 4;
|
||||||
|
|
||||||
|
float getAxisValue(XINPUT_STATE& state, int axis);
|
||||||
|
//typedef std::array<float, static_cast<int>(Gamepad::Axis::LAST) + 1> GamepadAxisState;
|
||||||
|
//std::array<GamepadAxisState, MAX_GAMEPADS> m_CurrentGamepadAxisState;
|
||||||
|
//std::array<GamepadAxisState, MAX_GAMEPADS> m_LastGamepadAxisState;
|
||||||
|
//typedef std::array<bool, static_cast<int>(Gamepad::Button::LAST) + 1> GamepadButtonState;
|
||||||
|
//std::array<GamepadButtonState, MAX_GAMEPADS> m_CurrentGamepadButtonState;
|
||||||
|
//std::array<GamepadButtonState, MAX_GAMEPADS> m_LastGamepadButtonState;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,84 +1,14 @@
|
|||||||
#ifndef Client_h__
|
#ifndef Client_h__
|
||||||
#define Client_h__
|
#define Client_h__
|
||||||
|
|
||||||
#include <string>
|
#include <boost\asio.hpp>
|
||||||
#include <ctime>
|
|
||||||
|
|
||||||
#include <glm/common.hpp>
|
class Client
|
||||||
#include <boost/asio.hpp>
|
|
||||||
|
|
||||||
#include "Network/Network.h"
|
|
||||||
#include "Network/MessageType.h"
|
|
||||||
#include "Network/PlayerDefinition.h"
|
|
||||||
#include "Network/SnapshotDefinitions.h"
|
|
||||||
#include "Core/World.h"
|
|
||||||
#include "Core/EventBroker.h"
|
|
||||||
#include "Core/ConfigFile.h"
|
|
||||||
#include "Input/EInputCommand.h"
|
|
||||||
|
|
||||||
class Client : public Network
|
|
||||||
{
|
{
|
||||||
public:
|
Client();
|
||||||
Client(ConfigFile* config);
|
~Client();
|
||||||
~Client();
|
|
||||||
void Start(World* world, EventBroker* eventBroker) override;
|
|
||||||
void Update() override;
|
|
||||||
void Close();
|
|
||||||
private:
|
|
||||||
// Assio UDP logic
|
|
||||||
boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
|
|
||||||
boost::asio::io_service m_IOService;
|
|
||||||
boost::asio::ip::udp::socket m_Socket;
|
|
||||||
|
|
||||||
// Sending message to server logic
|
|
||||||
int bytesRead = -1;
|
|
||||||
char readBuf[1024] = { 0 };
|
|
||||||
int snapshotInterval = 33;
|
|
||||||
std::clock_t previousSnapshotMessage = std::clock();
|
|
||||||
|
|
||||||
// Packet loss logic
|
|
||||||
unsigned int m_PacketID = 0;
|
|
||||||
unsigned int m_PreviousPacketID = 0;
|
|
||||||
unsigned int m_SendPacketID = 0;
|
|
||||||
|
|
||||||
// Game logic
|
|
||||||
World* m_World;
|
|
||||||
std::string m_PlayerName;
|
|
||||||
int m_PlayerID = -1;
|
|
||||||
|
|
||||||
// Network logic
|
|
||||||
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
|
|
||||||
SnapshotDefinitions m_NextSnapshot;
|
|
||||||
bool m_ThreadIsRunning = true;
|
|
||||||
double m_DurationOfPingTime;
|
|
||||||
std::clock_t m_StartPingTime;
|
|
||||||
// Use to check if we should send disconnect message
|
|
||||||
// if game is turned of by closing window.
|
|
||||||
bool m_WasStarted = false;
|
|
||||||
|
|
||||||
// Private member functions
|
|
||||||
void readFromServer();
|
|
||||||
void sendSnapshotToServer();
|
|
||||||
int receive(char* data, size_t length);
|
|
||||||
void send(Packet& packet);
|
|
||||||
void connect();
|
|
||||||
void disconnect();
|
|
||||||
void ping();
|
|
||||||
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
|
|
||||||
void parseMessageType(Packet& packet);
|
|
||||||
void parseEventMessage(Packet& packet);
|
|
||||||
void parseConnect(Packet& packet);
|
|
||||||
void parsePing();
|
|
||||||
void parseServerPing();
|
|
||||||
void parseSnapshot(Packet& packet);
|
|
||||||
void identifyPacketLoss();
|
|
||||||
bool isConnected();
|
|
||||||
EntityID createPlayer();
|
|
||||||
|
|
||||||
// Events
|
|
||||||
EventBroker* m_EventBroker;
|
|
||||||
EventRelay<Client, Events::InputCommand> m_EInputCommand;
|
|
||||||
bool OnInputCommand(const Events::InputCommand &e);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
#ifndef MessageType_h__
|
|
||||||
#define MessageType_h__
|
|
||||||
|
|
||||||
// Message types used by both server and client.
|
|
||||||
// Used to determine what type of message was sent.
|
|
||||||
enum class MessageType
|
|
||||||
{
|
|
||||||
Connect,
|
|
||||||
Disconnect,
|
|
||||||
ClientPing,
|
|
||||||
ServerPing,
|
|
||||||
Message,
|
|
||||||
Snapshot,
|
|
||||||
Event,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#ifndef Network_h__
|
|
||||||
#define Network_h__
|
|
||||||
|
|
||||||
#include "Core/World.h"
|
|
||||||
#include "Core/EventBroker.h"
|
|
||||||
#include "Network/Packet.h"
|
|
||||||
|
|
||||||
#define MAXCONNECTIONS 8
|
|
||||||
#define INPUTSIZE 128
|
|
||||||
|
|
||||||
class Network
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~Network() { };
|
|
||||||
virtual void Start(World* m_world, EventBroker *eventBroker) = 0;
|
|
||||||
virtual void Update() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
#ifndef Packet_h__
|
|
||||||
#define Packet_h__
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "Network/MessageType.h"
|
|
||||||
#include "Core/Util/Logging.h"
|
|
||||||
|
|
||||||
// Defines the
|
|
||||||
class Packet
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// arg1: Type of message (Connect, Disconnect...)
|
|
||||||
// arg2: PacketID for identifying packet loss.
|
|
||||||
Packet(MessageType type, unsigned int& packetID);
|
|
||||||
// Used to create packet from already existing data buffer.
|
|
||||||
Packet(char* data, const int sizeOfPacket);
|
|
||||||
|
|
||||||
~Packet();
|
|
||||||
// Add primitive types like int, float, char...
|
|
||||||
template<typename T>
|
|
||||||
void WritePrimitive(T val)
|
|
||||||
{
|
|
||||||
// Check if we are trying to add more than the package can fit.
|
|
||||||
if (m_MaxPacketSize < m_Offset + sizeof(T)) {
|
|
||||||
LOG_WARNING("Packet AddPrimitive(): You are trying to add more than we have allocated for!");
|
|
||||||
}
|
|
||||||
memcpy(m_Data + m_Offset, &val, sizeof(T));
|
|
||||||
m_Offset += sizeof(T);
|
|
||||||
}
|
|
||||||
// Pops the first element as if it was a primitive.
|
|
||||||
template<typename T>
|
|
||||||
T ReadPrimitive()
|
|
||||||
{
|
|
||||||
if (m_Offset < m_ReturnDataOffset + sizeof(T)) {
|
|
||||||
LOG_WARNING("Packet PopFrontPrimitive(): You are trying to remove more than what exists in this packet!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
T returnValue;
|
|
||||||
memcpy(&returnValue, m_Data + m_ReturnDataOffset, sizeof(T));
|
|
||||||
m_ReturnDataOffset += sizeof(T);
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
// Add a string to the message
|
|
||||||
void WriteString(std::string str);
|
|
||||||
// Add data to the message
|
|
||||||
void WriteData(char* data, int sizeOfData);
|
|
||||||
// Pops the first element as if it was a string.
|
|
||||||
std::string ReadString();
|
|
||||||
char* ReadData(int SizeOfData);
|
|
||||||
|
|
||||||
int Size() { return m_Offset; };
|
|
||||||
char* Data() { return m_Data; };
|
|
||||||
|
|
||||||
private:
|
|
||||||
char* m_Data;
|
|
||||||
unsigned int m_ReturnDataOffset = 0;
|
|
||||||
int m_Offset = 0;
|
|
||||||
unsigned int m_MaxPacketSize = 128;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#ifndef PlayerDefinition_h__
|
|
||||||
#define PlayerDefinition_h__
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
struct PlayerDefinition {
|
|
||||||
int EntityID = -1;
|
|
||||||
std::string Name = "";
|
|
||||||
boost::asio::ip::udp::endpoint Endpoint;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,85 +1,12 @@
|
|||||||
#ifndef Server_h__
|
#ifndef Server_h__
|
||||||
#define Server_h__
|
#define Server_h__
|
||||||
|
|
||||||
#include <string>
|
#include <boost\asio.hpp>
|
||||||
#include <ctime>
|
|
||||||
|
|
||||||
#include <glm/common.hpp>
|
class Server
|
||||||
#include <boost/asio/ip/udp.hpp>
|
|
||||||
|
|
||||||
#include "Network/MessageType.h"
|
|
||||||
#include "Network/PlayerDefinition.h"
|
|
||||||
#include "Core/World.h"
|
|
||||||
#include "Core/EventBroker.h"
|
|
||||||
#include "Network/Network.h"
|
|
||||||
|
|
||||||
class Server : public Network
|
|
||||||
{
|
{
|
||||||
public:
|
Server();
|
||||||
Server();
|
~Server();
|
||||||
~Server();
|
|
||||||
void Start(World* m_world, EventBroker *eventBroker) override;
|
|
||||||
void Update() override;
|
|
||||||
void Close();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// UDP logic
|
|
||||||
boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
|
|
||||||
boost::asio::io_service m_IOService;
|
|
||||||
boost::asio::ip::udp::socket m_Socket;
|
|
||||||
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
|
|
||||||
|
|
||||||
// Sending messages to client logic
|
|
||||||
char readBuffer[1024] = { 0 };
|
|
||||||
int bytesRead = 0;
|
|
||||||
// time for previouse message
|
|
||||||
std::clock_t previousePingMessage = std::clock();
|
|
||||||
std::clock_t previousSnapshotMessage = std::clock();
|
|
||||||
std::clock_t timOutTimer = std::clock();
|
|
||||||
// How often we send messages (milliseconds)
|
|
||||||
int intervalMs = 1000;
|
|
||||||
int snapshotInterval = 50;
|
|
||||||
int checkTimeOutInterval = 100;
|
|
||||||
|
|
||||||
//Timers
|
|
||||||
std::clock_t m_StartPingTime;
|
|
||||||
std::clock_t m_StopTimes[8];
|
|
||||||
|
|
||||||
// Game logic
|
|
||||||
World* m_World;
|
|
||||||
EventBroker* m_EventBroker;
|
|
||||||
// vec.size() = ammount of players to create, stores playerID's
|
|
||||||
std::vector<unsigned int> m_PlayersToCreate;
|
|
||||||
|
|
||||||
// Packet loss logic
|
|
||||||
unsigned int m_PacketID;
|
|
||||||
unsigned int m_PreviousPacketID;
|
|
||||||
unsigned int m_SendPacketID;
|
|
||||||
|
|
||||||
// Close logic
|
|
||||||
bool m_ThreadIsRunning = true;
|
|
||||||
|
|
||||||
// Private member functions
|
|
||||||
int receive(char* data, size_t length);
|
|
||||||
void readFromClients();
|
|
||||||
void send(Packet& packet, int playerID);
|
|
||||||
void send(Packet& packet);
|
|
||||||
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
|
|
||||||
void broadcast(std::string message);
|
|
||||||
void broadcast(Packet& packet);
|
|
||||||
void sendSnapshot();
|
|
||||||
void sendPing();
|
|
||||||
void checkForTimeOuts();
|
|
||||||
void disconnect(int i);
|
|
||||||
void parseMessageType(Packet& packet);
|
|
||||||
void parseEvent(Packet& packet);
|
|
||||||
void parseConnect(Packet& packet);
|
|
||||||
void parseDisconnect();
|
|
||||||
void parseClientPing();
|
|
||||||
void parseServerPing();
|
|
||||||
void parseSnapshot(Packet& packet);
|
|
||||||
void identifyPacketLoss();
|
|
||||||
EntityID createPlayer();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
#ifndef SnapshotDefinitions_h__
|
|
||||||
#define SnapshotDefinitions_h__
|
|
||||||
|
|
||||||
struct SnapshotDefinitions
|
|
||||||
{
|
|
||||||
// "+Forward" is 8 characters * sizeof(char) = 8
|
|
||||||
std::string InputForward;
|
|
||||||
// "+Right" is 6 characters * sizeof(char) = 6
|
|
||||||
std::string InputRight;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
#include <imgui/imgui.h>
|
|
||||||
#include "../Input/FirstPersonInputController.h"
|
#include "../Input/FirstPersonInputController.h"
|
||||||
|
|
||||||
template <typename EventContext>
|
template <typename EventContext>
|
||||||
@@ -14,35 +13,22 @@ public:
|
|||||||
|
|
||||||
virtual bool OnCommand(const Events::InputCommand& e) override
|
virtual bool OnCommand(const Events::InputCommand& e) override
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
|
|
||||||
if (e.Command == "PrimaryFire") {
|
if (e.Command == "PrimaryFire") {
|
||||||
if (e.Value > 0) {
|
if (e.Value > 0) {
|
||||||
if (!io.WantCaptureMouse) {
|
LockMouse();
|
||||||
LockMouse();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
UnlockMouse();
|
UnlockMouse();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!io.WantCaptureKeyboard) {
|
if (e.Command == "Right") {
|
||||||
if (e.Command == "Right") {
|
float value = std::max(-1.f, std::min(e.Value, 1.f));
|
||||||
float value = std::max(-1.f, std::min(e.Value, 1.f));
|
m_Velocity.x = value;
|
||||||
m_Velocity.x = value;
|
}
|
||||||
}
|
if (e.Command == "Forward") {
|
||||||
if (e.Command == "Forward") {
|
float value = std::max(-1.f, std::min(e.Value, 1.f));
|
||||||
float value = std::max(-1.f, std::min(e.Value, 1.f));
|
m_Velocity.z = -value;
|
||||||
m_Velocity.z = -value;
|
|
||||||
}
|
|
||||||
if (e.Command == "Sprint") {
|
|
||||||
if (e.Value > 0.f) {
|
|
||||||
m_Speed = m_BaseSpeed * 2.f * (e.Value);
|
|
||||||
} else {
|
|
||||||
m_Speed = m_BaseSpeed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FirstPersonInputController::OnCommand(e);
|
return FirstPersonInputController::OnCommand(e);
|
||||||
@@ -51,7 +37,7 @@ public:
|
|||||||
void Update(double dt)
|
void Update(double dt)
|
||||||
{
|
{
|
||||||
if (glm::length2(m_Velocity) > 0) {
|
if (glm::length2(m_Velocity) > 0) {
|
||||||
m_Position += m_Orientation * (glm::normalize(m_Velocity) * m_Speed * (float)dt);
|
m_Position += (m_Orientation * (m_Velocity * m_BaseSpeed)) * (float)dt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,5 +45,4 @@ protected:
|
|||||||
glm::vec3 m_Position = glm::vec3(0, 0, 0);
|
glm::vec3 m_Position = glm::vec3(0, 0, 0);
|
||||||
glm::vec3 m_Velocity = glm::vec3(0, 0, 0);
|
glm::vec3 m_Velocity = glm::vec3(0, 0, 0);
|
||||||
float m_BaseSpeed = 2.0f;
|
float m_BaseSpeed = 2.0f;
|
||||||
float m_Speed = m_BaseSpeed;
|
|
||||||
};
|
};
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#ifndef DrawScenePass_h__
|
|
||||||
#define DrawScenePass_h__
|
|
||||||
|
|
||||||
#include "IRenderer.h"
|
|
||||||
#include "DrawScenePassState.h"
|
|
||||||
#include "FrameBuffer.h"
|
|
||||||
#include "ShaderProgram.h"
|
|
||||||
#include "Util/UnorderedMapVec2.h"
|
|
||||||
#include "Texture.h"
|
|
||||||
|
|
||||||
class DrawScenePass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DrawScenePass(IRenderer* renderer);
|
|
||||||
~DrawScenePass() { }
|
|
||||||
void InitializeTextures();
|
|
||||||
void InitializeFrameBuffers();
|
|
||||||
void InitializeShaderPrograms();
|
|
||||||
|
|
||||||
void Draw(RenderQueueCollection& rq);
|
|
||||||
|
|
||||||
//Getters
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
|
|
||||||
|
|
||||||
Texture* m_WhiteTexture;
|
|
||||||
|
|
||||||
const IRenderer* m_Renderer;
|
|
||||||
|
|
||||||
ShaderProgram* m_BasicForwardProgram;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#ifndef DrawScenePassState_h__
|
|
||||||
#define DrawScenePassState_h__
|
|
||||||
|
|
||||||
#include "Rendering/RenderState.h"
|
|
||||||
|
|
||||||
class DrawScenePassState : public RenderState
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DrawScenePassState();
|
|
||||||
~DrawScenePassState();
|
|
||||||
private:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -34,26 +34,21 @@ public:
|
|||||||
EntityID Entity;
|
EntityID Entity;
|
||||||
//World position of the "pick"
|
//World position of the "pick"
|
||||||
glm::vec3 Position;
|
glm::vec3 Position;
|
||||||
// Depth
|
|
||||||
float Depth;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PickData Pick(glm::vec2 screenCoord) const
|
PickData Pick(glm::vec2 screenCoord) const
|
||||||
{
|
{
|
||||||
PickData pickData;
|
PickData pickData;
|
||||||
|
|
||||||
// Invert screen y coordinate
|
|
||||||
screenCoord.y = Resolution.Height - screenCoord.y;
|
|
||||||
ScreenCoords::PixelData data = ScreenCoords::ToPixelData(screenCoord, PickingBuffer, *DepthBuffer);
|
ScreenCoords::PixelData data = ScreenCoords::ToPixelData(screenCoord, PickingBuffer, *DepthBuffer);
|
||||||
pickData.Depth = data.Depth;
|
|
||||||
|
|
||||||
auto it = PickingColorsToEntity->find(glm::vec2(data.Color[0], data.Color[1]));
|
auto it = PickingColorsToEntity->find(glm::vec2(data.Color[0], data.Color[1]));
|
||||||
if (it != PickingColorsToEntity->end()) {
|
if (it != PickingColorsToEntity->end()) {
|
||||||
pickData.Entity = it->second;
|
pickData.Entity = it->second;
|
||||||
} else {
|
} else {
|
||||||
pickData.Entity = 0;
|
pickData.Entity = -1;
|
||||||
}
|
}
|
||||||
pickData.Position = ScreenCoords::ToWorldPos(screenCoord.x, screenCoord.y, data.Depth, Resolution, ProjectionMatrix, ViewMatrix);
|
pickData.Position = ScreenCoords::ToWorldPos(screenCoord.x, Resolution.Width - screenCoord.y, data.Depth, Resolution, ProjectionMatrix, ViewMatrix);
|
||||||
|
|
||||||
return pickData;
|
return pickData;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public:
|
|||||||
virtual void Draw(RenderQueueCollection& rq) = 0;
|
virtual void Draw(RenderQueueCollection& rq) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Rectangle m_Resolution = Rectangle::Rectangle(1280, 720);
|
Rectangle m_Resolution = Rectangle(1280, 720);
|
||||||
bool m_Fullscreen = false;
|
bool m_Fullscreen = false;
|
||||||
bool m_VSYNC = false;
|
bool m_VSYNC = false;
|
||||||
int m_GLVersion[2];
|
int m_GLVersion[2];
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
#include <imgui/imgui.h>
|
|
||||||
#include "../OpenGL.h"
|
|
||||||
#include "IRenderer.h"
|
|
||||||
#include "RenderState.h"
|
|
||||||
#include "../Core/EventBroker.h"
|
|
||||||
#include "../Core/EMousePress.h"
|
|
||||||
#include "../Core/EMouseRelease.h"
|
|
||||||
#include "../Core/EMouseMove.h"
|
|
||||||
#include "../Core/EMouseScroll.h"
|
|
||||||
#include "../Core/EKeyDown.h"
|
|
||||||
#include "../Core/EKeyUp.h"
|
|
||||||
#include "../Core/EKeyboardChar.h"
|
|
||||||
|
|
||||||
class ImGuiRenderState : public RenderState
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ImGuiRenderState()
|
|
||||||
: RenderState()
|
|
||||||
{
|
|
||||||
BindFramebuffer(0);
|
|
||||||
Enable(GL_BLEND);
|
|
||||||
BlendEquation(GL_FUNC_ADD);
|
|
||||||
BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
Disable(GL_CULL_FACE);
|
|
||||||
Disable(GL_DEPTH_TEST);
|
|
||||||
Enable(GL_SCISSOR_TEST);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ImGuiRenderPass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ImGuiRenderPass(IRenderer* renderer, EventBroker* eventBroker);
|
|
||||||
|
|
||||||
void Update(double dt);
|
|
||||||
void Draw();
|
|
||||||
|
|
||||||
private:
|
|
||||||
IRenderer* m_Renderer;
|
|
||||||
EventBroker* m_EventBroker;
|
|
||||||
|
|
||||||
GLFWwindow* g_Window;
|
|
||||||
double g_DeltaTime = 0.0;
|
|
||||||
float g_MouseWheel = 0.f;
|
|
||||||
GLuint g_FontTexture;
|
|
||||||
int g_ShaderHandle;
|
|
||||||
int g_VertHandle;
|
|
||||||
int g_FragHandle;
|
|
||||||
int g_AttribLocationTex;
|
|
||||||
int g_AttribLocationProjMtx;
|
|
||||||
int g_AttribLocationPosition;
|
|
||||||
int g_AttribLocationUV;
|
|
||||||
int g_AttribLocationColor;
|
|
||||||
GLuint g_VboHandle;
|
|
||||||
GLuint g_VaoHandle;
|
|
||||||
GLuint g_ElementsHandle;
|
|
||||||
|
|
||||||
EventRelay<ImGuiRenderPass, Events::MousePress> m_EMousePress;
|
|
||||||
bool OnMousePress(const Events::MousePress& e);
|
|
||||||
EventRelay<ImGuiRenderPass, Events::MouseRelease> m_EMouseRelease;
|
|
||||||
bool OnMouseRelease(const Events::MouseRelease& e);
|
|
||||||
EventRelay<ImGuiRenderPass, Events::MouseMove> m_EMouseMove;
|
|
||||||
bool OnMouseMove(const Events::MouseMove& e);
|
|
||||||
EventRelay<ImGuiRenderPass, Events::MouseScroll> m_EMouseScroll;
|
|
||||||
bool OnMouseScroll(const Events::MouseScroll& e);
|
|
||||||
EventRelay<ImGuiRenderPass, Events::KeyDown> m_EKeyDown;
|
|
||||||
bool OnKeyDown(const Events::KeyDown& e);
|
|
||||||
EventRelay<ImGuiRenderPass, Events::KeyUp> m_EKeyUp;
|
|
||||||
bool OnKeyUp(const Events::KeyUp& e);
|
|
||||||
EventRelay<ImGuiRenderPass, Events::KeyboardChar> m_EKeyboardChar;
|
|
||||||
bool OnKeyboardChar(const Events::KeyboardChar& e);
|
|
||||||
|
|
||||||
bool createDeviceObjects();
|
|
||||||
bool createFontsTexture();
|
|
||||||
|
|
||||||
void newFrame();
|
|
||||||
};
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#ifndef PickingPass_h__
|
|
||||||
#define PickingPass_h__
|
|
||||||
|
|
||||||
#include "IRenderer.h"
|
|
||||||
#include "PickingPassState.h"
|
|
||||||
#include "FrameBuffer.h"
|
|
||||||
#include "ShaderProgram.h"
|
|
||||||
#include "Util/UnorderedMapVec2.h"
|
|
||||||
#include "../Core/EventBroker.h"
|
|
||||||
#include "EPicking.h"
|
|
||||||
|
|
||||||
class PickingPass
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PickingPass(IRenderer* renderer, EventBroker* eb);
|
|
||||||
~PickingPass();
|
|
||||||
void InitializeTextures();
|
|
||||||
void InitializeFrameBuffers();
|
|
||||||
void InitializeShaderPrograms();
|
|
||||||
|
|
||||||
void Draw(RenderQueueCollection& rq);
|
|
||||||
|
|
||||||
|
|
||||||
//Getters
|
|
||||||
const ShaderProgram& PickingProgram() const { return *m_PickingProgram; }
|
|
||||||
const std::unordered_map<glm::vec2, EntityID>& PickingColorsToEntity() const { return m_PickingColorsToEntity; }
|
|
||||||
GLuint PickingTexture() const { return m_PickingTexture; }
|
|
||||||
GLuint DepthBuffer() const { return m_DepthBuffer; }
|
|
||||||
const FrameBuffer& PickingBuffer() const { return m_PickingBuffer; }
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
|
|
||||||
|
|
||||||
EventBroker* m_EventBroker;
|
|
||||||
|
|
||||||
const IRenderer* m_Renderer;
|
|
||||||
|
|
||||||
ShaderProgram* m_PickingProgram;
|
|
||||||
|
|
||||||
std::unordered_map<glm::vec2, EntityID> m_PickingColorsToEntity;
|
|
||||||
|
|
||||||
GLuint m_PickingTexture;
|
|
||||||
GLuint m_DepthBuffer;
|
|
||||||
|
|
||||||
FrameBuffer m_PickingBuffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#ifndef PickingPassState_h__
|
|
||||||
#define PickingPassState_h__
|
|
||||||
|
|
||||||
#include "Rendering/RenderState.h"
|
|
||||||
|
|
||||||
class PickingPassState : public RenderState
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PickingPassState(GLuint frameBuffer);
|
|
||||||
~PickingPassState();
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -13,12 +13,8 @@ public:
|
|||||||
RenderQueueFactory();
|
RenderQueueFactory();
|
||||||
void Update(World* world);
|
void Update(World* world);
|
||||||
|
|
||||||
|
|
||||||
RenderQueueCollection RenderQueues() const { return m_RenderQueues; }
|
RenderQueueCollection RenderQueues() const { return m_RenderQueues; }
|
||||||
|
|
||||||
static glm::vec3 AbsolutePosition(World* world, EntityID entity);
|
|
||||||
static glm::quat AbsoluteOrientation(World* world, EntityID entity);
|
|
||||||
static glm::vec3 AbsoluteScale(World* world, EntityID entity);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RenderQueueCollection m_RenderQueues;
|
RenderQueueCollection m_RenderQueues;
|
||||||
|
|
||||||
@@ -26,6 +22,10 @@ private:
|
|||||||
void FillLights(World* world, RenderQueue* renderQueue);
|
void FillLights(World* world, RenderQueue* renderQueue);
|
||||||
|
|
||||||
glm::mat4 ModelMatrix(World* world, EntityID entity);
|
glm::mat4 ModelMatrix(World* world, EntityID entity);
|
||||||
|
|
||||||
|
glm::vec3 AbsolutePosition(World* world, EntityID entity);
|
||||||
|
glm::quat AbsoluteOrientation(World* world, EntityID entity);
|
||||||
|
glm::vec3 AbsoluteScale(World* world, EntityID entity);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#ifndef RenderState_h__
|
|
||||||
#define RenderState_h__
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include "../Common.h"
|
|
||||||
#include "../OpenGL.h"
|
|
||||||
#include "../GLM.h"
|
|
||||||
|
|
||||||
class RenderState
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RenderState() = default;
|
|
||||||
~RenderState();
|
|
||||||
|
|
||||||
bool Enable(GLenum cap);
|
|
||||||
bool Disable(GLenum cap);
|
|
||||||
bool CullFace(GLenum mode);
|
|
||||||
bool ClearColor(glm::vec4 color);
|
|
||||||
bool Clear(GLbitfield mask);
|
|
||||||
bool BindFramebuffer(GLint framebuffer);
|
|
||||||
bool BlendEquation(GLenum mode);
|
|
||||||
bool BlendFunc(GLenum sfactor, GLenum dfactor);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<std::function<void(void)>> m_ResetFunctions;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
@@ -10,26 +10,9 @@
|
|||||||
#include "Util/UnorderedMapVec2.h"
|
#include "Util/UnorderedMapVec2.h"
|
||||||
#include "FrameBuffer.h"
|
#include "FrameBuffer.h"
|
||||||
#include "../Core/World.h"
|
#include "../Core/World.h"
|
||||||
#include "PickingPass.h"
|
|
||||||
#include "DrawScenePass.h"
|
|
||||||
#include "DebugCameraInputController.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define TILE_SIZE 16
|
|
||||||
#define NUM_LIGHTS 3
|
|
||||||
|
|
||||||
|
|
||||||
enum lightType
|
|
||||||
{
|
|
||||||
Point,
|
|
||||||
Spot,
|
|
||||||
Directional,
|
|
||||||
Area
|
|
||||||
};
|
|
||||||
|
|
||||||
#include "../Core/EventBroker.h"
|
#include "../Core/EventBroker.h"
|
||||||
#include "EPicking.h"
|
#include "EPicking.h"
|
||||||
#include "ImGuiRenderPass.h"
|
|
||||||
|
|
||||||
class Renderer : public IRenderer
|
class Renderer : public IRenderer
|
||||||
{
|
{
|
||||||
@@ -38,90 +21,44 @@ public:
|
|||||||
: m_EventBroker(eventBroker)
|
: m_EventBroker(eventBroker)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void Initialize() override;
|
virtual void Initialize() override;
|
||||||
virtual void Update(double dt) override;
|
virtual void Update(double dt) override;
|
||||||
virtual void Draw(RenderQueueCollection& rq) override;
|
virtual void Draw(RenderQueueCollection& rq) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//----------------------Variables----------------------//
|
//----------------------Variables----------------------//
|
||||||
EventBroker* m_EventBroker;
|
EventBroker* m_EventBroker;
|
||||||
|
|
||||||
std::shared_ptr<DebugCameraInputController<Renderer>> m_DebugCameraInputController;
|
Texture* m_ErrorTexture;
|
||||||
|
Texture* m_WhiteTexture;
|
||||||
Texture* m_ErrorTexture;
|
float m_CameraMoveSpeed;
|
||||||
Texture* m_WhiteTexture;
|
FrameBuffer m_PickingBuffer;
|
||||||
float m_CameraMoveSpeed;
|
GLuint m_PickingTexture;
|
||||||
|
GLuint m_DepthBuffer;
|
||||||
|
|
||||||
Model* m_ScreenQuad;
|
Model* m_ScreenQuad;
|
||||||
Model* m_UnitQuad;
|
Model* m_UnitQuad;
|
||||||
Model* m_UnitSphere;
|
Model* m_UnitSphere;
|
||||||
|
|
||||||
DrawScenePass* m_DrawScenePass;
|
std::unordered_map<glm::vec2, EntityID> m_PickingColorsToEntity;
|
||||||
PickingPass* m_PickingPass;
|
|
||||||
ImGuiRenderPass* m_ImGuiRenderPass;
|
|
||||||
|
|
||||||
//----------------------Functions----------------------//
|
//----------------------Functions----------------------//
|
||||||
void InitializeWindow();
|
void InitializeWindow();
|
||||||
void InitializeShaders();
|
void InitializeShaders();
|
||||||
void InitializeTextures();
|
void InitializeTextures();
|
||||||
void InitializeSSBOs();
|
void InitializeFrameBuffers();
|
||||||
void InitializeRenderPasses();
|
|
||||||
//TODO: Renderer: Get InputUpdate out of renderer
|
//TODO: Renderer: Get InputUpdate out of renderer
|
||||||
void InputUpdate(double dt);
|
void InputUpdate(double dt);
|
||||||
//void PickingPass(RenderQueueCollection& rq);
|
void PickingPass(RenderQueueCollection& rq);
|
||||||
void DrawScreenQuad(GLuint textureToDraw);
|
void DrawScreenQuad(GLuint textureToDraw);
|
||||||
|
void DrawScene(RenderQueueCollection& rq);
|
||||||
|
|
||||||
//----------------------Forward+-----------------------//
|
|
||||||
void CalculateFrustum();
|
|
||||||
void CullLights();
|
|
||||||
//Frustum
|
|
||||||
struct Plane {
|
|
||||||
glm::vec3 Normal;
|
|
||||||
float d;
|
|
||||||
};
|
|
||||||
struct Frustum {
|
|
||||||
Plane Planes[4];
|
|
||||||
};
|
|
||||||
Frustum m_Frustums[80*45]; //TODO: Renderer: Make this change with resolution
|
|
||||||
|
|
||||||
//Lights
|
|
||||||
void TEMPCreateLights();
|
|
||||||
//TODO: Renderer: Add Directionllights, spotlights and area lights to this as type.
|
|
||||||
struct PointLight {
|
|
||||||
glm::vec4 Position = glm::vec4(0.f);
|
|
||||||
glm::vec4 Color = glm::vec4(1.f);
|
|
||||||
float Radius = 5.f;
|
|
||||||
float Intensity = 0.8f;
|
|
||||||
float Falloff = 0.3f;
|
|
||||||
float Padding = 1337;
|
|
||||||
};
|
|
||||||
PointLight m_PointLights[NUM_LIGHTS];
|
|
||||||
|
|
||||||
struct LightGrid {
|
|
||||||
int Amount;
|
|
||||||
int Start;
|
|
||||||
glm::vec2 Padding;
|
|
||||||
};
|
|
||||||
LightGrid m_LightGrid[80*45];
|
|
||||||
|
|
||||||
int m_LightOffset = 0;
|
|
||||||
|
|
||||||
int m_LightIndex[80*45*200];
|
|
||||||
|
|
||||||
//-------------------------SSBO------------------------//
|
|
||||||
GLuint m_FrustumSSBO = 0;
|
|
||||||
GLuint m_LightSSBO = 1;
|
|
||||||
GLuint m_LightGridSSBO = 2;
|
|
||||||
GLuint m_LightOffsetSSBO = 3;
|
|
||||||
GLuint m_LightIndexSSBO = 4;
|
|
||||||
|
|
||||||
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type);
|
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type);
|
||||||
//--------------------ShaderPrograms-------------------//
|
//--------------------ShaderPrograms-------------------//
|
||||||
ShaderProgram* m_BasicForwardProgram;
|
ShaderProgram m_BasicForwardProgram;
|
||||||
ShaderProgram* m_DrawScreenQuadProgram;
|
ShaderProgram m_PickingProgram;
|
||||||
ShaderProgram* m_CalculateFrustumProgram;
|
ShaderProgram m_DrawScreenQuadProgram;
|
||||||
ShaderProgram* m_LightCullProgram;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
#ifndef ShaderProgram_h__
|
|
||||||
#define ShaderProgram_h__
|
|
||||||
|
|
||||||
#include "../Common.h"
|
#include "../Common.h"
|
||||||
#include "../OpenGL.h"
|
#include "../OpenGL.h"
|
||||||
#include "../Core/ResourceManager.h"
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
class Shader
|
class Shader
|
||||||
@@ -63,13 +60,11 @@ public:
|
|||||||
: ShaderType(fileName) { }
|
: ShaderType(fileName) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShaderProgram : public Resource
|
class ShaderProgram
|
||||||
{
|
{
|
||||||
friend class ResourceManager;
|
|
||||||
private:
|
|
||||||
ShaderProgram(std::string)
|
|
||||||
: m_ShaderProgramHandle(0) { }
|
|
||||||
public:
|
public:
|
||||||
|
ShaderProgram()
|
||||||
|
: m_ShaderProgramHandle(0) { }
|
||||||
~ShaderProgram();
|
~ShaderProgram();
|
||||||
|
|
||||||
void AddShader(std::shared_ptr<Shader> shader);
|
void AddShader(std::shared_ptr<Shader> shader);
|
||||||
@@ -84,5 +79,3 @@ private:
|
|||||||
GLuint m_ShaderProgramHandle;
|
GLuint m_ShaderProgramHandle;
|
||||||
std::vector<std::shared_ptr<Shader>> m_Shaders;
|
std::vector<std::shared_ptr<Shader>> m_Shaders;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -9,7 +9,7 @@ inline bool _GLERROR(const char* info, const char* file, const char* func, unsig
|
|||||||
GLenum error = glGetError();
|
GLenum error = glGetError();
|
||||||
if (error != GL_NO_ERROR)
|
if (error != GL_NO_ERROR)
|
||||||
{
|
{
|
||||||
_LOG(LOG_LEVEL_ERROR, file, func, line, "GL Error: %s, %i, %s", info, error, gluErrorString(error));
|
_LOG(LOG_LEVEL_ERROR, file, func, line, "GL Error: %s %i %s", info, error, gluErrorString(error));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-17
@@ -12,19 +12,12 @@
|
|||||||
#include "Input/InputProxy.h"
|
#include "Input/InputProxy.h"
|
||||||
#include "Input/KeyboardInputHandler.h"
|
#include "Input/KeyboardInputHandler.h"
|
||||||
#include "Input/MouseInputHandler.h"
|
#include "Input/MouseInputHandler.h"
|
||||||
|
#include "Input/XboxControllerInputHandler.h"
|
||||||
#include "Core/EKeyDown.h"
|
#include "Core/EKeyDown.h"
|
||||||
#include "Core/EntityXMLFile.h"
|
#include "Core/EntityXMLFile.h"
|
||||||
#include "Core/SystemPipeline.h"
|
#include "Core/SystemPipeline.h"
|
||||||
#include "RaptorCopterSystem.h"
|
#include "RaptorCopterSystem.h"
|
||||||
#include "PlayerSystem.h"
|
#include "PlayerSystem.h"
|
||||||
#include "Editor/EditorSystem.h"
|
|
||||||
|
|
||||||
// Network
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
#include "Network/Network.h"
|
|
||||||
#include "Network/Server.h"
|
|
||||||
#include "Network/Client.h"
|
|
||||||
|
|
||||||
|
|
||||||
class Game
|
class Game
|
||||||
{
|
{
|
||||||
@@ -46,21 +39,12 @@ private:
|
|||||||
World* m_World;
|
World* m_World;
|
||||||
SystemPipeline* m_SystemPipeline;
|
SystemPipeline* m_SystemPipeline;
|
||||||
RenderQueueFactory* m_RenderQueueFactory;
|
RenderQueueFactory* m_RenderQueueFactory;
|
||||||
// Network variables
|
|
||||||
boost::thread m_NetworkThread;
|
|
||||||
|
|
||||||
// Network methods
|
|
||||||
void networkFunction();
|
|
||||||
Network* m_ClientOrServer;
|
|
||||||
bool m_IsClientOrServer = false;
|
|
||||||
|
|
||||||
EventRelay<Game, Events::InputCommand> m_EInputCommand;
|
EventRelay<Game, Events::InputCommand> m_EInputCommand;
|
||||||
bool debugOnInputCommand(const Events::InputCommand& e);
|
bool debugOnInputCommand(const Events::InputCommand& e);
|
||||||
|
|
||||||
void debugInitialize();
|
void debugInitialize();
|
||||||
void debugTick(double dt);
|
void debugTick(double dt);
|
||||||
EventRelay<Client, Events::KeyDown> m_EKeyDown;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
#ifndef HealthSystem_h__
|
|
||||||
#define HealthSystem_h__
|
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
#include <glm/common.hpp>
|
|
||||||
|
|
||||||
#include "Common.h"
|
|
||||||
#include "Core/System.h"
|
|
||||||
#include "Core\EPlayerDamage.h";
|
|
||||||
#include "Core\EPlayerHealthPickup.h";
|
|
||||||
#include "Core\EPlayerDeath.h";
|
|
||||||
|
|
||||||
#include <tuple>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class HealthSystem : public PureSystem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HealthSystem(EventBroker* eventBroker);
|
|
||||||
|
|
||||||
//updatecomponent
|
|
||||||
virtual void UpdateComponent(World* world, ComponentWrapper& health, double dt) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
//methods which will take care of specific events
|
|
||||||
EventRelay<HealthSystem, Events::PlayerDamage> m_EPlayerDamage;
|
|
||||||
bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e);
|
|
||||||
EventRelay<HealthSystem, Events::PlayerHealthPickup> m_EPlayerHealthPickup;
|
|
||||||
bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e);
|
|
||||||
|
|
||||||
//vector which will keep track of health changes
|
|
||||||
std::vector<std::tuple<EntityID, double>> m_DeltaHealthVector;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
+24
-13
@@ -6,28 +6,39 @@
|
|||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
#include "Collision/ETrigger.h"
|
#include "Core/EventBroker.h"
|
||||||
|
#include "Core/EKeyDown.h"
|
||||||
|
#include "Core/EKeyUp.h"
|
||||||
|
|
||||||
class PlayerSystem : public PureSystem
|
struct KeyInput
|
||||||
|
{
|
||||||
|
bool Forward = false;
|
||||||
|
bool Left = false;
|
||||||
|
bool Back = false;
|
||||||
|
bool Right = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PlayerSystem : public System
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PlayerSystem(EventBroker* eventBroker)
|
PlayerSystem(EventBroker* eventBroker)
|
||||||
: PureSystem(eventBroker, "Player")
|
: System(eventBroker, "Player")
|
||||||
{
|
{
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_ETouch, &PlayerSystem::OnTouch);
|
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &PlayerSystem::OnKeyDown);
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EEnter, &PlayerSystem::OnEnter);
|
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &PlayerSystem::OnKeyUp);
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_ELeave, &PlayerSystem::OnLeave);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void UpdateComponent(World* world, ComponentWrapper& player, double dt) override;
|
virtual void Update(World* world, ComponentWrapper& player, double dt) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float m_Speed = 5;
|
float m_Speed = 5;
|
||||||
EventRelay<PlayerSystem, Events::TriggerEnter> m_EEnter;
|
glm::vec3 m_Direction;
|
||||||
bool OnEnter(const Events::TriggerEnter &event);
|
KeyInput input;
|
||||||
EventRelay<PlayerSystem, Events::TriggerTouch> m_ETouch;
|
|
||||||
bool PlayerSystem::OnTouch(const Events::TriggerTouch &event);
|
EventRelay<PlayerSystem, Events::KeyDown> m_EKeyDown;
|
||||||
EventRelay<PlayerSystem, Events::TriggerLeave> m_ELeave;
|
bool OnKeyDown(const Events::KeyDown &event);
|
||||||
bool PlayerSystem::OnLeave(const Events::TriggerLeave &event);
|
EventRelay<PlayerSystem, Events::KeyUp> m_EKeyUp;
|
||||||
|
bool OnKeyUp(const Events::KeyUp &event);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
|
|
||||||
class RaptorCopterSystem : public PureSystem
|
class RaptorCopterSystem : public System
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RaptorCopterSystem(EventBroker* eventBroker)
|
RaptorCopterSystem(EventBroker* eventBroker)
|
||||||
: PureSystem(eventBroker, "RaptorCopter")
|
: System(eventBroker, "RaptorCopter")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void UpdateComponent(World* world, ComponentWrapper& raptorCopter, double dt) override
|
virtual void Initialize() { }
|
||||||
|
|
||||||
|
virtual void Update(World* world, ComponentWrapper& raptorCopter, double dt) override
|
||||||
{
|
{
|
||||||
ComponentWrapper& transform = world->GetComponent(raptorCopter.EntityID, "Transform");
|
ComponentWrapper& transform = world->GetComponent(raptorCopter.EntityID, "Transform");
|
||||||
(glm::vec3&)transform["Orientation"] += (float)(double)raptorCopter["Speed"] * (float)dt * (glm::vec3)raptorCopter["Axis"];
|
(glm::vec3&)transform["Orientation"] += (float)(double)raptorCopter["Speed"] * (float)dt * (glm::vec3)raptorCopter["Axis"];
|
||||||
|
|||||||
@@ -1,19 +1,9 @@
|
|||||||
[Debug]
|
[Debug]
|
||||||
LogLevel=1
|
LogLevel=1
|
||||||
LoadMap=
|
LoadMap=
|
||||||
EditorEnabled=false
|
|
||||||
|
|
||||||
|
|
||||||
[Video]
|
[Video]
|
||||||
Fullscreen=false
|
Fullscreen=false
|
||||||
VSYNC=false
|
VSYNC=false
|
||||||
Width=1280
|
Width=1280
|
||||||
Height=720
|
Height=720
|
||||||
FOV=45
|
|
||||||
|
|
||||||
[Networking]
|
|
||||||
StartNetwork=false
|
|
||||||
IsServer=false
|
|
||||||
Name=Bob
|
|
||||||
Address=127.0.0.1
|
|
||||||
Port=13
|
|
||||||
@@ -14,11 +14,11 @@ R=Reload
|
|||||||
Space=Jump
|
Space=Jump
|
||||||
LeftControl=Crouch
|
LeftControl=Crouch
|
||||||
LeftShift=Sprint
|
LeftShift=Sprint
|
||||||
F1=ToggleEditor
|
|
||||||
1=EditorToolMove
|
GamepadRightTrigger=PrimaryFire
|
||||||
2=EditorToolRotate
|
GamepadRightX=Yaw
|
||||||
3=EditorToolScale
|
GamepadRightY=-Pitch
|
||||||
X=EditorToggleTransformSpace
|
GamepadA=TestGamepadA
|
||||||
C=ConnectToServer
|
GamepadX=TestGamepadX
|
||||||
N=SwitchToServer
|
GamepadLeftX=Right
|
||||||
M=SwitchToClient
|
GamepadLeftY=Forward
|
||||||
@@ -6,7 +6,4 @@
|
|||||||
<xs:include schemaLocation="Components/Test.xsd"/>
|
<xs:include schemaLocation="Components/Test.xsd"/>
|
||||||
<xs:include schemaLocation="Components/RaptorCopter.xsd"/>
|
<xs:include schemaLocation="Components/RaptorCopter.xsd"/>
|
||||||
<xs:include schemaLocation="Components/Player.xsd"/>
|
<xs:include schemaLocation="Components/Player.xsd"/>
|
||||||
<xs:include schemaLocation="Components/AABB.xsd"/>
|
|
||||||
<xs:include schemaLocation="Components/Trigger.xsd"/>
|
|
||||||
<xs:include schemaLocation="Components/Health.xsd"/>
|
|
||||||
</xs:schema>
|
</xs:schema>
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<c:AABB>
|
|
||||||
<BoxCenter X="0" Y="0" Z="0"/>
|
|
||||||
<BoxSize X="1" Y="1" Z="1"/>
|
|
||||||
</c:AABB>
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<?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="AABB">
|
|
||||||
<xs:complexType>
|
|
||||||
<xs:all>
|
|
||||||
<xs:element name="BoxCenter" type="t:Vector" minOccurs="0"/>
|
|
||||||
<xs:element name="BoxSize" type="t:Vector" minOccurs="0"/>
|
|
||||||
</xs:all>
|
|
||||||
</xs:complexType>
|
|
||||||
</xs:element>
|
|
||||||
</xs:schema>
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<c:Health>
|
|
||||||
<Health>100</Health>
|
|
||||||
<MaxHealth>100</MaxHealth>
|
|
||||||
</c:Health>
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<?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="Health">
|
|
||||||
<xs:complexType>
|
|
||||||
<xs:all>
|
|
||||||
<xs:element name="Health" type="t:double" minOccurs="0"/>
|
|
||||||
<xs:element name="MaxHealth" type="t:double" minOccurs="0"/>
|
|
||||||
</xs:all>
|
|
||||||
</xs:complexType>
|
|
||||||
</xs:element>
|
|
||||||
</xs:schema>
|
|
||||||
@@ -1,7 +1,3 @@
|
|||||||
<c:Player>
|
<c:Player>
|
||||||
<Velocity X="0" Y="0" Z="0"/>
|
<Velocity X="0" Y="0" Z="0"/>
|
||||||
<Forward>false</Forward>
|
|
||||||
<Left>false</Left>
|
|
||||||
<Back>false</Back>
|
|
||||||
<Right>false</Right>
|
|
||||||
</c:Player>
|
</c:Player>
|
||||||
@@ -7,10 +7,6 @@
|
|||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:all>
|
<xs:all>
|
||||||
<xs:element name="Velocity" type="t:Vector" minOccurs="0"/>
|
<xs:element name="Velocity" type="t:Vector" minOccurs="0"/>
|
||||||
<xs:element name="Forward" type="t:bool" minOccurs="0"/>
|
|
||||||
<xs:element name="Left" type="t:bool" minOccurs="0"/>
|
|
||||||
<xs:element name="Back" type="t:bool" minOccurs="0"/>
|
|
||||||
<xs:element name="Right" type="t:bool" minOccurs="0"/>
|
|
||||||
</xs:all>
|
</xs:all>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<c:Test>
|
||||||
|
<Integer>1</Integer>
|
||||||
|
<Float>1.333</Float>
|
||||||
|
<Vector X="1.33333" Y="2.33333" Z="3.33333"/>
|
||||||
|
<Quaternion X="1.33333" Y="2.33333" Z="3.33333" W="4.44444"/>
|
||||||
|
</c:Test>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?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="Test">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>ECS Test Component</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:all>
|
||||||
|
<xs:element name="Integer" type="t:int" minOccurs="0"/>
|
||||||
|
<xs:element name="Double" type="t:double" minOccurs="0"/>
|
||||||
|
<xs:element name="String" type="t:string" minOccurs="0"/>
|
||||||
|
<xs:element name="Vector" type="t:Vector" minOccurs="0"/>
|
||||||
|
<xs:element name="Quaternion" type="t:Quaternion" minOccurs="0"/>
|
||||||
|
</xs:all>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:schema>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<c:Transform>
|
<c:Transform>
|
||||||
<Position X="0" Y="0" Z="0"/>
|
<Position X="0" Y="0" Z="0"/>
|
||||||
<Orientation X="0" Y="0" Z="0"/>
|
<Orientation X="0" Y="0" Z="0" W="0"/>
|
||||||
<Scale X="1" Y="1" Z="1"/>
|
<Scale X="1" Y="1" Z="1"/>
|
||||||
</c:Transform>
|
</c:Transform>
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
<c:Trigger>
|
|
||||||
</c:Trigger>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?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="Trigger">
|
|
||||||
</xs:element>
|
|
||||||
</xs:schema>
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<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>
|
|
||||||
<Orientation X="0" Y="0" Z="0"/>
|
|
||||||
</c:Transform>
|
|
||||||
<c:Model>
|
|
||||||
<Resource>Models/DummyScene.obj</Resource>
|
|
||||||
</c:Model>
|
|
||||||
</Components>
|
|
||||||
<Children>
|
|
||||||
<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"/>
|
|
||||||
<Scale X="2" Y="2" Z="2"/>
|
|
||||||
</c:Transform>
|
|
||||||
<c:Model>
|
|
||||||
<Resource>Models/RotationWidgetX.obj</Resource>
|
|
||||||
</c:Model>
|
|
||||||
<c:Trigger>
|
|
||||||
</c:Trigger>
|
|
||||||
</Components>
|
|
||||||
</Entity>
|
|
||||||
<Entity>
|
|
||||||
<Components>
|
|
||||||
<c:Player>
|
|
||||||
<Velocity X="0" Y="0" Z="0"/>
|
|
||||||
</c:Player>
|
|
||||||
<c:Transform>
|
|
||||||
<Position X="2.5"/>
|
|
||||||
</c:Transform>
|
|
||||||
<c:Model>
|
|
||||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
|
||||||
</c:Model>
|
|
||||||
<c:AABB>
|
|
||||||
</c:AABB>
|
|
||||||
</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="1.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.01" Y="0.55"/>
|
|
||||||
<Orientation X="0" Y="0" Z="-1"/>
|
|
||||||
</c:Transform>
|
|
||||||
<c:RaptorCopter>
|
|
||||||
<Speed>20</Speed>
|
|
||||||
<Axis Y="1"/>
|
|
||||||
</c:RaptorCopter>
|
|
||||||
</Components>
|
|
||||||
<Children>
|
|
||||||
<Entity>
|
|
||||||
<Components>
|
|
||||||
<c:Transform>
|
|
||||||
<Position X="0" Y="0"/>
|
|
||||||
<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"/>
|
|
||||||
<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>
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<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="0" Y="0" Z="0"/>
|
|
||||||
<Orientation X="0" Y="0" Z="0"/>
|
|
||||||
</c:Transform>
|
|
||||||
</Components>
|
|
||||||
<Children>
|
|
||||||
<Entity>
|
|
||||||
<Components>
|
|
||||||
<c:Transform>
|
|
||||||
<Position X="0" Y="0" Z="0"/>
|
|
||||||
<Scale X="100" Y="1" Z="100"/>
|
|
||||||
</c:Transform>
|
|
||||||
<c:Model>
|
|
||||||
<Resource>Models/Core/UnitPlane.obj</Resource>
|
|
||||||
</c:Model>
|
|
||||||
</Components>
|
|
||||||
</Entity>
|
|
||||||
<Entity>
|
|
||||||
<Components>
|
|
||||||
<c:Transform>
|
|
||||||
<Position X="1" Y="1" Z="0"/>
|
|
||||||
<Orientation X="0" Y="0.78539" Z="0"/>
|
|
||||||
</c:Transform>
|
|
||||||
<c:Model>
|
|
||||||
<Resource>An error</Resource>
|
|
||||||
</c:Model>
|
|
||||||
</Components>
|
|
||||||
<Children>
|
|
||||||
<Entity>
|
|
||||||
<Components>
|
|
||||||
<c:Transform>
|
|
||||||
<Position X="2" Y="0" Z="0"/>
|
|
||||||
<Orientation X="0" Y="0.78539" Z="0"/>
|
|
||||||
</c:Transform>
|
|
||||||
<c:Model>
|
|
||||||
<Resource>An error</Resource>
|
|
||||||
</c:Model>
|
|
||||||
</Components>
|
|
||||||
<Children>
|
|
||||||
</Children>
|
|
||||||
</Entity>
|
|
||||||
</Children>
|
|
||||||
</Entity>
|
|
||||||
</Children>
|
|
||||||
</Entity>
|
|
||||||
@@ -25,16 +25,13 @@
|
|||||||
<Components>
|
<Components>
|
||||||
<c:Transform>
|
<c:Transform>
|
||||||
<Position X="1.5"/>
|
<Position X="1.5"/>
|
||||||
<Scale X="2" Y="2" Z="2"/>
|
|
||||||
</c:Transform>
|
</c:Transform>
|
||||||
<c:Model>
|
<c:Model>
|
||||||
<Resource>Models/RotationWidget.obj</Resource>
|
<Resource>Models/RotationWidget.obj</Resource>
|
||||||
</c:Model>
|
</c:Model>
|
||||||
<c:Trigger>
|
|
||||||
</c:Trigger>
|
|
||||||
</Components>
|
</Components>
|
||||||
</Entity>
|
</Entity>
|
||||||
<!--<Entity>
|
<Entity>
|
||||||
<Components>
|
<Components>
|
||||||
<c:Player>
|
<c:Player>
|
||||||
<Velocity X="0" Y="0" Z="0"/>
|
<Velocity X="0" Y="0" Z="0"/>
|
||||||
@@ -45,10 +42,8 @@
|
|||||||
<c:Model>
|
<c:Model>
|
||||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||||
</c:Model>
|
</c:Model>
|
||||||
<c:AABB>
|
|
||||||
</c:AABB>
|
|
||||||
</Components>
|
</Components>
|
||||||
</Entity>-->
|
</Entity>
|
||||||
<Entity>
|
<Entity>
|
||||||
<Components>
|
<Components>
|
||||||
<c:Transform>
|
<c:Transform>
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
<xs:element ref="c:Test" minOccurs="0"/>
|
<xs:element ref="c:Test" minOccurs="0"/>
|
||||||
<xs:element ref="c:RaptorCopter" minOccurs="0"/>
|
<xs:element ref="c:RaptorCopter" minOccurs="0"/>
|
||||||
<xs:element ref="c:Player" minOccurs="0"/>
|
<xs:element ref="c:Player" minOccurs="0"/>
|
||||||
<xs:element ref="c:Health" minOccurs="0"/>
|
|
||||||
</xs:all>
|
</xs:all>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
#version 430
|
|
||||||
|
|
||||||
#define TILE_SIZE 16
|
|
||||||
#define NUM_TILES 3600
|
|
||||||
|
|
||||||
uniform mat4 P;
|
|
||||||
uniform vec2 ScreenDimensions;
|
|
||||||
|
|
||||||
struct Plane {
|
|
||||||
vec3 Normal;
|
|
||||||
float d;
|
|
||||||
};
|
|
||||||
struct Frustum {
|
|
||||||
Plane Planes[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout (std430, binding = 0) buffer FrustumBuffer
|
|
||||||
{
|
|
||||||
Frustum Data[3600];
|
|
||||||
} Frustums;
|
|
||||||
|
|
||||||
vec4 ConvertToView(vec4 ScreenCoords)
|
|
||||||
{
|
|
||||||
vec2 normalizedScreenCoords = ScreenCoords.xy / ScreenDimensions;
|
|
||||||
vec4 clipSpace = vec4( vec2(normalizedScreenCoords.x, normalizedScreenCoords.y) * 2.0 - 1.0, ScreenCoords.z, ScreenCoords.w);
|
|
||||||
vec4 view = inverse(P) * clipSpace;
|
|
||||||
view = view / view.w;
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
Plane ComputePlane( vec3 p0, vec3 p1, vec3 p2 )
|
|
||||||
{
|
|
||||||
Plane plane;
|
|
||||||
|
|
||||||
vec3 v0 = p1 - p0;
|
|
||||||
vec3 v2 = p2 - p0;
|
|
||||||
|
|
||||||
plane.Normal = normalize( cross( v0, v2 ) );
|
|
||||||
plane.d = dot( vec3(plane.Normal), p0 ); // Always 0 probably
|
|
||||||
return plane;
|
|
||||||
}
|
|
||||||
|
|
||||||
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
|
||||||
void main ()
|
|
||||||
{
|
|
||||||
if(gl_GlobalInvocationID.x * TILE_SIZE < ScreenDimensions.x && gl_GlobalInvocationID.y * TILE_SIZE < ScreenDimensions.y) {
|
|
||||||
//Top-Left = 0 | Top-Right = 1
|
|
||||||
//Bottom-Left = 2 | Bottom-Right = 3
|
|
||||||
vec4 ScreenCoords[4];
|
|
||||||
ScreenCoords[0] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y + 1 ) * TILE_SIZE, -1.0, 1.0); // Z-axis might need to be 1
|
|
||||||
ScreenCoords[1] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0);
|
|
||||||
ScreenCoords[2] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0);
|
|
||||||
ScreenCoords[3] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0);
|
|
||||||
|
|
||||||
vec3 ViewVectors[4];
|
|
||||||
for(int i = 0; i < 4; i++) {
|
|
||||||
ViewVectors[i] = vec3(ConvertToView(ScreenCoords[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 EyePos = vec3(0,0,0);
|
|
||||||
|
|
||||||
Frustum f;
|
|
||||||
f.Planes[0] = ComputePlane(EyePos, ViewVectors[2], ViewVectors[0]);
|
|
||||||
f.Planes[1] = ComputePlane(EyePos, ViewVectors[1], ViewVectors[3]);
|
|
||||||
f.Planes[2] = ComputePlane(EyePos, ViewVectors[0], ViewVectors[1]);
|
|
||||||
f.Planes[3] = ComputePlane(EyePos, ViewVectors[3], ViewVectors[2]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Frustums.Data[gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*80] = f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#version 430
|
|
||||||
|
|
||||||
//in uvec3 gl_NumWorkGroups;
|
|
||||||
//in uvec3 gl_WorkGroupID;
|
|
||||||
//in uvec3 gl_LocalInvocationID;
|
|
||||||
//in uvec3 gl_GlobalInvocationID;
|
|
||||||
//in uint gl_LocalInvocationIndex;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define NUM_LIGHTS 3
|
|
||||||
#define MAX_LIGHTS_PER_TILE 200
|
|
||||||
#define NUM_TILES 3600
|
|
||||||
|
|
||||||
struct Plane {
|
|
||||||
vec3 Normal;
|
|
||||||
float d;
|
|
||||||
};
|
|
||||||
struct Frustum {
|
|
||||||
Plane Planes[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout (std430, binding = 0) buffer FrustumBuffer
|
|
||||||
{
|
|
||||||
Frustum Data[3600];
|
|
||||||
} Frustums;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
|
||||||
void main ()
|
|
||||||
{
|
|
||||||
if(1 == 1) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -60,6 +60,7 @@ file(GLOB SOURCE_FILES_Rendering_Util
|
|||||||
"${INCLUDE_PATH}/Rendering/Util/*.h"
|
"${INCLUDE_PATH}/Rendering/Util/*.h"
|
||||||
"Rendering/Util/*.cpp"
|
"Rendering/Util/*.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group(Rendering FILES ${SOURCE_FILES_Rendering})
|
source_group(Rendering FILES ${SOURCE_FILES_Rendering})
|
||||||
source_group(Rendering\\Util FILES ${SOURCE_FILES_Rendering_Util})
|
source_group(Rendering\\Util FILES ${SOURCE_FILES_Rendering_Util})
|
||||||
|
|
||||||
@@ -69,18 +70,6 @@ file(GLOB SOURCE_FILES_GUI
|
|||||||
)
|
)
|
||||||
source_group(GUI FILES ${SOURCE_FILES_GUI})
|
source_group(GUI FILES ${SOURCE_FILES_GUI})
|
||||||
|
|
||||||
file(GLOB SOURCE_FILES_Collision
|
|
||||||
"${INCLUDE_PATH}/Collision/*.h"
|
|
||||||
"Collision/*.cpp"
|
|
||||||
)
|
|
||||||
source_group(Collision FILES ${SOURCE_FILES_Collision})
|
|
||||||
|
|
||||||
file(GLOB SOURCE_FILES_Editor
|
|
||||||
"${INCLUDE_PATH}/Editor/*.h"
|
|
||||||
"Editor/*.cpp"
|
|
||||||
)
|
|
||||||
source_group(Editor FILES ${SOURCE_FILES_Editor})
|
|
||||||
|
|
||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
${SOURCE_FILES_Core}
|
${SOURCE_FILES_Core}
|
||||||
${SOURCE_FILES_Core_Util}
|
${SOURCE_FILES_Core_Util}
|
||||||
@@ -89,11 +78,6 @@ set(SOURCE_FILES
|
|||||||
${SOURCE_FILES_GUI}
|
${SOURCE_FILES_GUI}
|
||||||
${SOURCE_FILES_Rendering}
|
${SOURCE_FILES_Rendering}
|
||||||
${SOURCE_FILES_Rendering_Util}
|
${SOURCE_FILES_Rendering_Util}
|
||||||
${SOURCE_FILES_Collision}
|
|
||||||
${CMAKE_SOURCE_DIR}/deps/include/imgui/imgui.cpp
|
|
||||||
${CMAKE_SOURCE_DIR}/deps/include/imgui/imgui_draw.cpp
|
|
||||||
${CMAKE_SOURCE_DIR}/deps/include/imgui/imgui_demo.cpp
|
|
||||||
${SOURCE_FILES_Editor}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBRARIES
|
set(LIBRARIES
|
||||||
|
|||||||
@@ -1,282 +0,0 @@
|
|||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "Collision/Collision.h"
|
|
||||||
#include "Engine/GLM.h"
|
|
||||||
#include "Core/World.h"
|
|
||||||
#include "Rendering/Model.h"
|
|
||||||
|
|
||||||
namespace Collision
|
|
||||||
{
|
|
||||||
|
|
||||||
//note: this one hasnt been delta adjusted like RayVsAABB has
|
|
||||||
bool RayAABBIntr(const Ray& ray, const AABB& box)
|
|
||||||
{
|
|
||||||
glm::vec3 w = 75.0f * ray.Direction();
|
|
||||||
glm::vec3 v = glm::abs(w);
|
|
||||||
glm::vec3 c = ray.Origin() - box.Center() + w;
|
|
||||||
glm::vec3 half = box.HalfSize();
|
|
||||||
|
|
||||||
if (abs(c.x) > v.x + half.x) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (abs(c.y) > v.y + half.y) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (abs(c.z) > v.z + half.z) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (abs(c.y*w.z - c.z*w.y) > half.y*v.z + half.z*v.y) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (abs(c.x*w.z - c.z*w.x) > half.x*v.z + half.z*v.x) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !(abs(c.x*w.y - c.y*w.x) > half.x*v.y + half.y*v.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RayVsAABB(const Ray& ray, const AABB& box)
|
|
||||||
{
|
|
||||||
float dummy;
|
|
||||||
return RayVsAABB(ray, box, dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance)
|
|
||||||
{
|
|
||||||
glm::vec3 invdir = 1.0f / ray.Direction();
|
|
||||||
glm::vec3 origin = ray.Origin();
|
|
||||||
|
|
||||||
float t1 = (box.MinCorner().x - origin.x)*invdir.x;
|
|
||||||
float t2 = (box.MaxCorner().x - origin.x)*invdir.x;
|
|
||||||
float t3 = (box.MinCorner().y - origin.y)*invdir.y;
|
|
||||||
float t4 = (box.MaxCorner().y - origin.y)*invdir.y;
|
|
||||||
float t5 = (box.MinCorner().z - origin.z)*invdir.z;
|
|
||||||
float t6 = (box.MaxCorner().z - origin.z)*invdir.z;
|
|
||||||
|
|
||||||
float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6));
|
|
||||||
float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6));
|
|
||||||
|
|
||||||
//if (tmax < 0 || tmin > tmax)
|
|
||||||
//if tmin,tmax are almost the same (i.e. hitting exactly in the corner) then tmin might be slightly
|
|
||||||
//greater than tmax becuase of floating-precision problems. fixed by adding a small delta to tmax
|
|
||||||
if (tmax < 0 || tmin>(tmax + 0.0001f))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
outDistance = (tmin > 0) ? tmin : tmax;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AABBVsAABB(const AABB& a, const AABB& b)
|
|
||||||
{
|
|
||||||
const glm::vec3& aCenter = a.Center();
|
|
||||||
const glm::vec3& bCenter = b.Center();
|
|
||||||
const glm::vec3& aHSize = a.HalfSize();
|
|
||||||
const glm::vec3& bHSize = b.HalfSize();
|
|
||||||
//Test will probably exit because of the X and Z axes more often, so test them first.
|
|
||||||
if (abs(aCenter[0] - bCenter[0]) > (aHSize[0] + bHSize[0])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (abs(aCenter[2] - bCenter[2]) > (aHSize[2] + bHSize[2])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (abs(aCenter[1] - bCenter[1]) <= (aHSize[1] + bHSize[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation)
|
|
||||||
{
|
|
||||||
minimumTranslation = glm::vec3(0, 0, 0);
|
|
||||||
const glm::vec3& aMax = a.MaxCorner();
|
|
||||||
const glm::vec3& bMax = b.MaxCorner();
|
|
||||||
const glm::vec3& aMin = a.MinCorner();
|
|
||||||
const glm::vec3& bMin = b.MinCorner();
|
|
||||||
const glm::vec3& bSize = b.Size();
|
|
||||||
const glm::vec3& aSize = a.Size();
|
|
||||||
float minOffset = INFINITY;
|
|
||||||
float off;
|
|
||||||
auto axisesIntersecting = glm::tvec3<bool, glm::highp>(false, false, false);
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
off = bMax[i] - aMin[i];
|
|
||||||
if (off > 0 && off < bSize[i] + aSize[i]) {
|
|
||||||
if (off < minOffset) {
|
|
||||||
minimumTranslation = glm::vec3();
|
|
||||||
minimumTranslation[i] = minOffset = off;
|
|
||||||
}
|
|
||||||
axisesIntersecting[i] = true;
|
|
||||||
}
|
|
||||||
off = aMax[i] - bMin[i];
|
|
||||||
if (off > 0 && off < bSize[i] + aSize[i]) {
|
|
||||||
if (off < minOffset) {
|
|
||||||
minOffset = off;
|
|
||||||
minimumTranslation = glm::vec3();
|
|
||||||
minimumTranslation[i] = -off;
|
|
||||||
}
|
|
||||||
axisesIntersecting[i] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return glm::all(axisesIntersecting);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RayVsModel(const Ray& ray,
|
|
||||||
const std::vector<RawModel::Vertex>& modelVertices,
|
|
||||||
const std::vector<unsigned int>& modelIndices)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < modelIndices.size(); ++i) {
|
|
||||||
glm::vec3 v0 = modelVertices[modelIndices[i]].Position;
|
|
||||||
glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0
|
|
||||||
glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0
|
|
||||||
glm::vec3 m = ray.Origin() - v0;
|
|
||||||
glm::vec3 MxE1 = glm::cross(m, e1);
|
|
||||||
glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);
|
|
||||||
float DetInv = glm::dot(e1, DxE2);
|
|
||||||
if (std::abs(DetInv) < FLT_EPSILON) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
DetInv = 1.0f / DetInv;
|
|
||||||
float u = glm::dot(m, DxE2) * DetInv;
|
|
||||||
float v = glm::dot(ray.Direction(), MxE1) * DetInv;
|
|
||||||
//u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem
|
|
||||||
if ((u + 0.001f) < 0 || (v + 0.001f) < 0 || 1 < u + v) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit.
|
|
||||||
if (0 <= glm::dot(e2, MxE1) * DetInv) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RayVsModel(const Ray& ray,
|
|
||||||
const std::vector<RawModel::Vertex>& modelVertices,
|
|
||||||
const std::vector<unsigned int>& modelIndices,
|
|
||||||
float& outDistance,
|
|
||||||
float& outUCoord,
|
|
||||||
float& outVCoord)
|
|
||||||
{
|
|
||||||
outDistance = INFINITY;
|
|
||||||
bool hit = false;
|
|
||||||
for (int i = 0; i < modelIndices.size(); ++i) {
|
|
||||||
glm::vec3 v0 = modelVertices[modelIndices[i]].Position;
|
|
||||||
glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0
|
|
||||||
glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0
|
|
||||||
glm::vec3 m = ray.Origin() - v0;
|
|
||||||
glm::vec3 MxE1 = glm::cross(m, e1);
|
|
||||||
glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);//pVec
|
|
||||||
float DetInv = glm::dot(e1, DxE2);
|
|
||||||
if (std::abs(DetInv) < FLT_EPSILON) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
DetInv = 1.0f / DetInv;
|
|
||||||
float dist = glm::dot(e2, MxE1) * DetInv;
|
|
||||||
if (dist >= outDistance) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
float u = glm::dot(m, DxE2) * DetInv;
|
|
||||||
float v = glm::dot(ray.Direction(), MxE1) * DetInv;
|
|
||||||
|
|
||||||
//u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem
|
|
||||||
//If u and v are positive, u+v <= 1, dist is positive, and less than closest.
|
|
||||||
if (0 <= (u + 0.001f) && 0 <= (v + 0.001f) && u + v <= 1 && 0 <= dist) {
|
|
||||||
outDistance = dist;
|
|
||||||
outUCoord = u;
|
|
||||||
outVCoord = v;
|
|
||||||
hit = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hit;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RayVsModel(const Ray& ray,
|
|
||||||
const std::vector<RawModel::Vertex>& modelVertices,
|
|
||||||
const std::vector<unsigned int>& modelIndices,
|
|
||||||
glm::vec3& outHitPosition)
|
|
||||||
{
|
|
||||||
float u;
|
|
||||||
float v;
|
|
||||||
float dist;
|
|
||||||
bool hit = RayVsModel(ray, modelVertices, modelIndices, dist, u, v);
|
|
||||||
outHitPosition = ray.Origin() + dist * ray.Direction();
|
|
||||||
return hit;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon)
|
|
||||||
{
|
|
||||||
const glm::vec3& ma1 = first.MaxCorner();
|
|
||||||
const glm::vec3& ma2 = first.MaxCorner();
|
|
||||||
const glm::vec3& mi1 = second.MinCorner();
|
|
||||||
const glm::vec3& mi2 = second.MinCorner();
|
|
||||||
return (std::abs(ma1.x - ma2.x) < epsilon) &&
|
|
||||||
(std::abs(mi1.x - mi2.x) < epsilon) &&
|
|
||||||
(std::abs(ma1.z - ma2.z) < epsilon) &&
|
|
||||||
(std::abs(mi1.z - mi2.z) < epsilon) &&
|
|
||||||
(std::abs(ma1.y - ma2.y) < epsilon) &&
|
|
||||||
(std::abs(mi1.y - mi2.y) < epsilon);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool attachAABBComponentFromModel(World* world, EntityID id)
|
|
||||||
{
|
|
||||||
if (!world->HasComponent(id, "Model")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ComponentWrapper model = world->GetComponent(id, "Model");
|
|
||||||
ComponentWrapper collision = world->AttachComponent(id, "AABB");
|
|
||||||
Model* modelRes = ResourceManager::Load<Model>(model["Resource"]);
|
|
||||||
if (modelRes == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 modelMatrix = modelRes->m_Matrix;
|
|
||||||
|
|
||||||
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;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GetEntityBox(World* world, ComponentWrapper& AABBComponent, AABB& outBox)
|
|
||||||
{
|
|
||||||
ComponentWrapper& cTrans = world->GetComponent(AABBComponent.EntityID, "Transform");
|
|
||||||
ComponentWrapper model = world->GetComponent(AABBComponent.EntityID, "Model");
|
|
||||||
Model* modelRes = ResourceManager::Load<Model>(model["Resource"]);
|
|
||||||
outBox.CreateFromCenter(AABBComponent["BoxCenter"], AABBComponent["BoxSize"]);
|
|
||||||
glm::vec3 mini = outBox.MinCorner();
|
|
||||||
glm::vec3 maxi = outBox.MaxCorner();
|
|
||||||
|
|
||||||
if (modelRes == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
glm::mat4 modelMatrix = modelRes->m_Matrix *
|
|
||||||
glm::translate(glm::mat4(), (glm::vec3)cTrans["Position"]) *
|
|
||||||
glm::scale((glm::vec3)cTrans["Scale"]);
|
|
||||||
|
|
||||||
outBox = AABB(modelMatrix * glm::vec4(mini.x, mini.y, mini.z, 1),
|
|
||||||
modelMatrix * glm::vec4(maxi.x, maxi.y, maxi.z, 1));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GetEntityBox(World* world, EntityID entity, AABB& outBox, bool forceBoxFromModel)
|
|
||||||
{
|
|
||||||
if (!world->HasComponent(entity, "AABB")) {
|
|
||||||
if (forceBoxFromModel) {
|
|
||||||
if (!attachAABBComponentFromModel(world, entity))
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ComponentWrapper& cBox = world->GetComponent(entity, "AABB");
|
|
||||||
return GetEntityBox(world, cBox, outBox);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#include "Collision/Collision.h"
|
|
||||||
#include "Collision/CollisionSystem.h"
|
|
||||||
#include "Core/AABB.h"
|
|
||||||
|
|
||||||
void CollisionSystem::UpdateComponent(World * world, ComponentWrapper & cAABB, double dt)
|
|
||||||
{
|
|
||||||
//Right now, cAABB is a component attached to any entity that should be collideable.
|
|
||||||
AABB thisBox;
|
|
||||||
if (!Collision::GetEntityBox(world, cAABB, thisBox)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//Press 'Z' to enable/disable collision.
|
|
||||||
if (zPress) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//Here, mover should be an object that moves, currently only players.
|
|
||||||
for (auto& mover : *world->GetComponents("Player")) {
|
|
||||||
if (cAABB.EntityID == mover.EntityID) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
AABB otherBox;
|
|
||||||
if (!Collision::GetEntityBox(world, mover.EntityID, otherBox)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
glm::vec3 resolveTranslation;
|
|
||||||
if (Collision::AABBVsAABB(otherBox, thisBox, resolveTranslation)) {
|
|
||||||
ComponentWrapper& trans = world->GetComponent(mover.EntityID, "Transform");
|
|
||||||
//TODO: Special treatment if both are movers.
|
|
||||||
trans["Position"] = (glm::vec3)trans["Position"] + resolveTranslation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CollisionSystem::OnKeyUp(const Events::KeyUp & event)
|
|
||||||
{
|
|
||||||
if (event.KeyCode == GLFW_KEY_Z) {
|
|
||||||
zPress = !zPress;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
#include "Collision/TriggerSystem.h"
|
|
||||||
#include "Collision/Collision.h"
|
|
||||||
#include "Core/AABB.h"
|
|
||||||
#include "Rendering/Model.h"
|
|
||||||
|
|
||||||
void TriggerSystem::UpdateComponent(World* world, ComponentWrapper& trigger, double dt)
|
|
||||||
{
|
|
||||||
//Currently only players can trigger things.
|
|
||||||
auto players = world->GetComponents("Player");
|
|
||||||
if (players == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EntityID tId = trigger.EntityID;
|
|
||||||
AABB triggerBox;
|
|
||||||
//The trigger *should* have a bounding box, or something, to test against so it can be triggered.
|
|
||||||
if (!Collision::GetEntityBox(world, tId, triggerBox, true)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (auto& pc : *players) {
|
|
||||||
EntityID pId = pc.EntityID;
|
|
||||||
AABB playerBox;
|
|
||||||
//The player can't trigger anything without an AABB.
|
|
||||||
if (!Collision::GetEntityBox(world, pId, playerBox, true)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!Collision::AABBVsAABB(triggerBox, playerBox)) {
|
|
||||||
//Entity is not touching the trigger,
|
|
||||||
//Throw event if it was previously.
|
|
||||||
if (throwLeaveIfWasInTrigger(m_EntitiesTouchingTrigger[tId], pId, tId)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//This only occurs if the entity was completely inside the trigger one frame,
|
|
||||||
//then completely outside the trigger, e.g. when dying and respawning.
|
|
||||||
throwLeaveIfWasInTrigger(m_EntitiesCompletelyInTrigger[tId], pId, tId);
|
|
||||||
} else {
|
|
||||||
//Entity is at least touching the trigger.
|
|
||||||
AABB completelyInsideBox;
|
|
||||||
completelyInsideBox.CreateFromCenter(triggerBox.Center(), triggerBox.Size() - 2.0f * playerBox.Size());
|
|
||||||
if (Collision::AABBVsAABB(completelyInsideBox, playerBox) &&
|
|
||||||
glm::all(glm::greaterThan(triggerBox.Size(), playerBox.Size()))) {
|
|
||||||
//Entity is completely inside the trigger.
|
|
||||||
//If it was only touching before, it is erased.
|
|
||||||
m_EntitiesTouchingTrigger[tId].erase(pId);
|
|
||||||
std::unordered_set<EntityID>& completeSet = m_EntitiesCompletelyInTrigger[tId];
|
|
||||||
if (completeSet.count(pId) == 0) {
|
|
||||||
//If it wasn't completely in the trigger, throw Enter and add to the set.
|
|
||||||
completeSet.insert(pId);
|
|
||||||
publish<Events::TriggerEnter>(pId, tId);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Entity is only touching the trigger.
|
|
||||||
std::unordered_set<EntityID>& touchSet = m_EntitiesTouchingTrigger[tId];
|
|
||||||
std::unordered_set<EntityID>& completeSet = m_EntitiesCompletelyInTrigger[tId];
|
|
||||||
const auto& it = completeSet.find(pId);
|
|
||||||
//If it was completely inside before.
|
|
||||||
if (it != completeSet.end()) {
|
|
||||||
completeSet.erase(it);
|
|
||||||
touchSet.insert(pId);
|
|
||||||
//If it was completely outside before.
|
|
||||||
} else if (touchSet.count(pId) == 0) {
|
|
||||||
publish<Events::TriggerTouch>(pId, tId);
|
|
||||||
touchSet.insert(pId);
|
|
||||||
}
|
|
||||||
//Else, it was touching the trigger last frame too and nothing is done.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& triggerSet, EntityID pId, EntityID tId)
|
|
||||||
{
|
|
||||||
const auto& it = triggerSet.find(pId);
|
|
||||||
if (it != triggerSet.end()) {
|
|
||||||
//If it was in the trigger, but not anymore, throw leaveEvent and erase from the set.
|
|
||||||
triggerSet.erase(it);
|
|
||||||
publish<Events::TriggerLeave>(pId, tId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#include "Core/AABB.h"
|
|
||||||
#include "Common.h"
|
|
||||||
|
|
||||||
AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos)
|
|
||||||
: m_MinCorner(minPos)
|
|
||||||
, m_MaxCorner(maxPos)
|
|
||||||
, m_Center(0.5f * (maxPos + minPos))
|
|
||||||
, m_HalfSize(0.5f * (maxPos - minPos))
|
|
||||||
{
|
|
||||||
DEBUG_IF(glm::any(glm::lessThan(m_MaxCorner, m_MinCorner))) {
|
|
||||||
LOG_WARNING("AABB maxCorner coordinates are not greater than minCorner");
|
|
||||||
m_MaxCorner.x = glm::max(m_MaxCorner.x, m_MinCorner.x);
|
|
||||||
m_MinCorner.x = glm::min(m_MaxCorner.x, m_MinCorner.x);
|
|
||||||
m_MaxCorner.y = glm::max(m_MaxCorner.y, m_MinCorner.y);
|
|
||||||
m_MinCorner.y = glm::min(m_MaxCorner.y, m_MinCorner.y);
|
|
||||||
m_MaxCorner.z = glm::max(m_MaxCorner.z, m_MinCorner.z);
|
|
||||||
m_MinCorner.z = glm::min(m_MaxCorner.z, m_MinCorner.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB::AABB(const glm::vec4& minPos, const glm::vec4& maxPos)
|
|
||||||
: AABB(glm::vec3(minPos), glm::vec3(maxPos))
|
|
||||||
{}
|
|
||||||
|
|
||||||
void AABB::CreateFromCenter(const glm::vec3& center, const glm::vec3& size)
|
|
||||||
{
|
|
||||||
m_Center = center;
|
|
||||||
m_HalfSize = 0.5f * size;
|
|
||||||
m_MinCorner = m_Center - m_HalfSize;
|
|
||||||
m_MaxCorner = m_Center + m_HalfSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB::~AABB()
|
|
||||||
{}
|
|
||||||
@@ -19,7 +19,7 @@ bool ComponentPoolForwardIterator::operator!=(const ComponentPoolForwardIterator
|
|||||||
return m_MemoryPoolIterator != other.m_MemoryPoolIterator;
|
return m_MemoryPoolIterator != other.m_MemoryPoolIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
ComponentPoolForwardIterator ComponentPoolForwardIterator::operator++(int)
|
ComponentPoolForwardIterator& ComponentPoolForwardIterator::operator++(int)
|
||||||
{
|
{
|
||||||
ComponentPoolForwardIterator copyIter(*this);
|
ComponentPoolForwardIterator copyIter(*this);
|
||||||
operator++();
|
operator++();
|
||||||
@@ -50,16 +50,10 @@ ComponentWrapper ComponentPool::GetByEntity(EntityID ent)
|
|||||||
return ComponentWrapper(m_ComponentInfo, m_EntityToComponent.at(ent));
|
return ComponentWrapper(m_ComponentInfo, m_EntityToComponent.at(ent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ComponentPool::KnowsEntity(EntityID ent)
|
|
||||||
{
|
|
||||||
return m_EntityToComponent.find(ent) != m_EntityToComponent.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ComponentPool::Delete(ComponentWrapper& wrapper)
|
void ComponentPool::Delete(ComponentWrapper& wrapper)
|
||||||
{
|
{
|
||||||
m_EntityToComponent.erase(wrapper.EntityID);
|
m_EntityToComponent.erase(wrapper.EntityID);
|
||||||
m_Pool.Free(wrapper.Data - sizeof(EntityID));
|
m_Pool.Free(wrapper.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
ComponentPool::iterator ComponentPool::begin() const
|
ComponentPool::iterator ComponentPool::begin() const
|
||||||
|
|||||||
@@ -415,7 +415,6 @@ std::size_t EntityXMLFile::getTypeStride(std::string typeName)
|
|||||||
std::map<std::string, size_t> typeStrides{
|
std::map<std::string, size_t> typeStrides{
|
||||||
{ "bool", sizeof(bool) },
|
{ "bool", sizeof(bool) },
|
||||||
{ "int", sizeof(int) },
|
{ "int", sizeof(int) },
|
||||||
{ "float", sizeof(float) },
|
|
||||||
{ "double", sizeof(double) },
|
{ "double", sizeof(double) },
|
||||||
{ "string", sizeof(std::string) },
|
{ "string", sizeof(std::string) },
|
||||||
{ "Vector", sizeof(glm::vec3) },
|
{ "Vector", sizeof(glm::vec3) },
|
||||||
@@ -431,12 +430,12 @@ float EntityXMLFile::getFloatAttribute(const xercesc::DOMElement* element, const
|
|||||||
{
|
{
|
||||||
using namespace xercesc;
|
using namespace xercesc;
|
||||||
XSValue::Status status;
|
XSValue::Status status;
|
||||||
XSValue* val = XSValue::getActualValue(element->getAttribute(XSTR(attribute)), xercesc::XSValue::DataType::dt_double, status);
|
XSValue* val = XSValue::getActualValue(element->getAttribute(XSTR(attribute)), xercesc::XSValue::DataType::dt_float, status);
|
||||||
if (val == nullptr) {
|
if (val == nullptr) {
|
||||||
LOG_ERROR("Element \"%s\" doesn't have an \"%s\" attribute!", XSTR(element->getTagName()), attribute);
|
LOG_ERROR("Element \"%s\" doesn't have an \"%s\" attribute!", XSTR(element->getTagName()), attribute);
|
||||||
return 0.f;
|
return 0.f;
|
||||||
} else {
|
} else {
|
||||||
return static_cast<float>(val->fData.fValue.f_double);
|
return val->fData.fValue.f_float;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,52 +443,39 @@ void EntityXMLFile::writeData(const xercesc::DOMElement* element, std::string ty
|
|||||||
{
|
{
|
||||||
using namespace xercesc;
|
using namespace xercesc;
|
||||||
|
|
||||||
if (typeName == "Vector") {
|
XSValue::DataType dataType = XSValue::getDataType(XSTR(typeName.c_str()));
|
||||||
glm::vec3 vec;
|
if (dataType == XSValue::DataType::dt_MAXCOUNT) {
|
||||||
vec.x = getFloatAttribute(element, "X");
|
if (typeName == "Vector") {
|
||||||
vec.y = getFloatAttribute(element, "Y");
|
glm::vec3 vec;
|
||||||
vec.z = getFloatAttribute(element, "Z");
|
vec.x = getFloatAttribute(element, "X");
|
||||||
memcpy(outData, reinterpret_cast<char*>(&vec), getTypeStride(typeName));
|
vec.y = getFloatAttribute(element, "Y");
|
||||||
} else if (typeName == "Color") {
|
vec.z = getFloatAttribute(element, "Z");
|
||||||
glm::vec4 vec;
|
memcpy(outData, reinterpret_cast<char*>(&vec), getTypeStride(typeName));
|
||||||
vec.r = getFloatAttribute(element, "R");
|
} else if (typeName == "Color") {
|
||||||
vec.g = getFloatAttribute(element, "G");
|
glm::vec4 vec;
|
||||||
vec.b = getFloatAttribute(element, "B");
|
vec.r = getFloatAttribute(element, "R");
|
||||||
vec.a = getFloatAttribute(element, "A");
|
vec.g = getFloatAttribute(element, "G");
|
||||||
memcpy(outData, reinterpret_cast<char*>(&vec), getTypeStride(typeName));
|
vec.b = getFloatAttribute(element, "B");
|
||||||
} else if (typeName == "Quaternion") {
|
vec.a = getFloatAttribute(element, "A");
|
||||||
glm::quat q;
|
memcpy(outData, reinterpret_cast<char*>(&vec), getTypeStride(typeName));
|
||||||
q.x = getFloatAttribute(element, "X");
|
} else if (typeName == "Quaternion") {
|
||||||
q.y = getFloatAttribute(element, "Y");
|
glm::quat q;
|
||||||
q.z = getFloatAttribute(element, "Z");
|
q.x = getFloatAttribute(element, "X");
|
||||||
q.w = getFloatAttribute(element, "W");
|
q.y = getFloatAttribute(element, "Y");
|
||||||
memcpy(outData, reinterpret_cast<char*>(&q), getTypeStride(typeName));
|
q.z = getFloatAttribute(element, "Z");
|
||||||
} else if (typeName == "float") {
|
q.w = getFloatAttribute(element, "W");
|
||||||
XSValue::Status status;
|
memcpy(outData, reinterpret_cast<char*>(&q), getTypeStride(typeName));
|
||||||
XSValue* val = XSValue::getActualValue(element->getTextContent(), xercesc::XSValue::DataType::dt_float, status);
|
|
||||||
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue.f_float), getTypeStride(typeName));
|
|
||||||
} else if (typeName == "double") {
|
|
||||||
XSValue::Status status;
|
|
||||||
XSValue* val = XSValue::getActualValue(element->getTextContent(), xercesc::XSValue::DataType::dt_double, status);
|
|
||||||
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue.f_double), getTypeStride(typeName));
|
|
||||||
} else if (typeName == "bool") {
|
|
||||||
XSValue::Status status;
|
|
||||||
XSValue* val = XSValue::getActualValue(element->getTextContent(), xercesc::XSValue::DataType::dt_boolean, status);
|
|
||||||
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue.f_bool), getTypeStride(typeName));
|
|
||||||
} else {
|
|
||||||
XSValue::DataType dataType = XSValue::getDataType(XSTR(typeName.c_str()));
|
|
||||||
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));
|
|
||||||
LOG_WARNING("Unknown native data type: %s", typeName.c_str());
|
|
||||||
}
|
}
|
||||||
|
} 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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,24 +2,21 @@
|
|||||||
|
|
||||||
BaseEventRelay::~BaseEventRelay()
|
BaseEventRelay::~BaseEventRelay()
|
||||||
{
|
{
|
||||||
if (m_Broker != nullptr) {
|
if (m_Broker != nullptr) {
|
||||||
m_Broker->Unsubscribe(*this);
|
m_Broker->Unsubscribe(*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventBroker::Unsubscribe(BaseEventRelay& relay) // ?
|
void EventBroker::Unsubscribe(BaseEventRelay &relay) // ?
|
||||||
{
|
{
|
||||||
auto identifier = std::make_tuple(relay.m_EventID, relay.m_ContextTypeName, relay.m_EventTypeName);
|
if (m_IsProcessing) {
|
||||||
|
m_RelaysToUnsubscribe.push_back(&relay);
|
||||||
relay.m_Broker = nullptr;
|
} else {
|
||||||
if (m_IsProcessing) {
|
unsubscribeImmediate(relay);
|
||||||
m_RelaysToUnsubscribe.push_back(identifier);
|
}
|
||||||
} else {
|
|
||||||
unsubscribeImmediate(identifier);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventBroker::Subscribe(BaseEventRelay& relay)
|
void EventBroker::Subscribe(BaseEventRelay &relay)
|
||||||
{
|
{
|
||||||
if (m_IsProcessing) {
|
if (m_IsProcessing) {
|
||||||
m_RelaysToSubscribe.push_back(&relay);
|
m_RelaysToSubscribe.push_back(&relay);
|
||||||
@@ -41,11 +38,12 @@ int EventBroker::Process(std::string contextTypeName)
|
|||||||
|
|
||||||
int eventsProcessed = 0;
|
int eventsProcessed = 0;
|
||||||
for (auto &pair : *m_EventQueueRead) {
|
for (auto &pair : *m_EventQueueRead) {
|
||||||
std::string& eventTypeName = pair.first;
|
std::string &eventTypeName = pair.first;
|
||||||
std::shared_ptr<Event> event = pair.second;
|
std::shared_ptr<Event> event = pair.second;
|
||||||
|
|
||||||
auto itpair = relays.equal_range(eventTypeName);
|
auto itpair = relays.equal_range(eventTypeName);
|
||||||
for (auto it2 = itpair.first; it2 != itpair.second; it2++) {
|
for (auto it2 = itpair.first; it2 != itpair.second; it2++)
|
||||||
|
{
|
||||||
std::string name = it2->first;
|
std::string name = it2->first;
|
||||||
BaseEventRelay* relay = it2->second;
|
BaseEventRelay* relay = it2->second;
|
||||||
relay->Receive(event);
|
relay->Receive(event);
|
||||||
@@ -62,8 +60,8 @@ int EventBroker::Process(std::string contextTypeName)
|
|||||||
m_RelaysToSubscribe.clear();
|
m_RelaysToSubscribe.clear();
|
||||||
|
|
||||||
// Process pending unsubscriptions
|
// Process pending unsubscriptions
|
||||||
for (auto& identifier : m_RelaysToUnsubscribe) {
|
for (auto& r : m_RelaysToUnsubscribe) {
|
||||||
unsubscribeImmediate(identifier);
|
unsubscribeImmediate(*r);
|
||||||
}
|
}
|
||||||
m_RelaysToUnsubscribe.clear();
|
m_RelaysToUnsubscribe.clear();
|
||||||
|
|
||||||
@@ -83,26 +81,21 @@ void EventBroker::Clear()
|
|||||||
void EventBroker::subscribeImmediate(BaseEventRelay& relay)
|
void EventBroker::subscribeImmediate(BaseEventRelay& relay)
|
||||||
{
|
{
|
||||||
relay.m_Broker = this;
|
relay.m_Broker = this;
|
||||||
relay.m_EventID = m_NextEventID++;
|
|
||||||
m_ContextRelays[relay.m_ContextTypeName].insert(std::make_pair(relay.m_EventTypeName, &relay));
|
m_ContextRelays[relay.m_ContextTypeName].insert(std::make_pair(relay.m_EventTypeName, &relay));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventBroker::unsubscribeImmediate(std::tuple<EventID, ContextTypeName_t, EventTypeName_t> identifier)
|
void EventBroker::unsubscribeImmediate(BaseEventRelay& relay)
|
||||||
{
|
{
|
||||||
EventID eventID;
|
auto contextIt = m_ContextRelays.find(relay.m_ContextTypeName);
|
||||||
ContextTypeName_t contextTypeName;
|
|
||||||
EventTypeName_t eventTypeName;
|
|
||||||
std::tie(eventID, contextTypeName, eventTypeName) = identifier;
|
|
||||||
|
|
||||||
auto contextIt = m_ContextRelays.find(contextTypeName);
|
|
||||||
if (contextIt == m_ContextRelays.end()) {
|
if (contextIt == m_ContextRelays.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto eventRelays = contextIt->second;
|
auto eventRelays = contextIt->second;
|
||||||
auto itpair = eventRelays.equal_range(eventTypeName);
|
auto itpair = eventRelays.equal_range(relay.m_EventTypeName);
|
||||||
for (auto it = itpair.first; it != itpair.second; ++it) {
|
for (auto it = itpair.first; it != itpair.second; ++it) {
|
||||||
if (it->second->m_EventID == eventID) {
|
if (it->second == &relay) {
|
||||||
|
relay.m_Broker = nullptr;
|
||||||
eventRelays.erase(it);
|
eventRelays.erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,15 @@
|
|||||||
#include "Core/InputManager.h"
|
#include "Core/InputManager.h"
|
||||||
|
|
||||||
std::vector<unsigned int> InputManager::GLFWCharCallbackQueue;
|
|
||||||
std::vector<std::pair<double, double>> InputManager::GLFWScrollCallbackQueue;
|
|
||||||
std::vector<std::string> InputManager::GLFWDropCallbackQueue;
|
|
||||||
|
|
||||||
void InputManager::Initialize()
|
void InputManager::Initialize()
|
||||||
{
|
{
|
||||||
// TODO: Gamepad
|
// TODO: Gamepad
|
||||||
//m_LastGamepadAxisState = std::array<GamepadAxisState, XUSER_MAX_COUNT>();
|
//m_LastGamepadAxisState = std::array<GamepadAxisState, XUSER_MAX_COUNT>();
|
||||||
//m_LastGamepadButtonState = std::array<GamepadButtonState, XUSER_MAX_COUNT>();
|
//m_LastGamepadButtonState = std::array<GamepadButtonState, XUSER_MAX_COUNT>();
|
||||||
glfwSetCharCallback(m_GLFWWindow, &InputManager::GLFWCharCallback);
|
|
||||||
glfwSetScrollCallback(m_GLFWWindow, &InputManager::GLFWScrollCallback);
|
|
||||||
glfwSetDropCallback(m_GLFWWindow, &InputManager::GLFWDropCallback);
|
|
||||||
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &InputManager::OnLockMouse);
|
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &InputManager::OnLockMouse);
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &InputManager::OnUnlockMouse);
|
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &InputManager::OnUnlockMouse);
|
||||||
|
|
||||||
|
//glfwSetMouseButtonCallback(m_GLFWWindow, &InputManager::GLFWMouseButtonCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::Update(double dt)
|
void InputManager::Update(double dt)
|
||||||
@@ -43,15 +38,6 @@ void InputManager::Update(double dt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keyboard text input
|
|
||||||
for (unsigned int& c : GLFWCharCallbackQueue) {
|
|
||||||
Events::KeyboardChar e;
|
|
||||||
e.Timestamp = glfwGetTime();
|
|
||||||
e.Char = c;
|
|
||||||
m_EventBroker->Publish(e);
|
|
||||||
}
|
|
||||||
GLFWCharCallbackQueue.clear();
|
|
||||||
|
|
||||||
// Mouse buttons
|
// Mouse buttons
|
||||||
for (int i = 0; i <= GLFW_MOUSE_BUTTON_LAST; ++i) {
|
for (int i = 0; i <= GLFW_MOUSE_BUTTON_LAST; ++i) {
|
||||||
m_CurrentMouseState[i] = glfwGetMouseButton(m_GLFWWindow, i);
|
m_CurrentMouseState[i] = glfwGetMouseButton(m_GLFWWindow, i);
|
||||||
@@ -89,21 +75,20 @@ void InputManager::Update(double dt)
|
|||||||
m_EventBroker->Publish(e);
|
m_EventBroker->Publish(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mouse scroll
|
// Joysticks
|
||||||
for (auto& pair : GLFWScrollCallbackQueue) {
|
//for (int i = 0; i < GLFW_JOYSTICK_LAST; i++) {
|
||||||
Events::MouseScroll e;
|
// if (glfwJoystickPresent(i) == GL_FALSE) {
|
||||||
std::tie(e.DeltaX, e.DeltaY) = pair;
|
// continue;
|
||||||
m_EventBroker->Publish(e);
|
// }
|
||||||
}
|
|
||||||
GLFWScrollCallbackQueue.clear();
|
|
||||||
|
|
||||||
// File drop
|
// int count;
|
||||||
for (auto& path : GLFWDropCallbackQueue) {
|
// const float* axes = glfwGetJoystickAxes(i, &count);
|
||||||
Events::FileDropped e;
|
// LOG_DEBUG("Controller %i NumAxes: %i", i, count);
|
||||||
e.Path = path;
|
// m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftX)] = axes[0];
|
||||||
m_EventBroker->Publish(e);
|
// m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftY)] = axes[1];
|
||||||
}
|
// m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightX)] = axes[2];
|
||||||
GLFWDropCallbackQueue.clear();
|
// m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightY)] = axes[3];
|
||||||
|
//}
|
||||||
|
|
||||||
// // Lock mouse while holding LMB
|
// // Lock mouse while holding LMB
|
||||||
// if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT])
|
// if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT])
|
||||||
@@ -123,128 +108,46 @@ void InputManager::Update(double dt)
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// TODO: Xbox360 controller
|
// TODO: Xbox360 controller
|
||||||
/*DWORD dwResult;
|
/**/
|
||||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
|
||||||
{
|
|
||||||
XINPUT_STATE state = { 0 };
|
|
||||||
// Simply get the state of the controller from XInput.
|
|
||||||
dwResult = XInputGetState(i, &state);
|
|
||||||
if (dwResult == 0)
|
|
||||||
{
|
|
||||||
if(std::abs(state.Gamepad.sThumbLX) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
|
||||||
state.Gamepad.sThumbLX = 0;
|
|
||||||
if(std::abs(state.Gamepad.sThumbLY) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
|
||||||
state.Gamepad.sThumbLY = 0;
|
|
||||||
if(std::abs(state.Gamepad.sThumbRX) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
|
||||||
state.Gamepad.sThumbRX = 0;
|
|
||||||
if(std::abs(state.Gamepad.sThumbRY) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
|
||||||
state.Gamepad.sThumbRY = 0;
|
|
||||||
if(std::abs(state.Gamepad.bLeftTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
|
||||||
state.Gamepad.bLeftTrigger = 0;
|
|
||||||
if(std::abs(state.Gamepad.bRightTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
|
||||||
state.Gamepad.bRightTrigger = 0;
|
|
||||||
|
|
||||||
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftX)] = state.Gamepad.sThumbLX / 32767.f;
|
|
||||||
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftY)] = state.Gamepad.sThumbLY / 32767.f;
|
|
||||||
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightX)] = state.Gamepad.sThumbRX / 32767.f;
|
|
||||||
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightY)] = state.Gamepad.sThumbRY / 32767.f;
|
|
||||||
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftTrigger)] = state.Gamepad.bLeftTrigger / 255.f;
|
|
||||||
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightTrigger)] = state.Gamepad.bRightTrigger / 255.f;
|
|
||||||
PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftX);
|
|
||||||
PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftY);
|
|
||||||
PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightX);
|
|
||||||
PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightY);
|
|
||||||
PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftTrigger);
|
|
||||||
PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightTrigger);
|
|
||||||
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Up)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Down)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Left)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Right)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Start)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_START);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Back)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::LeftThumb)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::RightThumb)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::LeftShoulder)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::RightShoulder)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::A)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_A);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::B)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_B);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::X)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_X);
|
|
||||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Y)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Up);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Down);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Left);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Right);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Start);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Back);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftThumb);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::RightThumb);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftShoulder);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::RightShoulder);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::A);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::B);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::X);
|
|
||||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Y);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
m_LastKeyState = m_CurrentKeyState;
|
m_LastKeyState = m_CurrentKeyState;
|
||||||
m_LastMouseState = m_CurrentMouseState;
|
m_LastMouseState = m_CurrentMouseState;
|
||||||
m_LastMouseX = m_CurrentMouseX;
|
m_LastMouseX = m_CurrentMouseX;
|
||||||
m_LastMouseY = m_CurrentMouseY;
|
m_LastMouseY = m_CurrentMouseY;
|
||||||
m_LastGamepadAxisState = m_CurrentGamepadAxisState;
|
//m_LastGamepadAxisState = m_CurrentGamepadAxisState;
|
||||||
m_LastGamepadButtonState = m_CurrentGamepadButtonState;
|
//m_LastGamepadButtonState = m_CurrentGamepadButtonState;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis)
|
void InputManager::PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis)
|
||||||
{
|
{
|
||||||
float currentValue = m_CurrentGamepadAxisState[gamepadID][static_cast<int>(axis)];
|
//float currentValue = m_CurrentGamepadAxisState[gamepadID][static_cast<int>(axis)];
|
||||||
float lastValue = m_LastGamepadAxisState[gamepadID][static_cast<int>(axis)];
|
//float lastValue = m_LastGamepadAxisState[gamepadID][static_cast<int>(axis)];
|
||||||
if (currentValue != lastValue) {
|
//if (currentValue != lastValue) {
|
||||||
Events::GamepadAxis e;
|
// Events::GamepadAxis e;
|
||||||
e.GamepadID = gamepadID;
|
// e.GamepadID = gamepadID;
|
||||||
e.Axis = axis;
|
// e.Axis = axis;
|
||||||
e.Value = currentValue;
|
// e.Value = currentValue;
|
||||||
m_EventBroker->Publish(e);
|
// m_EventBroker->Publish(e);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button)
|
void InputManager::PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button)
|
||||||
{
|
{
|
||||||
bool currentState = m_CurrentGamepadButtonState[gamepadID][static_cast<int>(button)];
|
//bool currentState = m_CurrentGamepadButtonState[gamepadID][static_cast<int>(button)];
|
||||||
float lastState = m_LastGamepadButtonState[gamepadID][static_cast<int>(button)];
|
//float lastState = m_LastGamepadButtonState[gamepadID][static_cast<int>(button)];
|
||||||
if (currentState != lastState) {
|
//if (currentState != lastState) {
|
||||||
if (currentState == true) {
|
// if (currentState == true) {
|
||||||
Events::GamepadButtonDown e;
|
// Events::GamepadButtonDown e;
|
||||||
e.GamepadID = gamepadID;
|
// e.GamepadID = gamepadID;
|
||||||
e.Button = button;
|
// e.Button = button;
|
||||||
m_EventBroker->Publish(e);
|
// m_EventBroker->Publish(e);
|
||||||
} else {
|
// } else {
|
||||||
Events::GamepadButtonUp e;
|
// Events::GamepadButtonUp e;
|
||||||
e.GamepadID = gamepadID;
|
// e.GamepadID = gamepadID;
|
||||||
e.Button = button;
|
// e.Button = button;
|
||||||
m_EventBroker->Publish(e);
|
// m_EventBroker->Publish(e);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
}
|
|
||||||
|
|
||||||
void InputManager::GLFWCharCallback(GLFWwindow* window, unsigned int c)
|
|
||||||
{
|
|
||||||
GLFWCharCallbackQueue.push_back(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void InputManager::GLFWScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
|
|
||||||
{
|
|
||||||
GLFWScrollCallbackQueue.push_back(std::make_pair(xoffset, yoffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void InputManager::GLFWDropCallback(GLFWwindow* window, int count, const char* paths[])
|
|
||||||
{
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
GLFWDropCallbackQueue.push_back(std::string(paths[i]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputManager::OnLockMouse(const Events::LockMouse &event)
|
bool InputManager::OnLockMouse(const Events::LockMouse &event)
|
||||||
|
|||||||
@@ -1,377 +0,0 @@
|
|||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <bitset>
|
|
||||||
|
|
||||||
#include "Core/OctTree.h"
|
|
||||||
#include "Collision/Collision.h"
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
//To be able to sort nodes based on distance to ray origin.
|
|
||||||
struct ChildInfo
|
|
||||||
{
|
|
||||||
int Index;
|
|
||||||
float Distance;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool isFirstLower(const ChildInfo& first, const ChildInfo& second)
|
|
||||||
{
|
|
||||||
return first.Distance < second.Distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
OctTree::OctTree()
|
|
||||||
: OctTree(AABB(), 0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
OctTree::OctTree(const AABB& octTreeBounds, int subDivisions)
|
|
||||||
: 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 (OctChild*& c : m_Children) {
|
|
||||||
c = nullptr;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
--subDivisions;
|
|
||||||
for (int i = 0; i < 8; ++i) {
|
|
||||||
glm::vec3 minPos, maxPos;
|
|
||||||
const glm::vec3& parentMin = m_Box.MinCorner();
|
|
||||||
const glm::vec3& parentMax = m_Box.MaxCorner();
|
|
||||||
const glm::vec3& parentCenter = m_Box.Center();
|
|
||||||
std::bitset<3> bits(i);
|
|
||||||
//If child is 4,5,6,7.
|
|
||||||
if (bits.test(2)) {
|
|
||||||
minPos.x = parentCenter.x;
|
|
||||||
maxPos.x = parentMax.x;
|
|
||||||
} else {
|
|
||||||
minPos.x = parentMin.x;
|
|
||||||
maxPos.x = parentCenter.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
//If child is 2,3,6,7
|
|
||||||
if (bits.test(1)) {
|
|
||||||
minPos.y = parentCenter.y;
|
|
||||||
maxPos.y = parentMax.y;
|
|
||||||
} else {
|
|
||||||
minPos.y = parentMin.y;
|
|
||||||
maxPos.y = parentCenter.y;
|
|
||||||
}
|
|
||||||
//If child is 1,3,5,7
|
|
||||||
if (bits.test(0)) {
|
|
||||||
minPos.z = parentCenter.z;
|
|
||||||
maxPos.z = parentMax.z;
|
|
||||||
} else {
|
|
||||||
minPos.z = parentMin.z;
|
|
||||||
maxPos.z = parentCenter.z;
|
|
||||||
}
|
|
||||||
m_Children[i] = new OctChild(AABB(minPos, maxPos), subDivisions, m_StaticObjectsRef, m_DynamicObjectsRef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OctTree::OctChild::~OctChild()
|
|
||||||
{
|
|
||||||
for (OctChild*& c : m_Children) {
|
|
||||||
if (c != nullptr) {
|
|
||||||
delete c;
|
|
||||||
c = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OctTree::OctChild::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const
|
|
||||||
{
|
|
||||||
if (hasChildren()) {
|
|
||||||
for (int i : childIndicesContainingBox(boxToTest)) {
|
|
||||||
if (m_Children[i]->BoxCollides(boxToTest, outBoxIntersected))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
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 (!Collision::IsSameBoxProbably(boxToTest, objBox) &&
|
|
||||||
Collision::AABBVsAABB(boxToTest, objBox)) {
|
|
||||||
outBoxIntersected = objBox;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
m_DynamicObjectsRef[i].Checked = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)) {
|
|
||||||
//If the ray shoots the tree, and it is a parent to 8 children :o
|
|
||||||
if (hasChildren()) {
|
|
||||||
//Sort children according to their distance from the ray origin.
|
|
||||||
std::vector<ChildInfo> childInfos;
|
|
||||||
childInfos.reserve(8);
|
|
||||||
for (int i = 0; i < 8; ++i) {
|
|
||||||
childInfos.push_back({ i, glm::distance(ray.Origin(), m_Children[i]->m_Box.Center()) });
|
|
||||||
}
|
|
||||||
std::sort(childInfos.begin(), childInfos.end(), isFirstLower);
|
|
||||||
//Loop through the children, starting with the one closest to the ray origin. I.e the first to be hit.
|
|
||||||
for (const ChildInfo& info : childInfos) {
|
|
||||||
if (m_Children[info.Index]->RayCollides(ray, data)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Check against boxes in the node.
|
|
||||||
float minDist = INFINITY;
|
|
||||||
bool intersected = false;
|
|
||||||
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;
|
|
||||||
return intersected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OctTree::OctChild::AddDynamicObject(const AABB& box)
|
|
||||||
{
|
|
||||||
if (hasChildren()) {
|
|
||||||
for (auto i : childIndicesContainingBox(box)) {
|
|
||||||
m_Children[i]->AddDynamicObject(box);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Since it hasn't been added yet to the real object list, the index is after the last =size.
|
|
||||||
m_DynamicObjIndices.push_back((int)m_DynamicObjectsRef.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OctTree::OctChild::AddStaticObject(const AABB& box)
|
|
||||||
{
|
|
||||||
if (hasChildren()) {
|
|
||||||
for (auto i : childIndicesContainingBox(box)) {
|
|
||||||
m_Children[i]->AddStaticObject(box);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Since it hasn't been added yet to the real object list, the index is after the last =size.
|
|
||||||
m_StaticObjIndices.push_back((int)m_StaticObjectsRef.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
size_t 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::OctChild::ClearObjects()
|
|
||||||
{
|
|
||||||
if (hasChildren()) {
|
|
||||||
for (OctChild*& c : m_Children) {
|
|
||||||
c->ClearObjects();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_DynamicObjIndices.clear();
|
|
||||||
m_StaticObjIndices.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OctTree::OctChild::ClearDynamicObjects()
|
|
||||||
{
|
|
||||||
if (hasChildren()) {
|
|
||||||
for (OctChild*& c : m_Children) {
|
|
||||||
c->ClearObjects();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_DynamicObjIndices.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//: 3 7
|
|
||||||
//:
|
|
||||||
//: 2 6
|
|
||||||
//: |
|
|
||||||
//: 1 5 \ y
|
|
||||||
//: z
|
|
||||||
//: 0 4 0 x-->
|
|
||||||
//
|
|
||||||
// child: 0 1 2 3 4 5 6 7
|
|
||||||
// x : - - - - + + + +
|
|
||||||
// y : - - + + - - + +
|
|
||||||
// z : - + - + - + - +
|
|
||||||
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::OctChild::childIndicesContainingBox(const AABB& box) const
|
|
||||||
{
|
|
||||||
int minInd = childIndexContainingPoint(box.MinCorner());
|
|
||||||
int maxInd = childIndexContainingPoint(box.MaxCorner());
|
|
||||||
//Because of the predictable ordering of the child indices,
|
|
||||||
//the number of bits set when xor:ing the indices will determine the number of children containing the box.
|
|
||||||
std::bitset<3> bits(minInd ^ maxInd);
|
|
||||||
switch (bits.count()) {
|
|
||||||
//Box contained completely in one child.
|
|
||||||
case 0:
|
|
||||||
return{ minInd };
|
|
||||||
//Two children.
|
|
||||||
case 1:
|
|
||||||
return{ minInd, maxInd };
|
|
||||||
//Four children.
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
std::vector<int> ret;
|
|
||||||
//Bit-hax to calculate the correct 4 children containing the box.
|
|
||||||
//This works because of the childrens index determine what part of
|
|
||||||
//the dimensions they are responsible for (which octant).
|
|
||||||
bits.flip();
|
|
||||||
//At this point the bits necessarily have exactly one bit set.
|
|
||||||
for (int c = 0; c < 8; ++c) {
|
|
||||||
//If the child index have the same bit set as the bits, add box to it.
|
|
||||||
if (bits.to_ulong() & c) {
|
|
||||||
ret.push_back(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
case 3: //Eight children.
|
|
||||||
return{ 0,1,2,3,4,5,6,7 };
|
|
||||||
default:
|
|
||||||
return std::vector<int>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool OctTree::OctChild::hasChildren() const
|
|
||||||
{
|
|
||||||
return m_Children[0] != nullptr;
|
|
||||||
}
|
|
||||||
@@ -100,7 +100,7 @@ Resource* ResourceManager::Load(std::string resourceType, std::string resourceNa
|
|||||||
LOG_WARNING("Hot-loading resource \"%s\"", resourceName.c_str());
|
LOG_WARNING("Hot-loading resource \"%s\"", resourceName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateResource(resourceType, resourceName, parent);
|
return CreateResource(resourceType, resourceName, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource* ResourceManager::CreateResource(std::string resourceType, std::string resourceName, Resource* parent)
|
Resource* ResourceManager::CreateResource(std::string resourceType, std::string resourceName, Resource* parent)
|
||||||
@@ -112,16 +112,10 @@ Resource* ResourceManager::CreateResource(std::string resourceType, std::string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call the factory function
|
// Call the factory function
|
||||||
Resource* resource;
|
Resource* resource = facIt->second(resourceName);
|
||||||
try {
|
// Store IDs
|
||||||
resource = facIt->second(resourceName);
|
resource->TypeID = GetTypeID(resourceType);
|
||||||
// Store IDs
|
resource->ResourceID = GetNewResourceID(resource->TypeID);
|
||||||
resource->TypeID = GetTypeID(resourceType);
|
|
||||||
resource->ResourceID = GetNewResourceID(resource->TypeID);
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
resource = nullptr;
|
|
||||||
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": %s", resourceName.c_str(), resourceType.c_str(), e.what());
|
|
||||||
}
|
|
||||||
// Cache
|
// Cache
|
||||||
m_ResourceCache[std::make_pair(resourceType, resourceName)] = resource;
|
m_ResourceCache[std::make_pair(resourceType, resourceName)] = resource;
|
||||||
m_ResourceFromName[resourceName] = resource;
|
m_ResourceFromName[resourceName] = resource;
|
||||||
|
|||||||
@@ -11,43 +11,12 @@ EntityID World::CreateEntity(EntityID parent /*= 0*/)
|
|||||||
{
|
{
|
||||||
EntityID newEntity = generateEntityID();
|
EntityID newEntity = generateEntityID();
|
||||||
m_EntityParents[newEntity] = parent;
|
m_EntityParents[newEntity] = parent;
|
||||||
m_EntityChildren.insert(std::make_pair(parent, newEntity));
|
if (parent != 0) {
|
||||||
|
m_EntityChildren.insert(std::make_pair(parent, newEntity));
|
||||||
|
}
|
||||||
return newEntity;
|
return newEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void World::DeleteEntity(EntityID entity)
|
|
||||||
{
|
|
||||||
// Delete components
|
|
||||||
for (auto& pair : m_ComponentPools) {
|
|
||||||
auto& pool = pair.second;
|
|
||||||
if (pool->KnowsEntity(entity)) {
|
|
||||||
auto& c = pool->GetByEntity(entity);
|
|
||||||
pool->Delete(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop through children
|
|
||||||
std::vector<EntityID> childrenToDelete;
|
|
||||||
auto children = m_EntityChildren.equal_range(entity);
|
|
||||||
for (auto it = children.first; it != children.second; ++it) {
|
|
||||||
childrenToDelete.push_back(it->second);
|
|
||||||
}
|
|
||||||
for (auto& child : childrenToDelete) {
|
|
||||||
DeleteEntity(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityID parent = m_EntityParents.at(entity);
|
|
||||||
m_EntityParents.erase(entity);
|
|
||||||
auto parentChildren = m_EntityChildren.equal_range(parent);
|
|
||||||
for (auto it = parentChildren.first; it != parentChildren.second; ++it) {
|
|
||||||
if (it->second == entity) {
|
|
||||||
m_EntityChildren.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void World::RegisterComponent(ComponentInfo& ci)
|
void World::RegisterComponent(ComponentInfo& ci)
|
||||||
{
|
{
|
||||||
m_ComponentPools[ci.Name] = new ComponentPool(ci);
|
m_ComponentPools[ci.Name] = new ComponentPool(ci);
|
||||||
@@ -66,27 +35,12 @@ ComponentWrapper World::AttachComponent(EntityID entity, std::string componentTy
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool World::HasComponent(EntityID entity, std::string componentType)
|
|
||||||
{
|
|
||||||
ComponentPool* pool = m_ComponentPools.at(componentType);
|
|
||||||
return pool->KnowsEntity(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
ComponentWrapper World::GetComponent(EntityID entity, std::string componentType)
|
ComponentWrapper World::GetComponent(EntityID entity, std::string componentType)
|
||||||
{
|
{
|
||||||
ComponentPool* pool = m_ComponentPools.at(componentType);
|
ComponentPool* pool = m_ComponentPools.at(componentType);
|
||||||
return pool->GetByEntity(entity);
|
return pool->GetByEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void World::DeleteComponent(EntityID entity, std::string componentType)
|
|
||||||
{
|
|
||||||
ComponentPool* pool = m_ComponentPools.at(componentType);
|
|
||||||
ComponentWrapper c = pool->GetByEntity(entity);
|
|
||||||
return pool->Delete(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ComponentPool* World::GetComponents(std::string componentType)
|
const ComponentPool* World::GetComponents(std::string componentType)
|
||||||
{
|
{
|
||||||
auto it = m_ComponentPools.find(componentType);
|
auto it = m_ComponentPools.find(componentType);
|
||||||
@@ -99,22 +53,6 @@ EntityID World::GetParent(EntityID entity)
|
|||||||
return m_EntityParents.at(entity);
|
return m_EntityParents.at(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void World::SetParent(EntityID entity, EntityID parent)
|
|
||||||
{
|
|
||||||
EntityID lastParent = m_EntityParents.at(entity);
|
|
||||||
auto parentChildren = m_EntityChildren.equal_range(lastParent);
|
|
||||||
for (auto it = parentChildren.first; it != parentChildren.second; it++) {
|
|
||||||
if (it->second == entity) {
|
|
||||||
m_EntityChildren.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_EntityParents[entity] = parent;
|
|
||||||
m_EntityChildren.insert(std::make_pair(parent, entity));
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityID World::generateEntityID()
|
EntityID World::generateEntityID()
|
||||||
{
|
{
|
||||||
// TODO: Make EntityID generation smarter
|
// TODO: Make EntityID generation smarter
|
||||||
|
|||||||
@@ -1,596 +0,0 @@
|
|||||||
#include "Editor/EditorSystem.h"
|
|
||||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
|
||||||
#include <imgui/imgui_internal.h>
|
|
||||||
|
|
||||||
EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer)
|
|
||||||
: ImpureSystem(eventBroker)
|
|
||||||
, m_Renderer(renderer)
|
|
||||||
{
|
|
||||||
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
|
|
||||||
m_Enabled = config->Get<bool>("Debug.EditorEnabled", false);
|
|
||||||
m_Visible = m_Enabled;
|
|
||||||
|
|
||||||
if (!m_Enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &EditorSystem::OnInputCommand);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorSystem::OnMouseRelease);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorSystem::OnMouseMove);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EPicking, &EditorSystem::OnPicking);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorSystem::OnFileDropped);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorSystem::Update(World* world, double dt)
|
|
||||||
{
|
|
||||||
m_World = world;
|
|
||||||
|
|
||||||
if (!m_Enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_Visible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateWidget();
|
|
||||||
|
|
||||||
drawUI(world, dt);
|
|
||||||
|
|
||||||
// Clear drop queue if it wasn't handled by any UI element
|
|
||||||
if (!m_LastDroppedFile.empty()) {
|
|
||||||
m_LastDroppedFile = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EditorSystem::OnInputCommand(const Events::InputCommand& e)
|
|
||||||
{
|
|
||||||
if (e.Command == "ToggleEditor" && e.Value > 0) {
|
|
||||||
m_Visible = !m_Visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.Command == "EditorToolMove" && e.Value > 0) {
|
|
||||||
setWidgetMode(WidgetMode::Translate);
|
|
||||||
}
|
|
||||||
if (e.Command == "EditorToolRotate" && e.Value > 0) {
|
|
||||||
setWidgetMode(WidgetMode::Rotate);
|
|
||||||
}
|
|
||||||
if (e.Command == "EditorToolScale" && e.Value > 0) {
|
|
||||||
setWidgetMode(WidgetMode::Scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.Command == "EditorToggleTransformSpace" && e.Value > 0) {
|
|
||||||
if (m_WidgetSpace == WidgetSpace::Global) {
|
|
||||||
setWidgetSpace(WidgetSpace::Local);
|
|
||||||
} else if (m_WidgetSpace == WidgetSpace::Local) {
|
|
||||||
setWidgetSpace(WidgetSpace::Global);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EditorSystem::OnMousePress(const Events::MousePress& e)
|
|
||||||
{
|
|
||||||
if (e.Button == GLFW_MOUSE_BUTTON_RIGHT) {
|
|
||||||
m_PickingQueue.push_back(glm::vec2((int)e.X, (int)e.Y));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EditorSystem::OnMouseMove(const Events::MouseMove& e)
|
|
||||||
{
|
|
||||||
if (m_Widget == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Selection == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
|
||||||
glm::vec3 widgetOrientation = widgetTransform["Orientation"];
|
|
||||||
|
|
||||||
glm::quat totalOrientation = m_Renderer->Camera()->Orientation() * glm::inverse(glm::quat(widgetOrientation));
|
|
||||||
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
glfwGetFramebufferSize(m_Renderer->Window(), &width, &height);
|
|
||||||
Rectangle res(width, height);
|
|
||||||
|
|
||||||
glm::vec2 delta2(res.Width / 2.f + e.DeltaX, res.Height / 2.f + -e.DeltaY);
|
|
||||||
glm::vec3 deltaWorld = ScreenCoords::ToWorldPos(
|
|
||||||
delta2,
|
|
||||||
m_WidgetPickingDepth,
|
|
||||||
res,
|
|
||||||
m_Renderer->Camera()->ProjectionMatrix(),
|
|
||||||
glm::toMat4(glm::inverse(totalOrientation))
|
|
||||||
);
|
|
||||||
glm::vec3 origin = ScreenCoords::ToWorldPos(
|
|
||||||
glm::vec2(res.Width / 2.f, res.Height / 2.f),
|
|
||||||
m_WidgetPickingDepth,
|
|
||||||
res,
|
|
||||||
m_Renderer->Camera()->ProjectionMatrix(),
|
|
||||||
glm::toMat4(glm::inverse(totalOrientation))
|
|
||||||
);
|
|
||||||
deltaWorld = deltaWorld - origin;
|
|
||||||
glm::vec3 movement = deltaWorld * m_WidgetCurrentAxis;
|
|
||||||
|
|
||||||
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
|
|
||||||
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
|
||||||
if (m_WidgetMode == WidgetMode::Translate) {
|
|
||||||
if (m_WidgetSpace == WidgetSpace::Global) {
|
|
||||||
EntityID parent = m_World->GetParent(m_Selection);
|
|
||||||
glm::quat inverseParentOrientation;
|
|
||||||
if (parent != 0) {
|
|
||||||
inverseParentOrientation = glm::inverse(RenderQueueFactory::AbsoluteOrientation(m_World, parent));
|
|
||||||
}
|
|
||||||
(glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Position"] += inverseParentOrientation * movement;
|
|
||||||
} else if (m_WidgetSpace == WidgetSpace::Local) {
|
|
||||||
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
|
||||||
(glm::vec3&)selectionTransform["Position"] += glm::quat((glm::vec3)selectionTransform["Orientation"]) * movement;
|
|
||||||
}
|
|
||||||
} else if (m_WidgetMode == WidgetMode::Rotate) {
|
|
||||||
glm::vec3 finalMovement;
|
|
||||||
finalMovement.x = -deltaWorld.y * m_WidgetCurrentAxis.x;
|
|
||||||
finalMovement.y = deltaWorld.x * m_WidgetCurrentAxis.y;
|
|
||||||
finalMovement.z = deltaWorld.y * m_WidgetCurrentAxis.z;
|
|
||||||
if (m_WidgetSpace == WidgetSpace::Global) {
|
|
||||||
EntityID parent = m_World->GetParent(m_Selection);
|
|
||||||
glm::quat parentOrientation;
|
|
||||||
if (parent != 0) {
|
|
||||||
parentOrientation = RenderQueueFactory::AbsoluteOrientation(m_World, parent);
|
|
||||||
}
|
|
||||||
glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"];
|
|
||||||
//glm::quat currentOrientation = RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection);
|
|
||||||
glm::quat currentOrientation = parentOrientation * glm::quat(selectionOrientation);
|
|
||||||
glm::quat deltaOrientation(finalMovement);
|
|
||||||
selectionOrientation = glm::eulerAngles(glm::inverse(parentOrientation) * (deltaOrientation * currentOrientation));
|
|
||||||
} else if (m_WidgetSpace == WidgetSpace::Local) {
|
|
||||||
glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"];
|
|
||||||
glm::quat currentOrientation(selectionOrientation);
|
|
||||||
glm::quat deltaOrientation(finalMovement);
|
|
||||||
selectionOrientation = glm::eulerAngles(currentOrientation * deltaOrientation);
|
|
||||||
}
|
|
||||||
} else if (m_WidgetMode == WidgetMode::Scale) {
|
|
||||||
glm::vec3& scaleX = m_World->GetComponent(m_WidgetX, "Transform")["Scale"];
|
|
||||||
glm::vec3& scaleY = m_World->GetComponent(m_WidgetY, "Transform")["Scale"];
|
|
||||||
glm::vec3& scaleZ = m_World->GetComponent(m_WidgetZ, "Transform")["Scale"];
|
|
||||||
|
|
||||||
if (m_WidgetCurrentAxis.x > 0 && m_WidgetCurrentAxis.y > 0 && m_WidgetCurrentAxis.z > 0) {
|
|
||||||
float movementLength = glm::length(movement);
|
|
||||||
float dot = glm::dot((glm::vec3)widgetOrientation, movement);
|
|
||||||
movement = glm::vec3(movementLength) * glm::sign(dot);
|
|
||||||
(glm::vec3&)m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] += movement;
|
|
||||||
}
|
|
||||||
if (m_WidgetCurrentAxis.x > 0) {
|
|
||||||
scaleX.x += movement.x;
|
|
||||||
}
|
|
||||||
if (m_WidgetCurrentAxis.y > 0) {
|
|
||||||
scaleY.y += movement.y;
|
|
||||||
}
|
|
||||||
if (m_WidgetCurrentAxis.z > 0) {
|
|
||||||
scaleZ.z += movement.z;
|
|
||||||
}
|
|
||||||
(glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Scale"] += movement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*LOG_DEBUG("DELTA %f", e.DeltaX);
|
|
||||||
if (e.X < 0) {
|
|
||||||
glfwSetCursorPos(m_Renderer->Window(), width - 1, e.Y);
|
|
||||||
}
|
|
||||||
if (e.X >= width) {
|
|
||||||
glfwSetCursorPos(m_Renderer->Window(), 0, e.Y);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EditorSystem::OnMouseRelease(const Events::MouseRelease& e)
|
|
||||||
{
|
|
||||||
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
|
|
||||||
m_WidgetCurrentAxis = glm::vec3(0.f);
|
|
||||||
//setWidgetMode(m_WidgetMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EditorSystem::OnPicking(const Events::Picking& e)
|
|
||||||
{
|
|
||||||
for (auto& pos : m_PickingQueue) {
|
|
||||||
auto result = e.Pick(pos);
|
|
||||||
EntityID entity = result.Entity;
|
|
||||||
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
|
|
||||||
} else {
|
|
||||||
LOG_INFO("Selected %i", entity);
|
|
||||||
if (entity != 0) {
|
|
||||||
EntityID parent = m_World->GetParent(entity);
|
|
||||||
if (parent == m_Widget) {
|
|
||||||
m_WidgetCurrentAxis = glm::vec3(
|
|
||||||
(entity == m_WidgetX) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneY || entity == m_WidgetPlaneZ),
|
|
||||||
(entity == m_WidgetY) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneZ),
|
|
||||||
(entity == m_WidgetZ) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneY)
|
|
||||||
);
|
|
||||||
m_WidgetPickingDepth = result.Depth;
|
|
||||||
|
|
||||||
//auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
|
||||||
//auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
|
||||||
//widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"];
|
|
||||||
} else {
|
|
||||||
ImGui::SetActiveID(0, nullptr);
|
|
||||||
m_Selection = entity;
|
|
||||||
setWidgetMode(m_WidgetMode);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_Selection = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_PickingQueue.clear();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool EditorSystem::OnFileDropped(const Events::FileDropped& e)
|
|
||||||
{
|
|
||||||
m_LastDroppedFile = boost::filesystem::path(e.Path).lexically_relative(boost::filesystem::current_path()).string();
|
|
||||||
std::replace(m_LastDroppedFile.begin(), m_LastDroppedFile.end(), '\\', '/');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorSystem::updateWidget()
|
|
||||||
{
|
|
||||||
if (m_Widget == 0) {
|
|
||||||
m_Widget = m_World->CreateEntity();
|
|
||||||
m_World->AttachComponent(m_Widget, "Transform");
|
|
||||||
m_WidgetX = m_World->CreateEntity(m_Widget);
|
|
||||||
m_World->AttachComponent(m_WidgetX, "Transform");
|
|
||||||
m_World->AttachComponent(m_WidgetX, "Model");
|
|
||||||
m_WidgetPlaneX = m_World->CreateEntity(m_Widget);
|
|
||||||
m_World->AttachComponent(m_WidgetPlaneX, "Transform");
|
|
||||||
m_World->AttachComponent(m_WidgetPlaneX, "Model");
|
|
||||||
m_World->GetComponent(m_WidgetPlaneX, "Model")["Resource"] = "Models/WidgetPlaneX.obj";
|
|
||||||
m_WidgetY = m_World->CreateEntity(m_Widget);
|
|
||||||
m_World->AttachComponent(m_WidgetY, "Transform");
|
|
||||||
m_World->AttachComponent(m_WidgetY, "Model");
|
|
||||||
m_WidgetPlaneY = m_World->CreateEntity(m_Widget);
|
|
||||||
m_World->AttachComponent(m_WidgetPlaneY, "Transform");
|
|
||||||
m_World->AttachComponent(m_WidgetPlaneY, "Model");
|
|
||||||
m_World->GetComponent(m_WidgetPlaneY, "Model")["Resource"] = "Models/WidgetPlaneY.obj";
|
|
||||||
m_WidgetZ = m_World->CreateEntity(m_Widget);
|
|
||||||
m_World->AttachComponent(m_WidgetZ, "Transform");
|
|
||||||
m_World->AttachComponent(m_WidgetZ, "Model");
|
|
||||||
m_WidgetPlaneZ = m_World->CreateEntity(m_Widget);
|
|
||||||
m_World->AttachComponent(m_WidgetPlaneZ, "Transform");
|
|
||||||
m_World->AttachComponent(m_WidgetPlaneZ, "Model");
|
|
||||||
m_World->GetComponent(m_WidgetPlaneZ, "Model")["Resource"] = "Models/WidgetPlaneZ.obj";
|
|
||||||
m_WidgetOrigin = m_World->CreateEntity(m_Widget);
|
|
||||||
m_World->AttachComponent(m_WidgetOrigin, "Transform");
|
|
||||||
m_World->AttachComponent(m_WidgetOrigin, "Model");
|
|
||||||
setWidgetMode(WidgetMode::Translate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Selection != 0) {
|
|
||||||
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
|
||||||
glm::vec3 selectionPosition = RenderQueueFactory::AbsolutePosition(m_World, m_Selection);
|
|
||||||
widgetTransform["Position"] = selectionPosition;
|
|
||||||
if (m_WidgetSpace == WidgetSpace::Local) {
|
|
||||||
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorSystem::setWidgetMode(WidgetMode newMode)
|
|
||||||
{
|
|
||||||
if (m_Widget == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
|
||||||
widgetTransform["Orientation"] = glm::vec3(0.f);
|
|
||||||
m_World->GetComponent(m_WidgetX, "Transform")["Scale"] = glm::vec3(1.f);
|
|
||||||
m_World->GetComponent(m_WidgetPlaneX, "Model")["Visible"] = false;
|
|
||||||
m_World->GetComponent(m_WidgetY, "Transform")["Scale"] = glm::vec3(1.f);
|
|
||||||
m_World->GetComponent(m_WidgetPlaneY, "Model")["Visible"] = false;
|
|
||||||
m_World->GetComponent(m_WidgetZ, "Transform")["Scale"] = glm::vec3(1.f);
|
|
||||||
m_World->GetComponent(m_WidgetPlaneZ, "Model")["Visible"] = false;
|
|
||||||
m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] = glm::vec3(1.f);
|
|
||||||
m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = false;
|
|
||||||
|
|
||||||
if (newMode == WidgetMode::Translate) {
|
|
||||||
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/TranslationWidgetX.obj";
|
|
||||||
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/TranslationWidgetY.obj";
|
|
||||||
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/TranslationWidgetZ.obj";
|
|
||||||
// Temporarily disabled for local space until I can figure out what's wrong with the math
|
|
||||||
if (m_WidgetSpace != WidgetSpace::Local) {
|
|
||||||
m_World->GetComponent(m_WidgetPlaneX, "Model")["Visible"] = true;
|
|
||||||
m_World->GetComponent(m_WidgetPlaneY, "Model")["Visible"] = true;
|
|
||||||
m_World->GetComponent(m_WidgetPlaneZ, "Model")["Visible"] = true;
|
|
||||||
}
|
|
||||||
if (m_Selection != 0) {
|
|
||||||
if (m_WidgetSpace == WidgetSpace::Local) {
|
|
||||||
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
|
||||||
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (newMode == WidgetMode::Scale) {
|
|
||||||
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/ScaleWidgetX.obj";
|
|
||||||
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/ScaleWidgetY.obj";
|
|
||||||
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/ScaleWidgetZ.obj";
|
|
||||||
m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = true;
|
|
||||||
m_World->GetComponent(m_WidgetOrigin, "Model")["Resource"] = "Models/ScaleWidgetOrigin.obj";
|
|
||||||
if (m_Selection != 0) {
|
|
||||||
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
|
||||||
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
|
|
||||||
}
|
|
||||||
} else if (newMode == WidgetMode::Rotate) {
|
|
||||||
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/RotationWidgetX.obj";
|
|
||||||
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/RotationWidgetY.obj";
|
|
||||||
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/RotationWidgetZ.obj";
|
|
||||||
if (m_Selection != 0) {
|
|
||||||
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
|
||||||
if (m_WidgetSpace == WidgetSpace::Local) {
|
|
||||||
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_WidgetMode = newMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void EditorSystem::setWidgetSpace(WidgetSpace space)
|
|
||||||
{
|
|
||||||
m_WidgetSpace = space;
|
|
||||||
setWidgetMode(m_WidgetMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorSystem::drawUI(World* world, double dt)
|
|
||||||
{
|
|
||||||
ImGui::ShowTestWindow();
|
|
||||||
//ImGui::ShowStyleEditor();
|
|
||||||
|
|
||||||
if (ImGui::BeginMainMenuBar()) {
|
|
||||||
if (ImGui::BeginMenu("File")) {
|
|
||||||
|
|
||||||
if (ImGui::MenuItem("New")) { }
|
|
||||||
if (ImGui::MenuItem("Open", "Ctrl+O")) { }
|
|
||||||
if (ImGui::MenuItem("Save", "Ctrl+S")) { }
|
|
||||||
if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S")) { }
|
|
||||||
ImGui::Separator();
|
|
||||||
if (ImGui::MenuItem("Close Editor", "F1")) { }
|
|
||||||
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Move")) {
|
|
||||||
setWidgetMode(WidgetMode::Translate);
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Rotate")) {
|
|
||||||
setWidgetMode(WidgetMode::Rotate);
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Scale")) {
|
|
||||||
setWidgetMode(WidgetMode::Scale);
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (m_WidgetSpace == WidgetSpace::Global) {
|
|
||||||
if (ImGui::Button("(Global)")) {
|
|
||||||
setWidgetSpace(WidgetSpace::Local);
|
|
||||||
}
|
|
||||||
} else if (m_WidgetSpace == WidgetSpace::Local) {
|
|
||||||
if (ImGui::Button("(Local)")) {
|
|
||||||
setWidgetSpace(WidgetSpace::Global);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndMainMenuBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string title = std::string("Components #") + std::to_string(m_Selection) + std::string("###Components");
|
|
||||||
if (ImGui::Begin(title.c_str())) {
|
|
||||||
if (m_Selection != 0) {
|
|
||||||
auto& pools = world->GetComponentPools();
|
|
||||||
|
|
||||||
std::vector<const char*> componentTypes;
|
|
||||||
for (auto& pair : pools) {
|
|
||||||
// Only add components the entity doesn't already have
|
|
||||||
if (!pair.second->KnowsEntity(m_Selection)) {
|
|
||||||
componentTypes.push_back(pair.first.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int item = -1;
|
|
||||||
ImGui::PushItemWidth(ImGui::GetWindowContentRegionWidth() - 5.f);
|
|
||||||
if (ImGui::Combo("", &item, componentTypes.data(), componentTypes.size())) {
|
|
||||||
if (item != -1) {
|
|
||||||
std::string chosenType = std::string(componentTypes.at(item));
|
|
||||||
world->AttachComponent(m_Selection, chosenType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
|
|
||||||
for (auto& pair : pools) {
|
|
||||||
const std::string& componentType = pair.first;
|
|
||||||
auto pool = pair.second;
|
|
||||||
if (!pool->KnowsEntity(m_Selection)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto& ci = pool->ComponentInfo();
|
|
||||||
|
|
||||||
bool deletePressed = createDeleteButton(componentType);
|
|
||||||
if (deletePressed) {
|
|
||||||
world->DeleteComponent(m_Selection, componentType);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader(componentType.c_str())) {
|
|
||||||
if (!ci.Meta.Annotation.empty()) {
|
|
||||||
ImGui::Text(ci.Meta.Annotation.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& component = world->GetComponent(m_Selection, componentType);
|
|
||||||
for (auto& pair : ci.FieldTypes) {
|
|
||||||
const std::string& field = pair.first;
|
|
||||||
const std::string& type = pair.second;
|
|
||||||
|
|
||||||
ImGui::PushID(field.c_str());
|
|
||||||
if (type == "Vector") {
|
|
||||||
auto& val = component.Property<glm::vec3>(field);
|
|
||||||
if (field == "Scale") {
|
|
||||||
ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max());
|
|
||||||
} else if (field == "Orientation") {
|
|
||||||
glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi<float>()));
|
|
||||||
if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi<float>())) {
|
|
||||||
val = tempVal;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
|
|
||||||
}
|
|
||||||
} else if (type == "Color") {
|
|
||||||
auto& val = component.Property<glm::vec4>(field);
|
|
||||||
ImGui::ColorEdit4("", glm::value_ptr(val), true);
|
|
||||||
} else if (type == "string") {
|
|
||||||
std::string& val = component.Property<std::string>(field);
|
|
||||||
char tempString[1024];
|
|
||||||
memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString)));
|
|
||||||
if (ImGui::InputText("", tempString, sizeof(tempString))) {
|
|
||||||
val = std::string(tempString);
|
|
||||||
LOG_DEBUG("%s::%s changed!", componentType.c_str(), field.c_str());
|
|
||||||
}
|
|
||||||
// DROP STUFF
|
|
||||||
if (ImGui::IsItemHovered() && !m_LastDroppedFile.empty()) {
|
|
||||||
val = m_LastDroppedFile;
|
|
||||||
m_LastDroppedFile = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (type == "double") {
|
|
||||||
float tempVal = static_cast<float>(component.Property<double>(field));
|
|
||||||
if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) {
|
|
||||||
component.SetProperty(field, static_cast<double>(tempVal));
|
|
||||||
}
|
|
||||||
} else if (type == "bool") {
|
|
||||||
auto& val = component.Property<bool>(field);
|
|
||||||
ImGui::Checkbox("", &val);
|
|
||||||
} else {
|
|
||||||
ImGui::TextDisabled(type.c_str());
|
|
||||||
}
|
|
||||||
ImGui::PopID();
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Text(field.c_str());
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("field annotation goes here");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
ImGui::End();
|
|
||||||
|
|
||||||
if (ImGui::Begin("Entitites")) {
|
|
||||||
static EntityID draggingEntity = 0;
|
|
||||||
auto entityChildren = world->GetEntityChildren();
|
|
||||||
std::function<void(EntityID)> recurse = [&](EntityID parent) {
|
|
||||||
auto range = entityChildren.equal_range(parent);
|
|
||||||
for (auto it = range.first; it != range.second; it++) {
|
|
||||||
|
|
||||||
ImVec2 pos = ImGui::GetCursorScreenPos();
|
|
||||||
float width = ImGui::GetContentRegionAvailWidth();
|
|
||||||
ImRect bb(pos + ImVec2(20, 0), pos + ImVec2(width, 13));
|
|
||||||
auto window = ImGui::GetCurrentWindow();
|
|
||||||
if (m_Selection == it->second) {
|
|
||||||
const ImU32 col = window->Color(ImGuiCol_HeaderActive);
|
|
||||||
window->DrawList->AddRectFilled(bb.Min, bb.Max, col);
|
|
||||||
}
|
|
||||||
ImGuiID id = window->GetID((std::string("#SelectButton") + std::to_string(it->second)).c_str());
|
|
||||||
bool hovered = false;
|
|
||||||
bool held = false;
|
|
||||||
if (ImGui::ButtonBehavior(bb, id, &hovered, &held)) {
|
|
||||||
m_Selection = it->second;
|
|
||||||
}
|
|
||||||
if (held) {
|
|
||||||
ImVec2 entityDragDelta = ImGui::GetMouseDragDelta(0);
|
|
||||||
if (std::abs(entityDragDelta.x) > 0 && std::abs(entityDragDelta.y) > 0) {
|
|
||||||
if (draggingEntity == 0) {
|
|
||||||
draggingEntity = it->second;
|
|
||||||
LOG_DEBUG("Started drag of entity %i", draggingEntity);
|
|
||||||
}
|
|
||||||
ImGui::SetNextWindowPos(ImGui::GetIO().MousePos + ImVec2(20, 0));
|
|
||||||
ImGui::Begin("Change parent", nullptr, ImVec2(0, 0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings);
|
|
||||||
ImGui::Text("#%i", draggingEntity);
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once);
|
|
||||||
if (ImGui::TreeNode((std::string("#") + std::to_string(it->second)).c_str())) {
|
|
||||||
if (draggingEntity != 0 && ImGui::IsItemHoveredRect() && ImGui::IsMouseReleased(0)) {
|
|
||||||
LOG_DEBUG("Changed parent of %i to %i", draggingEntity, it->second);
|
|
||||||
changeParent(draggingEntity, it->second);
|
|
||||||
draggingEntity = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::BeginPopupContextItem("item context menu")) {
|
|
||||||
if (ImGui::Button("Add")) {
|
|
||||||
EntityID entity = world->CreateEntity(it->second);
|
|
||||||
world->AttachComponent(entity, "Transform");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("Delete")) {
|
|
||||||
world->DeleteEntity(it->second);
|
|
||||||
ImGui::CloseCurrentPopup();
|
|
||||||
if (m_Selection == it->second) {
|
|
||||||
m_Selection = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
recurse(it->second);
|
|
||||||
ImGui::TreePop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
recurse(0);
|
|
||||||
}
|
|
||||||
ImGui::End();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EditorSystem::createDeleteButton(std::string componentType)
|
|
||||||
{
|
|
||||||
float width = ImGui::GetContentRegionAvailWidth();
|
|
||||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
|
||||||
auto pos = ImGui::GetCursorScreenPos() + ImVec2(width - 14.f, 1);
|
|
||||||
ImRect bb = ImRect(pos, pos + ImVec2(14.f, 14.f));
|
|
||||||
std::string idString = "#DELETE";
|
|
||||||
idString += componentType;
|
|
||||||
ImGuiID id = window->GetID(idString.c_str());
|
|
||||||
bool hovered;
|
|
||||||
bool held;
|
|
||||||
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held);
|
|
||||||
//ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton);
|
|
||||||
ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
|
||||||
window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16);
|
|
||||||
return pressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorSystem::changeParent(EntityID entity, EntityID newParent)
|
|
||||||
{
|
|
||||||
if (entity == newParent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// An entity can't be a child to one of its own children
|
|
||||||
auto children = m_World->GetEntityChildren().equal_range(entity);
|
|
||||||
for (auto it = children.first; it != children.second; it++) {
|
|
||||||
if (it->second == newParent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_World->SetParent(entity, newParent);
|
|
||||||
}
|
|
||||||
@@ -25,11 +25,13 @@ MouseInputHandler::MouseInputHandler(EventBroker* eventBroker, InputProxy* input
|
|||||||
|
|
||||||
bool MouseInputHandler::BindOrigin(std::string origin, std::string command, float value)
|
bool MouseInputHandler::BindOrigin(std::string origin, std::string command, float value)
|
||||||
{
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
auto originCode = m_OriginCodes.find(origin);
|
auto originCode = m_OriginCodes.find(origin);
|
||||||
if (originCode != m_OriginCodes.end()) {
|
if (originCode != m_OriginCodes.end()) {
|
||||||
int code = originCode->second;
|
int code = originCode->second;
|
||||||
m_Bindings[code] = std::make_tuple(command, value);
|
m_Bindings[code] = std::make_tuple(command, value);
|
||||||
return true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto originAxis = m_OriginAxes.find(origin);
|
auto originAxis = m_OriginAxes.find(origin);
|
||||||
@@ -44,10 +46,10 @@ bool MouseInputHandler::BindOrigin(std::string origin, std::string command, floa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_Axes[axis] = std::make_tuple(command, value * multiplier);
|
m_Axes[axis] = std::make_tuple(command, value * multiplier);
|
||||||
return true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
float MouseInputHandler::GetCommandValue(std::string command)
|
float MouseInputHandler::GetCommandValue(std::string command)
|
||||||
|
|||||||
@@ -0,0 +1,187 @@
|
|||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <Xinput.h>
|
||||||
|
#pragma comment(lib, "Xinput.lib")
|
||||||
|
#pragma comment(lib, "Xinput9_1_0.lib")
|
||||||
|
#include "Input/XboxControllerInputHandler.h"
|
||||||
|
|
||||||
|
XboxControllerInputHandler::XboxControllerInputHandler(EventBroker* eventBroker, InputProxy* inputProxy)
|
||||||
|
: InputHandler(eventBroker, inputProxy)
|
||||||
|
{
|
||||||
|
m_OriginButtons["GamepadUp"] = XINPUT_GAMEPAD_DPAD_UP;
|
||||||
|
m_OriginButtons["GamepadDown"] = XINPUT_GAMEPAD_DPAD_DOWN;
|
||||||
|
m_OriginButtons["GamepadLeft"] = XINPUT_GAMEPAD_DPAD_LEFT;
|
||||||
|
m_OriginButtons["GamepadRight"] = XINPUT_GAMEPAD_DPAD_RIGHT;
|
||||||
|
m_OriginButtons["GamepadStart"] = XINPUT_GAMEPAD_START;
|
||||||
|
m_OriginButtons["GamepadBack"] = XINPUT_GAMEPAD_BACK;
|
||||||
|
m_OriginButtons["GamepadLeftStick"] = XINPUT_GAMEPAD_LEFT_THUMB;
|
||||||
|
m_OriginButtons["GamepadRightStick"] = XINPUT_GAMEPAD_RIGHT_THUMB;
|
||||||
|
m_OriginButtons["GamepadLeftBumper"] = XINPUT_GAMEPAD_LEFT_SHOULDER;
|
||||||
|
m_OriginButtons["GamepadRightBumper"] = XINPUT_GAMEPAD_RIGHT_SHOULDER;
|
||||||
|
m_OriginButtons["GamepadA"] = XINPUT_GAMEPAD_A;
|
||||||
|
m_OriginButtons["GamepadB"] = XINPUT_GAMEPAD_B;
|
||||||
|
m_OriginButtons["GamepadX"] = XINPUT_GAMEPAD_X;
|
||||||
|
m_OriginButtons["GamepadY"] = XINPUT_GAMEPAD_Y;
|
||||||
|
m_OriginAxes["GamepadLeftX"] = 0;
|
||||||
|
m_OriginAxes["GamepadLeftY"] = 1;
|
||||||
|
m_OriginAxes["GamepadRightX"] = 2;
|
||||||
|
m_OriginAxes["GamepadRightY"] = 3;
|
||||||
|
m_OriginAxes["GamepadLeftTrigger"] = 4;
|
||||||
|
m_OriginAxes["GamepadRightTrigger"] = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XboxControllerInputHandler::BindOrigin(std::string origin, std::string command, float value)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
auto originIt = m_OriginButtons.find(origin);
|
||||||
|
if (originIt != m_OriginButtons.end()) {
|
||||||
|
int button = originIt->second;
|
||||||
|
m_ButtonBindings[button] = std::make_tuple(command, value);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto originAxis = m_OriginAxes.find(origin);
|
||||||
|
if (originAxis != m_OriginAxes.end()) {
|
||||||
|
char axis = originAxis->second;
|
||||||
|
float multiplier = 0.5f;
|
||||||
|
//// Sensitivity
|
||||||
|
//multiplier *= ResourceManager::Load<ConfigFile>("Input.ini")->Get<float>("Mouse.Sensitivity", 1.f);
|
||||||
|
//if (axis == 'Y') {
|
||||||
|
// if (ResourceManager::Load<ConfigFile>("Input.ini")->Get<bool>("Mouse.InvertPitch", false)) {
|
||||||
|
// multiplier *= -1.f;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
m_AxisBindings[axis] = std::make_tuple(command, value * multiplier);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XboxControllerInputHandler::Update(double dt)
|
||||||
|
{
|
||||||
|
DWORD dwResult;
|
||||||
|
for (int i = 0; i < MAX_GAMEPADS; i++) {
|
||||||
|
XINPUT_STATE state = { 0 };
|
||||||
|
// Simply get the state of the controller from XInput.
|
||||||
|
dwResult = XInputGetState(i, &state);
|
||||||
|
if (dwResult == 0) {
|
||||||
|
if (std::abs(state.Gamepad.sThumbLX) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
||||||
|
state.Gamepad.sThumbLX = 0;
|
||||||
|
if (std::abs(state.Gamepad.sThumbLY) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
||||||
|
state.Gamepad.sThumbLY = 0;
|
||||||
|
if (std::abs(state.Gamepad.sThumbRX) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
||||||
|
state.Gamepad.sThumbRX = 0;
|
||||||
|
if (std::abs(state.Gamepad.sThumbRY) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
||||||
|
state.Gamepad.sThumbRY = 0;
|
||||||
|
if (std::abs(state.Gamepad.bLeftTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||||
|
state.Gamepad.bLeftTrigger = 0;
|
||||||
|
if (std::abs(state.Gamepad.bRightTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||||
|
state.Gamepad.bRightTrigger = 0;
|
||||||
|
|
||||||
|
//m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftX)] = state.Gamepad.sThumbLX / 32767.f;
|
||||||
|
//m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftY)] = state.Gamepad.sThumbLY / 32767.f;
|
||||||
|
//m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightX)] = state.Gamepad.sThumbRX / 32767.f;
|
||||||
|
//m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightY)] = state.Gamepad.sThumbRY / 32767.f;
|
||||||
|
//m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftTrigger)] = state.Gamepad.bLeftTrigger / 255.f;
|
||||||
|
//m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightTrigger)] = state.Gamepad.bRightTrigger / 255.f;
|
||||||
|
//PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftX);
|
||||||
|
//PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftY);
|
||||||
|
//PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightX);
|
||||||
|
//PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightY);
|
||||||
|
//PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftTrigger);
|
||||||
|
//PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightTrigger);
|
||||||
|
|
||||||
|
for (auto& pair : m_OriginAxes) {
|
||||||
|
const std::string& origin = pair.first;
|
||||||
|
int axis = pair.second;
|
||||||
|
auto& binding = m_AxisBindings.find(axis);
|
||||||
|
if (binding == m_AxisBindings.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string command;
|
||||||
|
float value;
|
||||||
|
std::tie(command, value) = binding->second;
|
||||||
|
|
||||||
|
Events::InputCommand e;
|
||||||
|
e.PlayerID = -1;
|
||||||
|
e.Command = command;
|
||||||
|
e.Value = value * getAxisValue(state, axis);
|
||||||
|
m_InputProxy->Publish(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& pair : m_OriginButtons) {
|
||||||
|
auto& binding = m_ButtonBindings.find(pair.second);
|
||||||
|
if (binding == m_ButtonBindings.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string command;
|
||||||
|
float value;
|
||||||
|
std::tie(command, value) = binding->second;
|
||||||
|
bool pressed = static_cast<bool>(state.Gamepad.wButtons & binding->first);
|
||||||
|
m_CommandValues[command] = (pressed) ? value : 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Up)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Down)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Left)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Right)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Start)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_START);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Back)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::LeftThumb)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::RightThumb)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::LeftShoulder)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::RightShoulder)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::A)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_A);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::B)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_B);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::X)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_X);
|
||||||
|
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Y)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Up);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Down);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Left);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Right);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Start);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Back);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftThumb);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::RightThumb);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftShoulder);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::RightShoulder);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::A);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::B);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::X);
|
||||||
|
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float XboxControllerInputHandler::GetCommandValue(std::string command)
|
||||||
|
{
|
||||||
|
auto it = m_CommandValues.find(command);
|
||||||
|
if (it != m_CommandValues.end()) {
|
||||||
|
return m_CommandValues[command];
|
||||||
|
} else {
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float XboxControllerInputHandler::getAxisValue(XINPUT_STATE& state, int axis)
|
||||||
|
{
|
||||||
|
switch (axis) {
|
||||||
|
case 0:
|
||||||
|
return state.Gamepad.sThumbLX / 32767.f;
|
||||||
|
case 1:
|
||||||
|
return state.Gamepad.sThumbLY / 32767.f;
|
||||||
|
case 2:
|
||||||
|
return state.Gamepad.sThumbRX / 32767.f;
|
||||||
|
case 3:
|
||||||
|
return state.Gamepad.sThumbRY / 32767.f;
|
||||||
|
case 4:
|
||||||
|
return state.Gamepad.bLeftTrigger / 255.f;
|
||||||
|
case 5:
|
||||||
|
return state.Gamepad.bRightTrigger / 255.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,334 +1,11 @@
|
|||||||
#include "Network/Client.h"
|
#include "Network\Client.h"
|
||||||
|
|
||||||
using namespace boost::asio::ip;
|
Client::Client()
|
||||||
|
|
||||||
|
|
||||||
Client::Client(ConfigFile* config) : m_Socket(m_IOService)
|
|
||||||
{
|
{
|
||||||
// Default is local host
|
|
||||||
std::string address = config->Get<std::string>("Networking.Address", "127.0.0.1");
|
|
||||||
int port = config->Get<int>("Networking.Port", 13);
|
|
||||||
m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port);
|
|
||||||
// Set up network stream
|
|
||||||
m_PlayerName = config->Get<std::string>("Networking.Name", "Raptorcopter");
|
|
||||||
m_NextSnapshot.InputForward = "";
|
|
||||||
m_NextSnapshot.InputRight = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::~Client()
|
Client::~Client()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::Start(World* world, EventBroker* eventBroker)
|
|
||||||
{
|
|
||||||
m_WasStarted = true;
|
|
||||||
m_EventBroker = eventBroker;
|
|
||||||
m_World = world;
|
|
||||||
|
|
||||||
// Subscribe to events
|
|
||||||
m_EInputCommand = decltype(m_EInputCommand)(std::bind(&Client::OnInputCommand, this, std::placeholders::_1));
|
|
||||||
m_EventBroker->Subscribe(m_EInputCommand);
|
|
||||||
|
|
||||||
|
|
||||||
//while (m_PlayerName.size() > 7) {
|
|
||||||
// LOG_INFO("Please enter your name (No longer than 7 characters):");
|
|
||||||
// std::cin >> m_PlayerName;
|
|
||||||
//}
|
|
||||||
m_Socket.connect(m_ReceiverEndpoint);
|
|
||||||
LOG_INFO("I am client. BIP BOP");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::Update()
|
|
||||||
{
|
|
||||||
readFromServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::Close()
|
|
||||||
{
|
|
||||||
if (m_WasStarted) {
|
|
||||||
disconnect();
|
|
||||||
m_ThreadIsRunning = false;
|
|
||||||
m_EventBroker->Unsubscribe(m_EInputCommand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::readFromServer()
|
|
||||||
{
|
|
||||||
if (m_Socket.available()) {
|
|
||||||
bytesRead = receive(readBuf, INPUTSIZE);
|
|
||||||
if (bytesRead > 0) {
|
|
||||||
Packet packet(readBuf, bytesRead);
|
|
||||||
parseMessageType(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::clock_t currentTime = std::clock();
|
|
||||||
if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) {
|
|
||||||
if (isConnected()) {
|
|
||||||
sendSnapshotToServer();
|
|
||||||
}
|
|
||||||
previousSnapshotMessage = currentTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::sendSnapshotToServer()
|
|
||||||
{
|
|
||||||
// Reset previouse key state in snapshot.
|
|
||||||
m_NextSnapshot.InputForward = "";
|
|
||||||
m_NextSnapshot.InputRight = "";
|
|
||||||
|
|
||||||
auto player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player");
|
|
||||||
|
|
||||||
|
|
||||||
// See if any movement keys are down
|
|
||||||
// We dont care if it's overwritten by later
|
|
||||||
// if statement. Watcha gonna do, right!
|
|
||||||
if (player["Forward"]) {
|
|
||||||
m_NextSnapshot.InputForward = "+Forward";
|
|
||||||
}
|
|
||||||
if (player["Left"]) {
|
|
||||||
m_NextSnapshot.InputRight = "-Right";
|
|
||||||
}
|
|
||||||
if (player["Back"]) {
|
|
||||||
m_NextSnapshot.InputForward = "-Forward";
|
|
||||||
}
|
|
||||||
if (player["Right"]) {
|
|
||||||
m_NextSnapshot.InputRight = "+Right";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_NextSnapshot.InputForward != "") {
|
|
||||||
Packet packet(MessageType::Event, m_SendPacketID);
|
|
||||||
packet.WriteString(m_NextSnapshot.InputForward);
|
|
||||||
send(packet);
|
|
||||||
} else {
|
|
||||||
Packet packet(MessageType::Event, m_SendPacketID);
|
|
||||||
packet.WriteString("0Forward");
|
|
||||||
send(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_NextSnapshot.InputRight != "") {
|
|
||||||
Packet packet(MessageType::Event, m_SendPacketID);
|
|
||||||
packet.WriteString(m_NextSnapshot.InputRight);
|
|
||||||
send(packet);
|
|
||||||
} else {
|
|
||||||
Packet packet(MessageType::Event, m_SendPacketID);
|
|
||||||
packet.WriteString("0Right");
|
|
||||||
send(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::parseMessageType(Packet& packet)
|
|
||||||
{
|
|
||||||
int messageType = packet.ReadPrimitive<int>();
|
|
||||||
if (messageType == -1)
|
|
||||||
return;
|
|
||||||
// Read packet ID
|
|
||||||
m_PreviousPacketID = m_PacketID; // Set previous packet id
|
|
||||||
m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id
|
|
||||||
//IdentifyPacketLoss();
|
|
||||||
|
|
||||||
switch (static_cast<MessageType>(messageType)) {
|
|
||||||
case MessageType::Connect:
|
|
||||||
parseConnect(packet);
|
|
||||||
break;
|
|
||||||
case MessageType::ClientPing:
|
|
||||||
parsePing();
|
|
||||||
break;
|
|
||||||
case MessageType::ServerPing:
|
|
||||||
parseServerPing();
|
|
||||||
break;
|
|
||||||
case MessageType::Message:
|
|
||||||
break;
|
|
||||||
case MessageType::Snapshot:
|
|
||||||
parseSnapshot(packet);
|
|
||||||
break;
|
|
||||||
case MessageType::Disconnect:
|
|
||||||
break;
|
|
||||||
case MessageType::Event:
|
|
||||||
parseEventMessage(packet);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::parseConnect(Packet& packet)
|
|
||||||
{
|
|
||||||
m_PlayerID = packet.ReadPrimitive<int>();
|
|
||||||
LOG_INFO("%i: I am player: %i", m_PacketID, m_PlayerID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::parsePing()
|
|
||||||
{
|
|
||||||
m_DurationOfPingTime = 1000 * (std::clock() - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC);
|
|
||||||
LOG_INFO("%i: response time with ctime(ms): %f", m_PacketID, m_DurationOfPingTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::parseServerPing()
|
|
||||||
{
|
|
||||||
Packet packet(MessageType::ServerPing, m_SendPacketID);
|
|
||||||
packet.WriteString("Ping recieved");
|
|
||||||
send(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::parseEventMessage(Packet& packet)
|
|
||||||
{
|
|
||||||
int Id = -1;
|
|
||||||
std::string command = packet.ReadString();
|
|
||||||
if (command.find("+Player") != std::string::npos) {
|
|
||||||
Id = packet.ReadPrimitive<int>();
|
|
||||||
// Sett Player name
|
|
||||||
m_PlayerDefinitions[Id].Name = command.erase(0, 7);
|
|
||||||
} else {
|
|
||||||
LOG_INFO("%i: Event message: %s", m_PacketID, command.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::parseSnapshot(Packet& packet)
|
|
||||||
{
|
|
||||||
std::string tempName;
|
|
||||||
for (size_t i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
// We're checking for empty name for now. This might not be the best way,
|
|
||||||
// but it is to avoid sending redundant data.
|
|
||||||
tempName = packet.ReadString();
|
|
||||||
|
|
||||||
|
|
||||||
// Apply the position data read to the player entity
|
|
||||||
// New player connected on the server side
|
|
||||||
if (m_PlayerDefinitions[i].Name == "" && tempName != "") {
|
|
||||||
m_PlayerDefinitions[i].Name = tempName;
|
|
||||||
m_PlayerDefinitions[i].EntityID = createPlayer();
|
|
||||||
} else if (m_PlayerDefinitions[i].Name != "" && tempName == "") {
|
|
||||||
// Someone disconnected
|
|
||||||
// TODO: Insert code here
|
|
||||||
break;
|
|
||||||
} else if (m_PlayerDefinitions[i].Name == "" && tempName == "") {
|
|
||||||
// Not a connected player
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (m_PlayerDefinitions[i].EntityID != -1) {
|
|
||||||
|
|
||||||
// Move player to server position
|
|
||||||
int dataSize = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform").Info.Meta.Stride;
|
|
||||||
memcpy(m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform").Data, packet.ReadData(dataSize), dataSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Client::receive(char* data, size_t length)
|
|
||||||
{
|
|
||||||
boost::system::error_code error;
|
|
||||||
|
|
||||||
int bytesReceived = m_Socket.receive_from(boost
|
|
||||||
::asio::buffer((void*)data, length),
|
|
||||||
m_ReceiverEndpoint,
|
|
||||||
0, error);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
//LOG_ERROR("receive: %s", error.message().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytesReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::send(Packet& packet)
|
|
||||||
{
|
|
||||||
m_Socket.send_to(boost::asio::buffer(
|
|
||||||
packet.Data(),
|
|
||||||
packet.Size()),
|
|
||||||
m_ReceiverEndpoint, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::connect()
|
|
||||||
{
|
|
||||||
Packet packet(MessageType::Connect, m_SendPacketID);
|
|
||||||
packet.WriteString(m_PlayerName);
|
|
||||||
m_StartPingTime = std::clock();
|
|
||||||
send(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::disconnect()
|
|
||||||
{
|
|
||||||
Packet packet(MessageType::Connect, m_SendPacketID);
|
|
||||||
packet.WriteString("+Disconnect");
|
|
||||||
send(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::ping()
|
|
||||||
{
|
|
||||||
Packet packet(MessageType::Connect, m_SendPacketID);
|
|
||||||
packet.WriteString("Ping");
|
|
||||||
m_StartPingTime = std::clock();
|
|
||||||
send(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::moveMessageHead(char*& data, size_t& length, size_t stepSize)
|
|
||||||
{
|
|
||||||
data += stepSize;
|
|
||||||
length -= stepSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Client::OnInputCommand(const Events::InputCommand & e)
|
|
||||||
{
|
|
||||||
if (isConnected()) {
|
|
||||||
ComponentWrapper& player = m_World->GetComponent(m_PlayerDefinitions[m_PlayerID].EntityID, "Player");
|
|
||||||
if (e.Command == "Forward") {
|
|
||||||
if (e.Value > 0) {
|
|
||||||
(bool&)player["Forward"] = true;
|
|
||||||
(bool&)player["Back"] = false;
|
|
||||||
} else if (e.Value < 0) {
|
|
||||||
(bool&)player["Back"] = true;
|
|
||||||
(bool&)player["Forward"] = false;
|
|
||||||
} else {
|
|
||||||
(bool&)player["Forward"] = false;
|
|
||||||
(bool&)player["Back"] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (e.Command == "Right") {
|
|
||||||
if (e.Value > 0) {
|
|
||||||
(bool&)player["Right"] = true;
|
|
||||||
(bool&)player["Left"] = false;
|
|
||||||
} else if (e.Value < 0) {
|
|
||||||
(bool&)player["Left"] = true;
|
|
||||||
(bool&)player["Right"] = false;
|
|
||||||
} else {
|
|
||||||
(bool&)player["Left"] = false;
|
|
||||||
(bool&)player["Right"] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (e.Command == "ConnectToServer") { // Connect for now
|
|
||||||
connect();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Client::identifyPacketLoss()
|
|
||||||
{
|
|
||||||
// if no packets lost, difference should be equal to 1
|
|
||||||
int difference = m_PacketID - m_PreviousPacketID;
|
|
||||||
if (difference != 1) {
|
|
||||||
LOG_INFO("%i Packet(s) were lost...", difference);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Client::isConnected()
|
|
||||||
{
|
|
||||||
if (m_PlayerID != -1) {
|
|
||||||
if (m_PlayerDefinitions[m_PlayerID].EntityID != -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityID Client::createPlayer()
|
|
||||||
{
|
|
||||||
EntityID entityID = m_World->CreateEntity();
|
|
||||||
ComponentWrapper transform = m_World->AttachComponent(entityID, "Transform");
|
|
||||||
ComponentWrapper model = m_World->AttachComponent(entityID, "Model");
|
|
||||||
model["Resource"] = "Models/Core/UnitSphere.obj";
|
|
||||||
ComponentWrapper player = m_World->AttachComponent(entityID, "Player");
|
|
||||||
return entityID;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
#include "Network/Packet.h"
|
|
||||||
|
|
||||||
Packet::Packet(MessageType type, unsigned int& packetID)
|
|
||||||
{
|
|
||||||
m_Data = new char[m_MaxPacketSize];
|
|
||||||
// Create message header
|
|
||||||
// Add message type
|
|
||||||
int messageType = static_cast<int>(type);
|
|
||||||
Packet::WritePrimitive<int>(messageType);
|
|
||||||
packetID = packetID % 1000; // Packet id modulos
|
|
||||||
Packet::WritePrimitive<int>(packetID);
|
|
||||||
packetID++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create message
|
|
||||||
Packet::Packet(char* data, const int sizeOfPacket)
|
|
||||||
{
|
|
||||||
// Resize message
|
|
||||||
m_MaxPacketSize = sizeOfPacket;
|
|
||||||
// Copy data newly allocated memory
|
|
||||||
m_Data = new char[sizeOfPacket];
|
|
||||||
memcpy(m_Data, data, sizeOfPacket);
|
|
||||||
m_Offset = sizeOfPacket;
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet::~Packet()
|
|
||||||
{
|
|
||||||
delete[] m_Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Packet::WriteString(std::string str)
|
|
||||||
{
|
|
||||||
// Message, add one extra byte for null terminator
|
|
||||||
int sizeOfString = str.size() + 1;
|
|
||||||
if (m_Offset + sizeOfString > m_MaxPacketSize) {
|
|
||||||
LOG_WARNING("Package::WriteString(): Data size in packet exceeded maximum package size.\n");
|
|
||||||
}
|
|
||||||
memcpy(m_Data + m_Offset, str.data(), sizeOfString * sizeof(char));
|
|
||||||
m_Offset += sizeOfString * sizeof(char);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Packet::WriteData(char * data, int sizeOfData)
|
|
||||||
{
|
|
||||||
if (m_Offset + sizeOfData > m_MaxPacketSize) {
|
|
||||||
LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size.\n");
|
|
||||||
}
|
|
||||||
memcpy(m_Data + m_Offset, data, sizeOfData);
|
|
||||||
m_Offset += sizeOfData;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Packet::ReadString()
|
|
||||||
{
|
|
||||||
std::string returnValue(m_Data + m_ReturnDataOffset);
|
|
||||||
if (m_Offset < m_ReturnDataOffset + returnValue.size()) {
|
|
||||||
LOG_WARNING("packet ReadString(): Oh no! You are trying to remove things outside my memory kingdom");
|
|
||||||
return "PopFrontString Failed";
|
|
||||||
}
|
|
||||||
// +1 for null terminator.
|
|
||||||
m_ReturnDataOffset += returnValue.size() + 1;
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
char * Packet::ReadData(int SizeOfData)
|
|
||||||
{
|
|
||||||
if (m_Offset < m_ReturnDataOffset + SizeOfData) {
|
|
||||||
LOG_WARNING("packet ReadData(): Oh no! You are trying to remove things outside my memory kingdom");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
unsigned int oldReturnDataOffset = m_ReturnDataOffset;
|
|
||||||
m_ReturnDataOffset += SizeOfData;
|
|
||||||
return (m_Data + oldReturnDataOffset);
|
|
||||||
}
|
|
||||||
@@ -1,355 +1,11 @@
|
|||||||
#include "Network/Server.h"
|
#include "Network\Server.h"
|
||||||
|
|
||||||
Server::Server() : m_Socket(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 13))
|
Server::Server()
|
||||||
{ }
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Server::~Server()
|
Server::~Server()
|
||||||
{ }
|
|
||||||
|
|
||||||
|
|
||||||
void Server::Start(World* world, EventBroker* eventBroker)
|
|
||||||
{
|
{
|
||||||
m_World = world;
|
|
||||||
m_EventBroker = eventBroker;
|
|
||||||
for (size_t i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
m_StopTimes[i] = std::clock();
|
|
||||||
}
|
|
||||||
LOG_INFO("I am Server. BIP BOP\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::Update()
|
|
||||||
{
|
|
||||||
readFromClients();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::Close()
|
|
||||||
{
|
|
||||||
m_ThreadIsRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::readFromClients()
|
|
||||||
{
|
|
||||||
// m_ThreadIsRunning might be unnecessary but the
|
|
||||||
// program crashed if it executed m_Socket.available()
|
|
||||||
// when closing the program.
|
|
||||||
|
|
||||||
if (m_Socket.available()) {
|
|
||||||
try {
|
|
||||||
bytesRead = receive(readBuffer, INPUTSIZE);
|
|
||||||
Packet packet(readBuffer, bytesRead);
|
|
||||||
parseMessageType(packet);
|
|
||||||
} catch (const std::exception& err) {
|
|
||||||
//LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
std::clock_t currentTime = std::clock();
|
|
||||||
// Send snapshot
|
|
||||||
if (snapshotInterval < (1000 * (currentTime - previousSnapshotMessage) / (double)CLOCKS_PER_SEC)) {
|
|
||||||
sendSnapshot();
|
|
||||||
previousSnapshotMessage = currentTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send pings each
|
|
||||||
if (intervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) {
|
|
||||||
sendPing();
|
|
||||||
previousePingMessage = currentTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time out logic
|
|
||||||
if (checkTimeOutInterval < (1000 * (currentTime - timOutTimer) / (double)CLOCKS_PER_SEC)) {
|
|
||||||
checkForTimeOuts();
|
|
||||||
timOutTimer = currentTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::parseMessageType(Packet& packet)
|
|
||||||
{
|
|
||||||
int messageType = packet.ReadPrimitive<int>(); // Read what type off message was sent from server
|
|
||||||
|
|
||||||
// Read packet ID
|
|
||||||
m_PreviousPacketID = m_PacketID; // Set previous packet id
|
|
||||||
m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id
|
|
||||||
//IdentifyPacketLoss();
|
|
||||||
switch (static_cast<MessageType>(messageType)) {
|
|
||||||
case MessageType::Connect:
|
|
||||||
parseConnect(packet);
|
|
||||||
break;
|
|
||||||
case MessageType::ClientPing:
|
|
||||||
//parseClientPing();
|
|
||||||
break;
|
|
||||||
case MessageType::ServerPing:
|
|
||||||
parseServerPing();
|
|
||||||
break;
|
|
||||||
case MessageType::Message:
|
|
||||||
break;
|
|
||||||
case MessageType::Snapshot:
|
|
||||||
parseSnapshot(packet);
|
|
||||||
break;
|
|
||||||
case MessageType::Disconnect:
|
|
||||||
parseDisconnect();
|
|
||||||
break;
|
|
||||||
case MessageType::Event:
|
|
||||||
parseEvent(packet);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Server::receive(char * data, size_t length)
|
|
||||||
{
|
|
||||||
length = m_Socket.receive_from(
|
|
||||||
boost::asio::buffer((void*)data
|
|
||||||
, length)
|
|
||||||
, m_ReceiverEndpoint, 0);
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::send(Packet& packet, int playerID)
|
|
||||||
{
|
|
||||||
m_Socket.send_to(
|
|
||||||
boost::asio::buffer(packet.Data(), packet.Size()),
|
|
||||||
m_PlayerDefinitions[playerID].Endpoint,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::send(Packet & packet)
|
|
||||||
{
|
|
||||||
m_Socket.send_to(
|
|
||||||
boost::asio::buffer(
|
|
||||||
packet.Data(),
|
|
||||||
packet.Size()),
|
|
||||||
m_ReceiverEndpoint,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::moveMessageHead(char *& data, size_t & length, size_t stepSize)
|
|
||||||
{
|
|
||||||
data += stepSize;
|
|
||||||
length -= stepSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::broadcast(std::string message)
|
|
||||||
{
|
|
||||||
Packet packet(MessageType::Event, m_SendPacketID);
|
|
||||||
packet.WriteString(message);
|
|
||||||
for (int i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) {
|
|
||||||
send(packet, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::broadcast(Packet& packet)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < MAXCONNECTIONS; ++i) {
|
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) {
|
|
||||||
send(packet, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::sendSnapshot()
|
|
||||||
{
|
|
||||||
Packet packet(MessageType::Snapshot, m_SendPacketID);
|
|
||||||
for (size_t i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
|
|
||||||
// Send an empty name if there is no player connected on this position.
|
|
||||||
packet.WriteString(m_PlayerDefinitions[i].Name);
|
|
||||||
|
|
||||||
if (m_PlayerDefinitions[i].EntityID == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Pack transfrom component into data packet
|
|
||||||
auto transform = m_World->GetComponent(m_PlayerDefinitions[i].EntityID, "Transform");
|
|
||||||
packet.WriteData(transform.Data, transform.Info.Meta.Stride);
|
|
||||||
}
|
|
||||||
broadcast(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::sendPing()
|
|
||||||
{
|
|
||||||
// Prints connected players ping
|
|
||||||
for (size_t i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) {
|
|
||||||
int ping = 1000 * (m_StopTimes[i] - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC);
|
|
||||||
LOG_INFO("%i: Player %i's ping: %i", m_PacketID, i, ping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create ping message
|
|
||||||
Packet packet(MessageType::ServerPing, m_SendPacketID);
|
|
||||||
packet.WriteString("Ping from server");
|
|
||||||
// Time message
|
|
||||||
m_StartPingTime = std::clock();
|
|
||||||
// Send message
|
|
||||||
broadcast(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::checkForTimeOuts()
|
|
||||||
{
|
|
||||||
int timeOutTimeMs = 5000;
|
|
||||||
int startPing = 1000 * m_StartPingTime
|
|
||||||
/ static_cast<double>(CLOCKS_PER_SEC);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) {
|
|
||||||
int stopPing = 1000 * m_StopTimes[i]
|
|
||||||
/ static_cast<double>(CLOCKS_PER_SEC);
|
|
||||||
if (startPing > stopPing + timeOutTimeMs) {
|
|
||||||
LOG_INFO("Player %i timed out!", i);
|
|
||||||
disconnect(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::disconnect(int i)
|
|
||||||
{
|
|
||||||
broadcast("A player disconnected");
|
|
||||||
LOG_INFO("Player %i disconnected/timed out", i);
|
|
||||||
|
|
||||||
// Remove enteties and stuff
|
|
||||||
m_PlayerDefinitions[i].Endpoint = boost::asio::ip::udp::endpoint();
|
|
||||||
m_PlayerDefinitions[i].EntityID = -1;
|
|
||||||
m_PlayerDefinitions[i].Name = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::parseEvent(Packet& packet)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If no player matches the address return.
|
|
||||||
if (i >= 8)
|
|
||||||
return;
|
|
||||||
|
|
||||||
unsigned int entityId = m_PlayerDefinitions[i].EntityID;
|
|
||||||
std::string eventString = packet.ReadString();
|
|
||||||
if ("+Forward" == eventString) {
|
|
||||||
m_World->GetComponent(entityId, "Player")["Forward"] = true;
|
|
||||||
m_World->GetComponent(entityId, "Player")["Back"] = false;
|
|
||||||
} else if ("-Forward" == eventString) {
|
|
||||||
m_World->GetComponent(entityId, "Player")["Forward"] = false;
|
|
||||||
m_World->GetComponent(entityId, "Player")["Back"] = true;
|
|
||||||
} else if ("0Forward" == eventString) {
|
|
||||||
m_World->GetComponent(entityId, "Player")["Forward"] = false;
|
|
||||||
m_World->GetComponent(entityId, "Player")["Back"] = false;
|
|
||||||
}
|
|
||||||
if ("+Right" == eventString) {
|
|
||||||
m_World->GetComponent(entityId, "Player")["Left"] = false;
|
|
||||||
m_World->GetComponent(entityId, "Player")["Right"] = true;
|
|
||||||
} else if ("-Right" == eventString) {
|
|
||||||
m_World->GetComponent(entityId, "Player")["Right"] = false;
|
|
||||||
m_World->GetComponent(entityId, "Player")["Left"] = true;
|
|
||||||
} else if ("0Right" == eventString) {
|
|
||||||
m_World->GetComponent(entityId, "Player")["Right"] = false;
|
|
||||||
m_World->GetComponent(entityId, "Player")["Left"] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::parseConnect(Packet& packet)
|
|
||||||
{
|
|
||||||
LOG_INFO("Parsing connections");
|
|
||||||
// Check if player is already connected
|
|
||||||
for (int i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() == boost::asio::ip::address()) {
|
|
||||||
// Create new player
|
|
||||||
m_PlayerDefinitions[i].EntityID = createPlayer();
|
|
||||||
m_PlayerDefinitions[i].Endpoint = m_ReceiverEndpoint;
|
|
||||||
m_PlayerDefinitions[i].Name = packet.ReadString();
|
|
||||||
|
|
||||||
m_StopTimes[i] = std::clock();
|
|
||||||
|
|
||||||
LOG_INFO("Player \"%s\" connected on IP: %s", m_PlayerDefinitions[i].Name, m_PlayerDefinitions[i].Endpoint.address().to_string());
|
|
||||||
|
|
||||||
Packet packet(MessageType::Connect, m_SendPacketID);
|
|
||||||
packet.WritePrimitive<int>(i); // Player ID
|
|
||||||
|
|
||||||
send(packet, i);
|
|
||||||
|
|
||||||
// Send notification that a player has connected
|
|
||||||
std::string str = m_PacketID + "Player " + m_PlayerDefinitions[i].Name + " connected on: "
|
|
||||||
+ m_PlayerDefinitions[i].Endpoint.address().to_string();
|
|
||||||
broadcast(str);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::parseDisconnect()
|
|
||||||
{
|
|
||||||
LOG_INFO("%i: Parsing disconnect", m_PacketID);
|
|
||||||
|
|
||||||
for (int i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) {
|
|
||||||
disconnect(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::parseClientPing()
|
|
||||||
{
|
|
||||||
LOG_INFO("%i: Parsing ping", m_PacketID);
|
|
||||||
// Return ping
|
|
||||||
Packet packet(MessageType::ClientPing, m_SendPacketID);
|
|
||||||
packet.WriteString("Ping received");
|
|
||||||
send(packet); // This dosen't work for multiple users
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::parseServerPing()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()) {
|
|
||||||
m_StopTimes[i] = std::clock();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOT USED
|
|
||||||
void Server::parseSnapshot(Packet& packet)
|
|
||||||
{
|
|
||||||
// Does no logic. Returns snapshot if client request one
|
|
||||||
// The snapshot is not a real snapshot tho...
|
|
||||||
for (int i = 0; i < MAXCONNECTIONS; i++) {
|
|
||||||
if (m_PlayerDefinitions[i].Endpoint.address() != boost::asio::ip::address()) {
|
|
||||||
m_Socket.send_to(
|
|
||||||
boost::asio::buffer("I'm sending a snapshot to you guys!"),
|
|
||||||
m_PlayerDefinitions[i].Endpoint,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::identifyPacketLoss()
|
|
||||||
{
|
|
||||||
// if no packets lost, difference should be equal to 1
|
|
||||||
int difference = m_PacketID - m_PreviousPacketID;
|
|
||||||
if (difference != 1) {
|
|
||||||
LOG_INFO("%i Packet(s) were lost...", difference);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityID Server::createPlayer()
|
|
||||||
{
|
|
||||||
EntityID entityID = m_World->CreateEntity();
|
|
||||||
ComponentWrapper transform = m_World->AttachComponent(entityID, "Transform");
|
|
||||||
transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f);
|
|
||||||
ComponentWrapper model = m_World->AttachComponent(entityID, "Model");
|
|
||||||
model["Resource"] = "Models/Core/UnitSphere.obj";
|
|
||||||
model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f);
|
|
||||||
ComponentWrapper player = m_World->AttachComponent(entityID, "Player");
|
|
||||||
return entityID;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
#include "Rendering/DrawScenePass.h"
|
|
||||||
|
|
||||||
DrawScenePass::DrawScenePass(IRenderer* renderer)
|
|
||||||
{
|
|
||||||
m_Renderer = renderer;
|
|
||||||
InitializeTextures();
|
|
||||||
InitializeShaderPrograms();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawScenePass::InitializeTextures()
|
|
||||||
{
|
|
||||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawScenePass::InitializeShaderPrograms()
|
|
||||||
{
|
|
||||||
//Gör så att shaders är en resource, tex som texture classen. Konstruktorn måste vara privat.
|
|
||||||
m_BasicForwardProgram = ResourceManager::Load<ShaderProgram>("#BasicForwardProgram");
|
|
||||||
|
|
||||||
m_BasicForwardProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/BasicForward.vert.glsl")));
|
|
||||||
m_BasicForwardProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/BasicForward.frag.glsl")));
|
|
||||||
m_BasicForwardProgram->Compile();
|
|
||||||
m_BasicForwardProgram->Link();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawScenePass::Draw(RenderQueueCollection& rq)
|
|
||||||
{
|
|
||||||
//glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
GLERROR("Renderer::Draw PickingPass");
|
|
||||||
|
|
||||||
DrawScenePassState state;
|
|
||||||
|
|
||||||
|
|
||||||
//TODO: Render: Add code for more jobs than modeljobs.
|
|
||||||
for (auto &job : rq.Forward) {
|
|
||||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
|
||||||
if (modelJob) {
|
|
||||||
GLuint ShaderHandle = m_BasicForwardProgram->GetHandle();
|
|
||||||
|
|
||||||
m_BasicForwardProgram->Bind();
|
|
||||||
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix));
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix()));
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix()));
|
|
||||||
glUniform4fv(glGetUniformLocation(ShaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color));
|
|
||||||
|
|
||||||
//TODO: Renderer: bättre textur felhantering samt fler texturer stöd
|
|
||||||
if (modelJob->DiffuseTexture != nullptr) {
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture);
|
|
||||||
} else {
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindVertexArray(modelJob->Model->VAO);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
|
||||||
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GLERROR("DrawScene Error");
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#include "Rendering/DrawScenePassState.h"
|
|
||||||
|
|
||||||
|
|
||||||
DrawScenePassState::DrawScenePassState()
|
|
||||||
{
|
|
||||||
GLERROR("---");
|
|
||||||
BindFramebuffer(0);
|
|
||||||
GLERROR("---");
|
|
||||||
Enable(GL_DEPTH_TEST);
|
|
||||||
Enable(GL_CULL_FACE);
|
|
||||||
ClearColor(glm::vec4(255.f / 255, 163.f / 255, 176.f / 255, 0.f));
|
|
||||||
Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawScenePassState::~DrawScenePassState()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -48,21 +48,13 @@ void FrameBuffer::Generate()
|
|||||||
switch ((*it)->m_ResourceType) {
|
switch ((*it)->m_ResourceType) {
|
||||||
case GL_TEXTURE_2D:
|
case GL_TEXTURE_2D:
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle, 0);
|
||||||
GLERROR("FrameBuffer generate: glFramebufferTexture2D");
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case GL_RENDERBUFFER:
|
case GL_RENDERBUFFER:
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle);
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle);
|
||||||
GLERROR("FrameBuffer generate: glFramebufferRenderbuffer");
|
|
||||||
if ( (*it)->m_Attachment != GL_COLOR_ATTACHMENT0 ||
|
|
||||||
(*it)->m_Attachment != GL_DEPTH_ATTACHMENT ||
|
|
||||||
(*it)->m_Attachment != GL_STENCIL_ATTACHMENT)
|
|
||||||
{
|
|
||||||
LOG_ERROR("RenderBuffer Attachment not valid.");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLERROR("FrameBuffer generate");
|
||||||
|
|
||||||
if ((*it)->m_Attachment != GL_DEPTH_ATTACHMENT) {
|
if ((*it)->m_Attachment != GL_DEPTH_ATTACHMENT) {
|
||||||
attachments.push_back((*it)->m_Attachment);
|
attachments.push_back((*it)->m_Attachment);
|
||||||
|
|||||||
@@ -1,307 +0,0 @@
|
|||||||
#include "Rendering/ImGuiRenderPass.h"
|
|
||||||
|
|
||||||
ImGuiRenderPass::ImGuiRenderPass(IRenderer* renderer, EventBroker* eventBroker)
|
|
||||||
: m_Renderer(renderer)
|
|
||||||
, m_EventBroker(eventBroker)
|
|
||||||
{
|
|
||||||
g_Window = renderer->Window();
|
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
|
|
||||||
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
|
|
||||||
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
|
|
||||||
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
|
|
||||||
io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN;
|
|
||||||
io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP;
|
|
||||||
io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
|
|
||||||
io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
|
|
||||||
io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
|
|
||||||
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
|
|
||||||
io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
|
|
||||||
io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER;
|
|
||||||
io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE;
|
|
||||||
io.KeyMap[ImGuiKey_A] = GLFW_KEY_A;
|
|
||||||
io.KeyMap[ImGuiKey_C] = GLFW_KEY_C;
|
|
||||||
io.KeyMap[ImGuiKey_V] = GLFW_KEY_V;
|
|
||||||
io.KeyMap[ImGuiKey_X] = GLFW_KEY_X;
|
|
||||||
io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y;
|
|
||||||
io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z;
|
|
||||||
|
|
||||||
ImGuiStyle& style = ImGui::GetStyle();
|
|
||||||
style.Alpha = 1.f;
|
|
||||||
style.WindowPadding = ImVec2(8.f, 7.f);
|
|
||||||
style.WindowRounding = 4.f;
|
|
||||||
style.ChildWindowRounding = 0.f;
|
|
||||||
style.FramePadding = ImVec2(4.f, 2.f);
|
|
||||||
style.FrameRounding = 2.f;
|
|
||||||
style.ItemSpacing = ImVec2(6.f, 2.f);
|
|
||||||
style.ItemInnerSpacing = ImVec2(3.f, 4.f);
|
|
||||||
style.IndentSpacing = 16.f;
|
|
||||||
style.ScrollbarSize = 12;
|
|
||||||
style.ScrollbarRounding = 2.f;
|
|
||||||
style.GrabMinSize = 13.f;
|
|
||||||
style.GrabRounding = 3.f;
|
|
||||||
|
|
||||||
createDeviceObjects();
|
|
||||||
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &ImGuiRenderPass::OnMousePress);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &ImGuiRenderPass::OnMouseRelease);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &ImGuiRenderPass::OnMouseMove);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EMouseScroll, &ImGuiRenderPass::OnMouseScroll);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &ImGuiRenderPass::OnKeyDown);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &ImGuiRenderPass::OnKeyUp);
|
|
||||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyboardChar, &ImGuiRenderPass::OnKeyboardChar);
|
|
||||||
|
|
||||||
// Prime the first frame
|
|
||||||
newFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGuiRenderPass::Update(double dt)
|
|
||||||
{
|
|
||||||
g_DeltaTime = dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGuiRenderPass::Draw()
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
|
|
||||||
ImGui::Render();
|
|
||||||
|
|
||||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
|
||||||
|
|
||||||
// Set up render state
|
|
||||||
ImGuiRenderState state;
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
|
|
||||||
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
|
|
||||||
float fb_height = io.DisplaySize.y * io.DisplayFramebufferScale.y;
|
|
||||||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
|
||||||
|
|
||||||
// Setup viewport, orthographic projection matrix
|
|
||||||
glViewport(0, 0, (GLsizei)io.DisplaySize.x, (GLsizei)io.DisplaySize.y);
|
|
||||||
const float ortho_projection[4][4] =
|
|
||||||
{
|
|
||||||
{ 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f },
|
|
||||||
{ 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f },
|
|
||||||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
|
||||||
{ -1.0f, 1.0f, 0.0f, 1.0f },
|
|
||||||
};
|
|
||||||
glUseProgram(g_ShaderHandle);
|
|
||||||
glUniform1i(g_AttribLocationTex, 0);
|
|
||||||
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
|
||||||
glBindVertexArray(g_VaoHandle);
|
|
||||||
|
|
||||||
for (int n = 0; n < draw_data->CmdListsCount; n++) {
|
|
||||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
|
||||||
const ImDrawIdx* idx_buffer_offset = 0;
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.size() * sizeof(ImDrawVert), (GLvoid*)&cmd_list->VtxBuffer.front(), GL_STREAM_DRAW);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx), (GLvoid*)&cmd_list->IdxBuffer.front(), GL_STREAM_DRAW);
|
|
||||||
|
|
||||||
for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) {
|
|
||||||
if (pcmd->UserCallback) {
|
|
||||||
pcmd->UserCallback(cmd_list, pcmd);
|
|
||||||
} else {
|
|
||||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
|
||||||
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
|
||||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
|
||||||
}
|
|
||||||
idx_buffer_offset += pcmd->ElemCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start next frame
|
|
||||||
newFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGuiRenderPass::OnMousePress(const Events::MousePress& e)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.MouseDown[e.Button] = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGuiRenderPass::OnMouseRelease(const Events::MouseRelease& e)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.MouseDown[e.Button] = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGuiRenderPass::OnMouseMove(const Events::MouseMove& e)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.MousePos.x = e.X;
|
|
||||||
io.MousePos.y = e.Y;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGuiRenderPass::OnMouseScroll(const Events::MouseScroll& e)
|
|
||||||
{
|
|
||||||
g_MouseWheel += (float)e.DeltaY;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGuiRenderPass::OnKeyDown(const Events::KeyDown& e)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.KeysDown[e.KeyCode] = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGuiRenderPass::OnKeyUp(const Events::KeyUp& e)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
io.KeysDown[e.KeyCode] = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGuiRenderPass::OnKeyboardChar(const Events::KeyboardChar& e)
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
if (e.Char > 0 && e.Char < 0x10000) {
|
|
||||||
io.AddInputCharacter((unsigned short)e.Char);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGuiRenderPass::createDeviceObjects()
|
|
||||||
{
|
|
||||||
// Backup GL state
|
|
||||||
GLint last_texture, last_array_buffer, last_vertex_array;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
|
||||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
|
||||||
|
|
||||||
const GLchar *vertex_shader =
|
|
||||||
"#version 330\n"
|
|
||||||
"uniform mat4 ProjMtx;\n"
|
|
||||||
"in vec2 Position;\n"
|
|
||||||
"in vec2 UV;\n"
|
|
||||||
"in vec4 Color;\n"
|
|
||||||
"out vec2 Frag_UV;\n"
|
|
||||||
"out vec4 Frag_Color;\n"
|
|
||||||
"void main()\n"
|
|
||||||
"{\n"
|
|
||||||
" Frag_UV = UV;\n"
|
|
||||||
" Frag_Color = Color;\n"
|
|
||||||
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
const GLchar* fragment_shader =
|
|
||||||
"#version 330\n"
|
|
||||||
"uniform sampler2D Texture;\n"
|
|
||||||
"in vec2 Frag_UV;\n"
|
|
||||||
"in vec4 Frag_Color;\n"
|
|
||||||
"out vec4 Out_Color;\n"
|
|
||||||
"void main()\n"
|
|
||||||
"{\n"
|
|
||||||
" Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
g_ShaderHandle = glCreateProgram();
|
|
||||||
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
|
|
||||||
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
glShaderSource(g_VertHandle, 1, &vertex_shader, 0);
|
|
||||||
glShaderSource(g_FragHandle, 1, &fragment_shader, 0);
|
|
||||||
glCompileShader(g_VertHandle);
|
|
||||||
glCompileShader(g_FragHandle);
|
|
||||||
glAttachShader(g_ShaderHandle, g_VertHandle);
|
|
||||||
glAttachShader(g_ShaderHandle, g_FragHandle);
|
|
||||||
glLinkProgram(g_ShaderHandle);
|
|
||||||
|
|
||||||
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
|
|
||||||
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
|
|
||||||
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
|
|
||||||
g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
|
|
||||||
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
|
|
||||||
|
|
||||||
glGenBuffers(1, &g_VboHandle);
|
|
||||||
glGenBuffers(1, &g_ElementsHandle);
|
|
||||||
|
|
||||||
glGenVertexArrays(1, &g_VaoHandle);
|
|
||||||
glBindVertexArray(g_VaoHandle);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
|
||||||
glEnableVertexAttribArray(g_AttribLocationPosition);
|
|
||||||
glEnableVertexAttribArray(g_AttribLocationUV);
|
|
||||||
glEnableVertexAttribArray(g_AttribLocationColor);
|
|
||||||
|
|
||||||
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
|
|
||||||
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos));
|
|
||||||
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv));
|
|
||||||
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
|
|
||||||
#undef OFFSETOF
|
|
||||||
|
|
||||||
createFontsTexture();
|
|
||||||
|
|
||||||
// Restore modified GL state
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
|
||||||
glBindVertexArray(last_vertex_array);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGuiRenderPass::createFontsTexture()
|
|
||||||
{
|
|
||||||
// Build texture atlas
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
|
|
||||||
io.Fonts->AddFontFromFileTTF("Fonts/DroidSans.ttf", 13.f);
|
|
||||||
//io.Fonts->AddFontFromFileTTF("Fonts/ProggyClean.ttf", 13.f);
|
|
||||||
//io.Fonts->AddFontFromFileTTF("Fonts/ProggyTiny.ttf", 10.f);
|
|
||||||
//io.Fonts->AddFontFromFileTTF("Fonts/Karla-Regular.ttf", 15.0f);
|
|
||||||
|
|
||||||
unsigned char* pixels;
|
|
||||||
int width, height;
|
|
||||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader.
|
|
||||||
|
|
||||||
// Upload texture to graphics system
|
|
||||||
GLint last_texture;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
|
||||||
glGenTextures(1, &g_FontTexture);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
|
||||||
|
|
||||||
// Store our identifier
|
|
||||||
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
|
||||||
|
|
||||||
// Restore state
|
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGuiRenderPass::newFrame()
|
|
||||||
{
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
|
|
||||||
// Setup display size (every frame to accommodate for window resizing)
|
|
||||||
int w, h;
|
|
||||||
int display_w, display_h;
|
|
||||||
glfwGetWindowSize(g_Window, &w, &h);
|
|
||||||
glfwGetFramebufferSize(g_Window, &display_w, &display_h);
|
|
||||||
io.DisplaySize = ImVec2((float)w, (float)h);
|
|
||||||
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
|
|
||||||
|
|
||||||
io.DeltaTime = g_DeltaTime;
|
|
||||||
|
|
||||||
io.KeyCtrl = glfwGetKey(g_Window, GLFW_KEY_LEFT_CONTROL) || glfwGetKey(g_Window, GLFW_KEY_RIGHT_CONTROL);
|
|
||||||
io.KeyShift = glfwGetKey(g_Window, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(g_Window, GLFW_KEY_RIGHT_SHIFT);
|
|
||||||
io.KeyAlt = glfwGetKey(g_Window, GLFW_KEY_LEFT_ALT) || glfwGetKey(g_Window, GLFW_KEY_RIGHT_ALT);
|
|
||||||
|
|
||||||
io.MouseWheel = g_MouseWheel;
|
|
||||||
g_MouseWheel = 0;
|
|
||||||
|
|
||||||
m_EventBroker->Process<ImGuiRenderPass>();
|
|
||||||
|
|
||||||
ImGui::NewFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
#include "Rendering/PickingPass.h"
|
|
||||||
|
|
||||||
PickingPass::PickingPass(IRenderer* renderer, EventBroker* eb)
|
|
||||||
{
|
|
||||||
m_Renderer = renderer;
|
|
||||||
m_EventBroker = eb;
|
|
||||||
|
|
||||||
InitializeTextures();
|
|
||||||
InitializeFrameBuffers();
|
|
||||||
InitializeShaderPrograms();
|
|
||||||
}
|
|
||||||
|
|
||||||
PickingPass::~PickingPass()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void PickingPass::InitializeTextures()
|
|
||||||
{
|
|
||||||
GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR,
|
|
||||||
glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PickingPass::InitializeFrameBuffers()
|
|
||||||
{
|
|
||||||
glGenRenderbuffers(1, &m_DepthBuffer);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer);
|
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
|
||||||
|
|
||||||
m_PickingBuffer.AddResource(std::shared_ptr<BufferResource>(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT)));
|
|
||||||
m_PickingBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_PickingTexture, GL_COLOR_ATTACHMENT0)));
|
|
||||||
m_PickingBuffer.Generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PickingPass::InitializeShaderPrograms()
|
|
||||||
{
|
|
||||||
m_PickingProgram = ResourceManager::Load<ShaderProgram>("#PickingProgram");
|
|
||||||
|
|
||||||
m_PickingProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Picking.vert.glsl")));
|
|
||||||
m_PickingProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Picking.frag.glsl")));
|
|
||||||
m_PickingProgram->Compile();
|
|
||||||
m_PickingProgram->BindFragDataLocation(0, "TextureFragment");
|
|
||||||
m_PickingProgram->Link();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PickingPass::Draw(RenderQueueCollection& rq)
|
|
||||||
{
|
|
||||||
m_PickingColorsToEntity.clear();
|
|
||||||
PickingPassState* state = new PickingPassState(m_PickingBuffer.GetHandle());
|
|
||||||
|
|
||||||
int r = 0;
|
|
||||||
int g = 0;
|
|
||||||
//TODO: Render: Add code for more jobs than modeljobs.
|
|
||||||
|
|
||||||
GLuint ShaderHandle = m_PickingProgram->GetHandle();
|
|
||||||
m_PickingProgram->Bind();
|
|
||||||
|
|
||||||
std::map<EntityID, glm::vec2> entityColors;
|
|
||||||
|
|
||||||
for (auto &job : rq.Forward) {
|
|
||||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
|
||||||
|
|
||||||
if (modelJob) {
|
|
||||||
int pickColor[2] = { r, g };
|
|
||||||
auto color = entityColors.find(modelJob->Entity);
|
|
||||||
if (color != entityColors.end()) {
|
|
||||||
pickColor[0] = color->second[0];
|
|
||||||
pickColor[1] = color->second[1];
|
|
||||||
} else {
|
|
||||||
entityColors[modelJob->Entity] = glm::vec2(pickColor[0], pickColor[1]);
|
|
||||||
if (r + 10 > 255) {
|
|
||||||
r = 0;
|
|
||||||
g += 1;
|
|
||||||
} else {
|
|
||||||
r += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_PickingColorsToEntity[glm::vec2(pickColor[0], pickColor[1])] = modelJob->Entity;
|
|
||||||
|
|
||||||
//Render picking stuff
|
|
||||||
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix));
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix()));
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix()));
|
|
||||||
glUniform2fv(glGetUniformLocation(ShaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
|
||||||
|
|
||||||
glBindVertexArray(modelJob->Model->VAO);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
|
||||||
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, nullptr, modelJob->StartIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_PickingBuffer.Unbind();
|
|
||||||
GLERROR("PickingPass Error");
|
|
||||||
|
|
||||||
//Publish pick event every frame with the pick data that can be picked by the event
|
|
||||||
int fbWidth;
|
|
||||||
int fbHeight;
|
|
||||||
glfwGetFramebufferSize(m_Renderer->Window(), &fbWidth, &fbHeight);
|
|
||||||
Events::Picking pickEvent = Events::Picking(
|
|
||||||
&m_PickingBuffer,
|
|
||||||
&m_DepthBuffer,
|
|
||||||
m_Renderer->Camera()->ProjectionMatrix(),
|
|
||||||
m_Renderer->Camera()->ViewMatrix(),
|
|
||||||
Rectangle(fbWidth, fbHeight),
|
|
||||||
&m_PickingColorsToEntity);
|
|
||||||
|
|
||||||
m_EventBroker->Publish(pickEvent);
|
|
||||||
|
|
||||||
delete state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PickingPass::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const
|
|
||||||
{
|
|
||||||
//TODO: Renderer: Make this in a sparate class
|
|
||||||
glGenTextures(1, texture);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, *texture);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, dimensions.x, dimensions.y, 0, format, type, nullptr);//TODO: Renderer: Fix the precision and Resolution
|
|
||||||
GLERROR("Texture initialization failed");
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#include "Rendering/PickingPassState.h"
|
|
||||||
|
|
||||||
|
|
||||||
PickingPassState::PickingPassState(GLuint frameBuffer)
|
|
||||||
{
|
|
||||||
GLERROR("---2");
|
|
||||||
BindFramebuffer(frameBuffer);
|
|
||||||
GLERROR("---3");
|
|
||||||
Enable(GL_DEPTH_TEST);
|
|
||||||
Enable(GL_CULL_FACE);
|
|
||||||
|
|
||||||
glm::vec4 clearColor = glm::vec4(0.f);
|
|
||||||
ClearColor(clearColor);
|
|
||||||
Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
PickingPassState::~PickingPassState()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,7 @@ RawModel::RawModel(std::string fileName)
|
|||||||
if (scene == nullptr) {
|
if (scene == nullptr) {
|
||||||
LOG_ERROR("Failed to load model \"%s\"", fileName.c_str());
|
LOG_ERROR("Failed to load model \"%s\"", fileName.c_str());
|
||||||
LOG_ERROR("Assimp error: %s", importer.GetErrorString());
|
LOG_ERROR("Assimp error: %s", importer.GetErrorString());
|
||||||
throw std::runtime_error("Failed to open model file.");
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto m = scene->mRootNode->mTransformation;
|
auto m = scene->mRootNode->mTransformation;
|
||||||
@@ -76,15 +76,13 @@ RawModel::RawModel(std::string fileName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Material diffuse color
|
// Material diffuse color
|
||||||
aiColor3D diffuse;
|
aiColor4D diffuse;
|
||||||
material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
|
material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
|
||||||
float opacity;
|
desc.DiffuseVertexColor = glm::vec4(diffuse.r, diffuse.g, diffuse.b, diffuse.a);
|
||||||
material->Get(AI_MATKEY_OPACITY, opacity);
|
|
||||||
desc.DiffuseVertexColor = glm::vec4(diffuse.r, diffuse.g, diffuse.b, opacity);
|
|
||||||
// Material specular color
|
// Material specular color
|
||||||
aiColor3D specular;
|
aiColor4D specular;
|
||||||
material->Get(AI_MATKEY_COLOR_SPECULAR, specular);
|
material->Get(AI_MATKEY_COLOR_SPECULAR, specular);
|
||||||
desc.SpecularVertexColor = glm::vec4(specular.r, specular.g, specular.b, 1.f);
|
desc.SpecularVertexColor = glm::vec4(specular.r, specular.g, specular.b, specular.a);
|
||||||
|
|
||||||
m_Vertices.push_back(desc);
|
m_Vertices.push_back(desc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,19 +23,15 @@ glm::mat4 RenderQueueFactory::ModelMatrix(World* world, EntityID entity)
|
|||||||
return modelMatrix;
|
return modelMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
glm::vec3 RenderQueueFactory::AbsolutePosition(World* world, EntityID entity)
|
glm::vec3 RenderQueueFactory::AbsolutePosition(World* world, EntityID entity)
|
||||||
{
|
{
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ComponentWrapper transform = world->GetComponent(entity, "Transform");
|
ComponentWrapper transform = world->GetComponent(entity, "Transform");
|
||||||
EntityID parent = world->GetParent(entity);
|
position += (glm::vec3)transform["Position"];
|
||||||
if (parent != 0) {
|
entity = world->GetParent(entity);
|
||||||
position += AbsoluteOrientation(world, parent) * (glm::vec3)transform["Position"];
|
|
||||||
} else {
|
|
||||||
position += (glm::vec3)transform["Position"];
|
|
||||||
}
|
|
||||||
entity = parent;
|
|
||||||
} while (entity != 0);
|
} while (entity != 0);
|
||||||
|
|
||||||
return position;
|
return position;
|
||||||
@@ -56,15 +52,15 @@ glm::quat RenderQueueFactory::AbsoluteOrientation(World* world, EntityID entity)
|
|||||||
|
|
||||||
glm::vec3 RenderQueueFactory::AbsoluteScale(World* world, EntityID entity)
|
glm::vec3 RenderQueueFactory::AbsoluteScale(World* world, EntityID entity)
|
||||||
{
|
{
|
||||||
glm::vec3 scale(1.f);
|
ComponentWrapper transform = world->GetComponent(entity, "Transform");
|
||||||
|
glm::vec3 scale = (glm::vec3)transform["Scale"];
|
||||||
|
|
||||||
do {
|
EntityID parent = world->GetParent(entity);
|
||||||
ComponentWrapper transform = world->GetComponent(entity, "Transform");
|
if (parent != 0) {
|
||||||
scale *= (glm::vec3)transform["Scale"];
|
return AbsoluteScale(world, parent) * scale;
|
||||||
entity = world->GetParent(entity);
|
} else {
|
||||||
} while (entity != 0);
|
return scale;
|
||||||
|
}
|
||||||
return scale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderQueueFactory::FillModels(World* world, RenderQueue* renderQueue)
|
void RenderQueueFactory::FillModels(World* world, RenderQueue* renderQueue)
|
||||||
@@ -75,19 +71,12 @@ void RenderQueueFactory::FillModels(World* world, RenderQueue* renderQueue)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto& modelC : *models) {
|
for (auto& modelC : *models) {
|
||||||
bool visible = modelC["Visible"];
|
|
||||||
if (!visible) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::string resource = modelC["Resource"];
|
std::string resource = modelC["Resource"];
|
||||||
if (resource.empty()) {
|
if (resource.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
glm::vec4 color = modelC["Color"];
|
glm::vec4 color = modelC["Color"];
|
||||||
Model* model = ResourceManager::Load<Model>(resource);
|
Model* model = ResourceManager::Load<Model>(resource);
|
||||||
if (model == nullptr) {
|
|
||||||
model = ResourceManager::Load<Model>("Models/Core/Error.obj");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto texGroup : model->TextureGroups) {
|
for (auto texGroup : model->TextureGroups) {
|
||||||
ModelJob job;
|
ModelJob job;
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
#include "Rendering/RenderState.h"
|
|
||||||
|
|
||||||
bool RenderState::Enable(GLenum cap)
|
|
||||||
{
|
|
||||||
if (glIsEnabled(cap)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_ResetFunctions.push_back(std::bind(glDisable, cap));
|
|
||||||
glEnable(cap);
|
|
||||||
return !GLERROR("RenderState::Enable");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderState::Disable(GLenum cap)
|
|
||||||
{
|
|
||||||
if (!glIsEnabled(cap)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_ResetFunctions.push_back(std::bind(glEnable, cap));
|
|
||||||
glDisable(cap);
|
|
||||||
return !GLERROR("RenderState::Disable");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderState::CullFace(GLenum mode)
|
|
||||||
{
|
|
||||||
if (!glIsEnabled(GL_CULL_FACE)) {
|
|
||||||
LOG_ERROR("Setting GL_CULL_FACE without enabling it.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLint original;
|
|
||||||
glGetIntegerv(GL_CULL_FACE_MODE, &original);
|
|
||||||
m_ResetFunctions.push_back(std::bind(glCullFace, original));
|
|
||||||
glCullFace(mode);
|
|
||||||
return !GLERROR("RenderState::CullFace");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderState::ClearColor(glm::vec4 color)
|
|
||||||
{
|
|
||||||
GLfloat original[4];
|
|
||||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, &original[0]);
|
|
||||||
m_ResetFunctions.push_back(std::bind(glClearColor, original[0], original[1], original[2], original[3]));
|
|
||||||
glClearColor(color.r, color.g, color.b, color.a);
|
|
||||||
return !GLERROR("RenderState::ClearColor");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderState::Clear(GLbitfield mask)
|
|
||||||
{
|
|
||||||
glClear(mask);
|
|
||||||
return !GLERROR("RenderState::Clear");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderState::BindFramebuffer(GLint framebuffer)
|
|
||||||
{
|
|
||||||
GLint originalRead;
|
|
||||||
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &originalRead);
|
|
||||||
GLint originalDraw;
|
|
||||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &originalDraw);
|
|
||||||
m_ResetFunctions.push_back([originalRead, originalDraw]() {
|
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, originalRead);
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, originalDraw);
|
|
||||||
});
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
|
||||||
return !GLERROR("RenderState::BindBuffer");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool RenderState::BlendEquation(GLenum mode)
|
|
||||||
{
|
|
||||||
GLint originalRGB;
|
|
||||||
glGetIntegerv(GL_BLEND_EQUATION_RGB, &originalRGB);
|
|
||||||
GLint originalAlpha;
|
|
||||||
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &originalAlpha);
|
|
||||||
m_ResetFunctions.push_back(std::bind(glBlendEquationSeparate, originalRGB, originalAlpha));
|
|
||||||
glBlendEquation(mode);
|
|
||||||
return !GLERROR("RenderState::BlendEquation");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderState::BlendFunc(GLenum sfactor, GLenum dfactor)
|
|
||||||
{
|
|
||||||
GLint originalSrcRGB;
|
|
||||||
glGetIntegerv(GL_BLEND_SRC_RGB, &originalSrcRGB);
|
|
||||||
GLint originalSrcAlpha;
|
|
||||||
glGetIntegerv(GL_BLEND_SRC_ALPHA, &originalSrcAlpha);
|
|
||||||
GLint originalDestRGB;
|
|
||||||
glGetIntegerv(GL_BLEND_DST_RGB, &originalDestRGB);
|
|
||||||
GLint originalDestAlpha;
|
|
||||||
glGetIntegerv(GL_BLEND_DST_ALPHA, &originalDestAlpha);
|
|
||||||
m_ResetFunctions.push_back(std::bind(glBlendFuncSeparate, originalSrcRGB, originalSrcAlpha, originalDestRGB, originalDestAlpha));
|
|
||||||
glBlendFunc(sfactor, dfactor);
|
|
||||||
return !GLERROR("RenderState::BlendFunc");
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderState::~RenderState()
|
|
||||||
{
|
|
||||||
for (auto& f : m_ResetFunctions) {
|
|
||||||
f();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+164
-123
@@ -1,4 +1,5 @@
|
|||||||
#include "Rendering/Renderer.h"
|
#include "Rendering/Renderer.h"
|
||||||
|
#include "Rendering/DebugCameraInputController.h"
|
||||||
|
|
||||||
void Renderer::Initialize()
|
void Renderer::Initialize()
|
||||||
{
|
{
|
||||||
@@ -9,21 +10,16 @@ void Renderer::Initialize()
|
|||||||
if (m_Camera == nullptr) {
|
if (m_Camera == nullptr) {
|
||||||
m_Camera = m_DefaultCamera;
|
m_Camera = m_DefaultCamera;
|
||||||
}
|
}
|
||||||
m_DebugCameraInputController = std::make_shared<DebugCameraInputController<Renderer>>(m_EventBroker, -1);
|
|
||||||
TEMPCreateLights();
|
|
||||||
InitializeRenderPasses();
|
|
||||||
|
|
||||||
glfwSwapInterval(m_VSYNC);
|
glfwSwapInterval(m_VSYNC);
|
||||||
InitializeShaders();
|
InitializeShaders();
|
||||||
InitializeTextures();
|
InitializeTextures();
|
||||||
InitializeSSBOs();
|
InitializeFrameBuffers();
|
||||||
//CalculateFrustum();
|
|
||||||
|
|
||||||
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
||||||
m_UnitQuad = ResourceManager::Load<Model>("Models/Core/UnitQuad.obj");
|
m_UnitQuad = ResourceManager::Load<Model>("Models/Core/UnitQuad.obj");
|
||||||
m_UnitSphere = ResourceManager::Load<Model>("Models/Core/UnitSphere.obj");
|
m_UnitSphere = ResourceManager::Load<Model>("Models/Core/UnitSphere.obj");
|
||||||
|
|
||||||
m_ImGuiRenderPass = new ImGuiRenderPass(this, m_EventBroker);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::InitializeWindow()
|
void Renderer::InitializeWindow()
|
||||||
@@ -68,27 +64,28 @@ void Renderer::InitializeWindow()
|
|||||||
|
|
||||||
void Renderer::InitializeShaders()
|
void Renderer::InitializeShaders()
|
||||||
{
|
{
|
||||||
m_BasicForwardProgram = ResourceManager::Load<ShaderProgram>("#m_BasicForwardProgram");
|
m_BasicForwardProgram.AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/BasicForward.vert.glsl")));
|
||||||
|
m_BasicForwardProgram.AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/BasicForward.frag.glsl")));
|
||||||
|
m_BasicForwardProgram.Compile();
|
||||||
|
m_BasicForwardProgram.Link();
|
||||||
|
|
||||||
m_DrawScreenQuadProgram = ResourceManager::Load<ShaderProgram>("#DrawScreenQuadProgram");
|
m_PickingProgram.AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Picking.vert.glsl")));
|
||||||
m_DrawScreenQuadProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/DrawScreenQuad.vert.glsl")));
|
m_PickingProgram.AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Picking.frag.glsl")));
|
||||||
m_DrawScreenQuadProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/DrawScreenQuad.frag.glsl")));
|
m_PickingProgram.Compile();
|
||||||
m_DrawScreenQuadProgram->Compile();
|
m_PickingProgram.BindFragDataLocation(0, "TextureFragment");
|
||||||
m_DrawScreenQuadProgram->Link();
|
m_PickingProgram.Link();
|
||||||
|
|
||||||
//m_CalculateFrustumProgram = ResourceManager::Load<ShaderProgram>("#CalculateFrustumProgram");
|
m_DrawScreenQuadProgram.AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/DrawScreenQuad.vert.glsl")));
|
||||||
//m_CalculateFrustumProgram.AddShader(std::shared_ptr<Shader>(new ComputeShader("Shaders/GridFrustum.comp.glsl")));
|
m_DrawScreenQuadProgram.AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/DrawScreenQuad.frag.glsl")));
|
||||||
//m_CalculateFrustumProgram.Compile();
|
m_DrawScreenQuadProgram.Compile();
|
||||||
//m_CalculateFrustumProgram.Link();
|
m_DrawScreenQuadProgram.Link();
|
||||||
|
|
||||||
//m_LightCullProgram = ResourceManager::Load<ShaderProgram>("#LightCullProgram");
|
|
||||||
//m_LightCullProgram.AddShader(std::shared_ptr<Shader>(new ComputeShader("Shaders/cullLights.comp.glsl")));
|
|
||||||
//m_LightCullProgram.Compile();
|
|
||||||
//m_LightCullProgram.Link();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::InputUpdate(double dt)
|
void Renderer::InputUpdate(double dt)
|
||||||
{
|
{
|
||||||
|
static DebugCameraInputController<Renderer> firstPersonInputController(m_EventBroker, -1);
|
||||||
|
|
||||||
glm::vec3 m_Position = m_Camera->Position();
|
glm::vec3 m_Position = m_Camera->Position();
|
||||||
if (glfwGetKey(m_Window, GLFW_KEY_O) == GLFW_PRESS)
|
if (glfwGetKey(m_Window, GLFW_KEY_O) == GLFW_PRESS)
|
||||||
{
|
{
|
||||||
@@ -118,32 +115,142 @@ void Renderer::InputUpdate(double dt)
|
|||||||
m_CameraMoveSpeed = 0.5f;
|
m_CameraMoveSpeed = 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_DebugCameraInputController->Update(dt);
|
firstPersonInputController.Update(dt);
|
||||||
m_Camera->SetOrientation(m_DebugCameraInputController->Orientation());
|
m_Camera->SetOrientation(firstPersonInputController.Orientation());
|
||||||
m_Camera->SetPosition(m_DebugCameraInputController->Position());
|
m_Camera->SetPosition(firstPersonInputController.Position());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Update(double dt)
|
void Renderer::Update(double dt)
|
||||||
{
|
{
|
||||||
m_EventBroker->Process<Renderer>();
|
m_EventBroker->Process<Renderer>();
|
||||||
InputUpdate(dt);
|
InputUpdate(dt);
|
||||||
m_ImGuiRenderPass->Update(dt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Draw(RenderQueueCollection& rq)
|
void Renderer::Draw(RenderQueueCollection& rq)
|
||||||
{
|
{
|
||||||
m_PickingPass->Draw(rq);
|
//TODO: Renderer: Kanske borde vara längst upp i update.
|
||||||
//DrawScreenQuad(m_PickingPass->PickingTexture());
|
PickingPass(rq);
|
||||||
//CullLights();
|
DrawScreenQuad(m_PickingTexture);
|
||||||
|
|
||||||
glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 1.f);
|
DrawScene(rq);
|
||||||
|
|
||||||
m_DrawScenePass->Draw(rq);
|
|
||||||
GLERROR("Renderer::Draw m_DrawScenePass->Draw");
|
|
||||||
m_ImGuiRenderPass->Draw();
|
|
||||||
glfwSwapBuffers(m_Window);
|
glfwSwapBuffers(m_Window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::DrawScene(RenderQueueCollection& rq)
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
//TODO: Render: Clean up draw code
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glCullFace(GL_BACK);
|
||||||
|
|
||||||
|
glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 0.f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
//TODO: Render: Add code for more jobs than modeljobs.
|
||||||
|
for (auto &job : rq.Forward) {
|
||||||
|
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||||
|
if (modelJob) {
|
||||||
|
GLuint ShaderHandle = m_BasicForwardProgram.GetHandle();
|
||||||
|
|
||||||
|
m_BasicForwardProgram.Bind();
|
||||||
|
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix()));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix()));
|
||||||
|
glUniform4fv(glGetUniformLocation(ShaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color));
|
||||||
|
|
||||||
|
//TODO: Renderer: bättre textur felhantering samt fler texturer stöd
|
||||||
|
if (modelJob->DiffuseTexture != nullptr) {
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture);
|
||||||
|
} else {
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindVertexArray(modelJob->Model->VAO);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||||
|
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GLERROR("DrawScene Error");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::PickingPass(RenderQueueCollection& rq)
|
||||||
|
{
|
||||||
|
m_PickingColorsToEntity.clear();
|
||||||
|
m_PickingBuffer.Bind();
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glCullFace(GL_BACK);
|
||||||
|
|
||||||
|
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
int r = 1;
|
||||||
|
int g = 0;
|
||||||
|
//TODO: Render: Add code for more jobs than modeljobs.
|
||||||
|
|
||||||
|
|
||||||
|
GLuint ShaderHandle = m_PickingProgram.GetHandle();
|
||||||
|
m_PickingProgram.Bind();
|
||||||
|
|
||||||
|
for (auto &job : rq.Forward) {
|
||||||
|
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||||
|
|
||||||
|
if (modelJob) {
|
||||||
|
//---------------
|
||||||
|
//TODO: Renderer: IMPORTANT: Fixa detta så det inte loopar igenom listan varje frame.
|
||||||
|
//---------------
|
||||||
|
int pickColor[2] = { r, g };
|
||||||
|
for (auto i : m_PickingColorsToEntity) {
|
||||||
|
if(modelJob->Entity == i.second) {
|
||||||
|
pickColor[0] = i.first.x;
|
||||||
|
pickColor[1] = i.first.y;
|
||||||
|
r -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_PickingColorsToEntity[glm::vec2(pickColor[0], pickColor[1])] = modelJob->Entity;
|
||||||
|
|
||||||
|
|
||||||
|
//Render picking stuff
|
||||||
|
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix()));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix()));
|
||||||
|
glUniform2fv(glGetUniformLocation(ShaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
||||||
|
|
||||||
|
glBindVertexArray(modelJob->Model->VAO);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||||
|
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex);
|
||||||
|
r += 1;
|
||||||
|
if(r > 255) {
|
||||||
|
r = 0;
|
||||||
|
g += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_PickingBuffer.Unbind();
|
||||||
|
GLERROR("PickingPass Error");
|
||||||
|
|
||||||
|
//Publish pick event every frame with the pick data that can be picked by the event
|
||||||
|
Events::Picking pickEvent = Events::Picking(
|
||||||
|
&m_PickingBuffer,
|
||||||
|
&m_DepthBuffer,
|
||||||
|
m_Camera->ProjectionMatrix(),
|
||||||
|
m_Camera->ViewMatrix(),
|
||||||
|
m_Resolution,
|
||||||
|
&m_PickingColorsToEntity);
|
||||||
|
|
||||||
|
m_EventBroker->Publish(pickEvent);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Renderer::DrawScreenQuad(GLuint textureToDraw)
|
void Renderer::DrawScreenQuad(GLuint textureToDraw)
|
||||||
{
|
{
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
@@ -155,7 +262,7 @@ void Renderer::DrawScreenQuad(GLuint textureToDraw)
|
|||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
|
||||||
m_DrawScreenQuadProgram->Bind();
|
m_DrawScreenQuadProgram.Bind();
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, textureToDraw);
|
glBindTexture(GL_TEXTURE_2D, textureToDraw);
|
||||||
|
|
||||||
@@ -165,10 +272,24 @@ void Renderer::DrawScreenQuad(GLuint textureToDraw)
|
|||||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->TextureGroups[0].StartIndex);
|
, GL_UNSIGNED_INT, 0, m_ScreenQuad->TextureGroups[0].StartIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Renderer::InitializeTextures()
|
void Renderer::InitializeTextures()
|
||||||
{
|
{
|
||||||
m_ErrorTexture=ResourceManager::Load<Texture>("Textures/Core/ErrorTexture.png");
|
m_ErrorTexture=ResourceManager::Load<Texture>("Textures/Core/ErrorTexture.png");
|
||||||
m_WhiteTexture=ResourceManager::Load<Texture>("Textures/Core/Blank.png");
|
m_WhiteTexture=ResourceManager::Load<Texture>("Textures/Core/Blank.png");
|
||||||
|
/*
|
||||||
|
glGenTextures(1, &m_PickingTexture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_PickingTexture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, m_Resolution.Width, m_Resolution.Height, 0, GL_RG, GL_FLOAT, NULL);//TODO: Renderer: Fix the precision and Resolution
|
||||||
|
GLERROR("m_PickingTexture initialization failed");
|
||||||
|
*/
|
||||||
|
|
||||||
|
GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR,
|
||||||
|
glm::vec2(m_Resolution.Width, m_Resolution.Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type)
|
void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type)
|
||||||
@@ -183,95 +304,15 @@ void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filterin
|
|||||||
GLERROR("Texture initialization failed");
|
GLERROR("Texture initialization failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::InitializeSSBOs()
|
|
||||||
|
|
||||||
|
void Renderer::InitializeFrameBuffers()//TODO: Renderer: Get this to a better location, as its really big
|
||||||
{
|
{
|
||||||
printf("Size: %i\n", sizeof(m_Frustums));
|
glGenRenderbuffers(1, &m_DepthBuffer);
|
||||||
glGenBuffers(1, &m_FrustumSSBO);
|
glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer);
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO);
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Resolution.Width, m_Resolution.Height);
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_Frustums), &m_Frustums, GL_DYNAMIC_COPY);
|
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
|
||||||
|
|
||||||
GLERROR("m_FrustumSSBO");
|
|
||||||
|
|
||||||
glGenBuffers(1, &m_LightSSBO);
|
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO);
|
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_PointLights), &m_PointLights, GL_DYNAMIC_COPY);
|
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO);
|
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
|
||||||
|
|
||||||
GLERROR("m_LightSSBO");
|
|
||||||
|
|
||||||
|
|
||||||
glGenBuffers(1, &m_LightGridSSBO);
|
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO);
|
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightGrid), &m_LightGrid, GL_DYNAMIC_COPY);
|
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO);
|
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
|
||||||
|
|
||||||
GLERROR("m_LightGridSSBO");
|
|
||||||
|
|
||||||
|
|
||||||
glGenBuffers(1, &m_LightOffsetSSBO);
|
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO);
|
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY);
|
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO);
|
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
|
||||||
|
|
||||||
GLERROR("m_LightOffsetSSBO");
|
|
||||||
|
|
||||||
|
|
||||||
glGenBuffers(1, &m_LightIndexSSBO);
|
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO);
|
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightIndex), &m_LightIndex, GL_DYNAMIC_COPY);
|
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO);
|
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
|
||||||
|
|
||||||
GLERROR("m_LightIndexSSBO");
|
|
||||||
|
|
||||||
|
m_PickingBuffer.AddResource(std::shared_ptr<BufferResource>(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT)));
|
||||||
|
m_PickingBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_PickingTexture, GL_COLOR_ATTACHMENT0)));
|
||||||
|
m_PickingBuffer.Generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::InitializeRenderPasses()
|
|
||||||
{
|
|
||||||
m_DrawScenePass = new DrawScenePass(this);
|
|
||||||
m_PickingPass = new PickingPass(this, m_EventBroker);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::CalculateFrustum()
|
|
||||||
{
|
|
||||||
GLERROR("CalculateFrustum Error-1");
|
|
||||||
m_CalculateFrustumProgram->Bind();
|
|
||||||
|
|
||||||
GLERROR("CalculateFrustum Error1");
|
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
|
||||||
GLERROR("CalculateFrustum Error2");
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(m_Camera->ProjectionMatrix()));
|
|
||||||
GLERROR("CalculateFrustum Error3");
|
|
||||||
glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Resolution.Width, m_Resolution.Height);
|
|
||||||
GLERROR("CalculateFrustum Error4");
|
|
||||||
glDispatchCompute(5, 3, 1);
|
|
||||||
GLERROR("CalculateFrustum Error5");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::TEMPCreateLights()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < NUM_LIGHTS; i++) {
|
|
||||||
m_PointLights[i].Position = glm::vec4(i, 0.f, 0.f, 0.f);
|
|
||||||
m_PointLights[i].Color = glm::vec4(1.f, 0.5f, 0.f + i*0.1f, 1.f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::CullLights()
|
|
||||||
{
|
|
||||||
m_LightCullProgram->Bind();
|
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO);
|
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO);
|
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO);
|
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO);
|
|
||||||
glDispatchCompute(m_Resolution.Width / TILE_SIZE, m_Resolution.Height / TILE_SIZE, 1);
|
|
||||||
GLERROR("CullLights Error");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user