diff --git a/CMakeLists.txt b/CMakeLists.txt index cbe8168a..43286658 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,8 @@ endif() if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") +elseif(MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") endif() #set(BUILD_SHARED_LIBS FALSE) @@ -34,6 +36,12 @@ foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES) +# DEBUG definition +set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS + $<$:DEBUG> + $<$:DEBUG> +) + include(cotire) add_subdirectory(src/Engine) add_subdirectory(src/Game) diff --git a/assets b/assets index 5f3ab8b3..e4dc9529 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 5f3ab8b35ddce150e972445fb2894fb9e9637258 +Subproject commit e4dc9529f2178d373808ddf487165fa50a641a78 diff --git a/include/Engine/Collision/CollidableOctreeSystem.h b/include/Engine/Collision/CollidableOctreeSystem.h index 0dcf5829..39aea979 100644 --- a/include/Engine/Collision/CollidableOctreeSystem.h +++ b/include/Engine/Collision/CollidableOctreeSystem.h @@ -4,11 +4,12 @@ #include "../Core/System.h" #include "../Core/Octree.h" #include "Collision.h" +#include "EntityAABB.h" class CollidableOctreeSystem : public ImpureSystem, public PureSystem { public: - CollidableOctreeSystem(World* world, EventBroker* eventBroker, Octree* octree) + CollidableOctreeSystem(World* world, EventBroker* eventBroker, Octree* octree) : System(world, eventBroker) , PureSystem("Collidable") , m_Octree(octree) @@ -18,7 +19,7 @@ public: virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; private: - Octree* m_Octree; + Octree* m_Octree; }; #endif \ No newline at end of file diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 194a18dc..cd10dbb2 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -15,6 +15,7 @@ #include "../Core/Transform.h" #include "../Core/Entity.h" #include "../Core/EntityWrapper.h" +#include "EntityAABB.h" class World; struct ComponentWrapper; @@ -58,10 +59,9 @@ 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); // Calculates an absolute AABB from an entity AABB component -boost::optional EntityAbsoluteAABB(EntityWrapper& entity); +boost::optional EntityAbsoluteAABB(EntityWrapper& entity); } diff --git a/include/Engine/Collision/CollisionSystem.h b/include/Engine/Collision/CollisionSystem.h index 5f15a3d5..f3a7e4fe 100644 --- a/include/Engine/Collision/CollisionSystem.h +++ b/include/Engine/Collision/CollisionSystem.h @@ -7,30 +7,23 @@ #include "../Common.h" #include "../Core/System.h" #include "../Core/EventBroker.h" -#include "../Core/EKeyUp.h" #include "../Core/Octree.h" +#include "EntityAABB.h" class CollisionSystem : public PureSystem { public: - CollisionSystem(World* world, EventBroker* eventBroker, Octree* octree) + CollisionSystem(World* world, EventBroker* eventBroker, Octree* octree) : System(world, eventBroker) , PureSystem("Collidable") , m_Octree(octree) - , zPress(false) - { - //TODO: Debug stuff, remove later. - EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp); - } + { } virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; private: - Octree* m_Octree; - bool zPress; - - EventRelay m_EKeyUp; - bool OnKeyUp(const Events::KeyUp &event); + Octree* m_Octree; + std::vector m_OctreeResult; }; #endif \ No newline at end of file diff --git a/include/Engine/Collision/ETrigger.h b/include/Engine/Collision/ETrigger.h index 687c73fa..0b35ef1b 100644 --- a/include/Engine/Collision/ETrigger.h +++ b/include/Engine/Collision/ETrigger.h @@ -2,7 +2,7 @@ #define Events_TriggerEnter_h__ #include "../Core/EventBroker.h" -#include "../Core/Entity.h" +#include "../Core/EntityWrapper.h" namespace Events { @@ -11,27 +11,27 @@ namespace Events struct TriggerTouch : Event { /** The id of the entity that touches the trigger. */ - EntityID Entity; + EntityWrapper Entity; /** The id of the trigger entity. */ - EntityID Trigger; + EntityWrapper 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; + EntityWrapper Entity; /** The id of the trigger entity. */ - EntityID Trigger; + EntityWrapper 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; + EntityWrapper Entity; /** The id of the trigger entity. */ - EntityID Trigger; + EntityWrapper Trigger; }; } diff --git a/include/Engine/Collision/EntityAABB.h b/include/Engine/Collision/EntityAABB.h new file mode 100644 index 00000000..79c21271 --- /dev/null +++ b/include/Engine/Collision/EntityAABB.h @@ -0,0 +1,22 @@ +#ifndef EntityAABB_h__ +#define EntityAABB_h__ + +#include "../Core/AABB.h" +#include "../Core/EntityWrapper.h" + +struct EntityAABB : AABB +{ + EntityAABB() = default; + + EntityAABB(const glm::vec3& minPos, const glm::vec3& maxPos) + : AABB(minPos, maxPos) + { } + + EntityAABB(const AABB& aabb) + : AABB(aabb) + { } + + EntityWrapper Entity; +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Collision/TriggerSystem.h b/include/Engine/Collision/TriggerSystem.h index 648c8585..fa322ddd 100644 --- a/include/Engine/Collision/TriggerSystem.h +++ b/include/Engine/Collision/TriggerSystem.h @@ -8,13 +8,14 @@ #include "../Core/EventBroker.h" #include "../Core/Octree.h" #include "ETrigger.h" +#include "EntityAABB.h" class AABB; class TriggerSystem : public PureSystem { public: - TriggerSystem(World* world, EventBroker* eventBroker, Octree* octree) + TriggerSystem(World* world, EventBroker* eventBroker, Octree* octree) : System(world, eventBroker) , PureSystem("Trigger") , m_Octree(octree) @@ -27,9 +28,10 @@ public: virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; private: - Octree* m_Octree; - std::unordered_map> m_EntitiesTouchingTrigger; - std::unordered_map> m_EntitiesCompletelyInTrigger; + Octree* m_Octree; + std::vector m_OctreeOut; + std::unordered_map> m_EntitiesTouchingTrigger; + std::unordered_map> m_EntitiesCompletelyInTrigger; //TODO: Only exists for debug purposes, remove later. EventRelay m_EEnter; @@ -40,13 +42,13 @@ private: bool OnLeave(const Events::TriggerLeave &event); //True if leave event was thrown. - bool throwLeaveIfWasInTrigger(std::unordered_set& triggerSet, EntityID pId, EntityID tId); + bool throwLeaveIfWasInTrigger(std::unordered_set& triggerSet, EntityWrapper colliderENtity, EntityWrapper triggerEntity); template - void publish(EntityID pId, EntityID tId) + void publish(EntityWrapper collider, EntityWrapper trigger) { Event e; - e.Trigger = tId; - e.Entity = pId; + e.Trigger = trigger; + e.Entity = collider; m_EventBroker->Publish(e); } }; diff --git a/include/Engine/Common.h b/include/Engine/Common.h index 8038b8af..8295554c 100644 --- a/include/Engine/Common.h +++ b/include/Engine/Common.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "Core/Util/Logging.h" #include "Core/Util/IfDebug.h" \ No newline at end of file diff --git a/include/Engine/Core/AABB.h b/include/Engine/Core/AABB.h index 5b9c6485..0dea9603 100644 --- a/include/Engine/Core/AABB.h +++ b/include/Engine/Core/AABB.h @@ -9,7 +9,6 @@ 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. static AABB FromOriginSize(const glm::vec3& origin, const glm::vec3& size); virtual ~AABB(); diff --git a/include/Engine/Core/EPlayerSpawned.h b/include/Engine/Core/EPlayerSpawned.h index a5700ed3..fcfaef61 100644 --- a/include/Engine/Core/EPlayerSpawned.h +++ b/include/Engine/Core/EPlayerSpawned.h @@ -12,6 +12,7 @@ struct PlayerSpawned : Event int PlayerID; EntityWrapper Player; EntityWrapper Spawner; + std::string PlayerName; }; } diff --git a/include/Engine/Core/EntityWrapper.h b/include/Engine/Core/EntityWrapper.h index 79bae9ed..bf34b9be 100644 --- a/include/Engine/Core/EntityWrapper.h +++ b/include/Engine/Core/EntityWrapper.h @@ -23,6 +23,7 @@ struct EntityWrapper static const EntityWrapper Invalid; + const std::string Name(); bool HasComponent(const std::string& componentType); EntityWrapper Parent(); EntityWrapper FirstChildByName(const std::string& name); @@ -34,7 +35,9 @@ struct EntityWrapper bool operator==(const EntityWrapper& e) const; bool operator!=(const EntityWrapper& e) const; explicit operator EntityID() const; - operator bool(); + +private: + EntityWrapper firstChildByNameRecursive(const std::string& name, EntityID parent); }; namespace std diff --git a/include/Engine/Core/Octree.h b/include/Engine/Core/Octree.h index 8bac5503..72825c3c 100644 --- a/include/Engine/Core/Octree.h +++ b/include/Engine/Core/Octree.h @@ -149,7 +149,7 @@ template template void Octree::ObjectsInSameRegion(const Box& box, std::vector& outObjects) { - static_assert(std::is_base_of::value, "template argument type Box in Octree::ObjectsInSameRegion must be a subclass of AABB."); + //static_assert(std::is_base_of::value, "template argument type Box in Octree::ObjectsInSameRegion must be a subclass of AABB."); falsifyObjectChecks(); m_Root->ObjectsInSameRegion(box, outObjects); } diff --git a/include/Engine/Core/Transform.h b/include/Engine/Core/Transform.h index 3b0811c9..2f549140 100644 --- a/include/Engine/Core/Transform.h +++ b/include/Engine/Core/Transform.h @@ -8,8 +8,10 @@ namespace Transform { +glm::mat4 AbsoluteTransformation(EntityWrapper entity); glm::vec3 AbsolutePosition(EntityWrapper entity); glm::vec3 AbsolutePosition(World* world, EntityID entity); +glm::vec3 AbsoluteOrientationEuler(EntityWrapper entity); glm::quat AbsoluteOrientation(EntityWrapper entity); glm::quat AbsoluteOrientation(World* world, EntityID entity); glm::vec3 AbsoluteScale(EntityWrapper entity); diff --git a/include/Engine/Core/Util/Logging.h b/include/Engine/Core/Util/Logging.h index 43f2c022..3d027937 100644 --- a/include/Engine/Core/Util/Logging.h +++ b/include/Engine/Core/Util/Logging.h @@ -29,41 +29,9 @@ enum _LOG_LEVEL extern _LOG_LEVEL LOG_LEVEL; -const static char* _LOG_LEVEL_PREFIX[] = -{ - "EE: ", - "", - "WW: ", - "DD: " -}; +extern const char* _LOG_LEVEL_PREFIX[]; -static void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int line, const char* format, ...) -{ - if (logLevel > LOG_LEVEL) { - return; - } - - char* message = nullptr; - va_list args; - - va_start(args, format); - size_t size = vsnprintf(message, 0, format, args) + 1; - va_end(args); - - va_start(args, format); - message = new char[size]; - vsnprintf(message, size, format, args); - va_end(args); - - if (logLevel == LOG_LEVEL_ERROR) { - std::cerr << file << ":" << line << " " << func << std::endl; - std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; - } else { - std::cout << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; - } - - delete[] message; -} +extern void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int line, const char* format, ...); #define LOG(logLevel, format, ...) \ _LOG(logLevel, __BASE_FILE__, __func__, __LINE__, format, ##__VA_ARGS__) @@ -77,7 +45,11 @@ static void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsign #define LOG_INFO(format, ...) \ LOG(LOG_LEVEL_INFO, format, ##__VA_ARGS__) +#ifdef DEBUG #define LOG_DEBUG(format, ...) \ LOG(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__) +#else +#define LOG_DEBUG(format, ...) +#endif #endif // Logging_h__ \ No newline at end of file diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index 973f6a90..c2cd1001 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "../Common.h" #include "../GLM.h" #include @@ -118,6 +119,7 @@ private: const std::string formatEntityName(EntityWrapper entity); GLuint tryLoadTexture(std::string filePath); void openModal(const std::string& modal); + static bool compareCharArray(const char* c1, const char* c2); // Entity file handling methods void entityImport(World* world); diff --git a/include/Engine/Input/EInputCommand.h b/include/Engine/Input/EInputCommand.h index 1e150786..d4608b55 100644 --- a/include/Engine/Input/EInputCommand.h +++ b/include/Engine/Input/EInputCommand.h @@ -2,6 +2,7 @@ #define Events_InputCommand_h__ #include "Core/EventBroker.h" +#include "Core/EntityWrapper.h" namespace Events { @@ -10,6 +11,7 @@ struct InputCommand : Event { /** Numerical ID of the player. */ int PlayerID; + EntityWrapper Player; /** The command that was sent. */ std::string Command; /** The value of the command. */ diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h index 03fcc0f3..e1e64fc1 100644 --- a/include/Engine/Network/Network.h +++ b/include/Engine/Network/Network.h @@ -12,7 +12,7 @@ #include #include -#define INPUTSIZE 4097 +#define INPUTSIZE 32000 typedef unsigned int PlayerID; typedef unsigned int PacketID; diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 17029809..11f983a9 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -34,6 +34,7 @@ private: // Sending messages to client logic std::map m_ConnectedPlayers; + // HACK: Fix INPUTSIZE char readBuffer[INPUTSIZE] = { 0 }; int bytesRead = 0; // time for previouse message diff --git a/include/Engine/Rendering/DrawFinalPass.h b/include/Engine/Rendering/DrawFinalPass.h index 4cf88842..6bd8acec 100644 --- a/include/Engine/Rendering/DrawFinalPass.h +++ b/include/Engine/Rendering/DrawFinalPass.h @@ -43,6 +43,7 @@ private: const LightCullingPass* m_LightCullingPass; ShaderProgram* m_ForwardPlusProgram; + ShaderProgram* m_ExplosionEffectProgram; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/ExplosionEffectJob.h b/include/Engine/Rendering/ExplosionEffectJob.h new file mode 100644 index 00000000..89b1342b --- /dev/null +++ b/include/Engine/Rendering/ExplosionEffectJob.h @@ -0,0 +1,106 @@ +#ifndef ExplosionEffectJob_h__ +#define ExplosionEffectJob_h__ + +#include + +#include "../Common.h" +#include "../GLM.h" +#include "../Core/ComponentWrapper.h" +#include "Texture.h" +#include "Model.h" +#include "RenderJob.h" +#include "../Core/ResourceManager.h" +#include "Camera.h" +#include "../Core/World.h" + +struct ExplosionEffectJob : ModelJob +{ + ExplosionEffectJob(ComponentWrapper explosionEffectComponent, ::Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialGroup matGroup, ComponentWrapper modelComponent, ::World* world, glm::vec4 fillColor, float fillPercentage) + : ModelJob(model, camera, matrix, matGroup, modelComponent, world, fillColor, fillPercentage) + { + ExplosionOrigin = (glm::vec3)explosionEffectComponent["ExplosionOrigin"]; + TimeSinceDeath = (double)explosionEffectComponent["TimeSinceDeath"]; + ExplosionDuration = (double)explosionEffectComponent["ExplosionDuration"]; + EndColor = (glm::vec4)explosionEffectComponent["EndColor"]; + Randomness = (bool)explosionEffectComponent["Randomness"]; + RandomnessScalar = (double)explosionEffectComponent["RandomnessScalar"]; + Velocity = (glm::vec2)explosionEffectComponent["Velocity"]; + ColorByDistance = (bool)explosionEffectComponent["ColorByDistance"]; + ExponentialAccelaration = (bool)explosionEffectComponent["ExponentialAccelaration"]; + }; + + glm::vec3 ExplosionOrigin; + double TimeSinceDeath = 0.f; //Seconds + double ExplosionDuration = 2.f; + //bool Gravity = true; + //double GravityForce = 1.f; // Speed + //double ObjectRadius = 2.f; // TODO: Change this for object radius when it's available + glm::vec4 EndColor; + bool Randomness = false; + + float RandomnessScalar = 1.f; + glm::vec2 Velocity; + bool ColorByDistance = false; + //bool ReverseAnimation = false; + //bool Wireframe = false; + bool ExponentialAccelaration = false; + + std::array RandomNumbers = { + 0.3257552917701f, + 0.07601508315467f, + 0.57408909014151f, + 0.0f, + 0.8618231368539f, + 0.074957156588769f, + 0.39413607511396f, + 0.54579346698979f, + 0.83222648353885f, + 0.83635707285086f, + 0.34473986148124f, + 0.98092448710507f, + 0.46346380070944f, + 0.7308761201477f, + 0.70832470371776f, + 0.28268750909841f, + 0.26291620883295f, + 0.07685032816457f, + 0.30760929515008f, + 0.2781575388639f , + 0.016950582161988f , + 0.25787915254844f , + 0.76293767279151f , + 0.67730279903733f , + 0.49042877018937f , + 0.13002237823327f , + 0.62803373841012f , + 0.94525353747665f , + 0.32893980076953f , + 0.95952951719962f , + 0.056386206790985f , + 0.012030893476694f , + 0.93090049220757f, + 0.83579883064879f, + 0.79733513938139f, + 0.8796381046435f , + 0.94160434600972f , + 0.76901855588379f , + 0.50253688101775f , + 0.82457069578793f , + 0.80157403359263f , + 0.87291810189975f , + 0.64679548919517f , + 0.42664138899494f , + 0.77171308303797f , + 0.75567959237643f , + 0.45190826265696f , + 0.59844922628181f , + 0.56534937655802f , + 0.195656257307f}; + + void CalculateHash() override + { + Hash = 0; + } +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index 32d89293..df7f1aec 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -17,7 +17,7 @@ struct ModelJob : RenderJob { - ModelJob(Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialGroup matGroup, ComponentWrapper modelComponent, World* world) + ModelJob(Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialGroup matGroup, ComponentWrapper modelComponent, World* world, glm::vec4 fillColor, float fillPercentage) : RenderJob() { Model = model; @@ -39,6 +39,9 @@ struct ModelJob : RenderJob Depth = worldpos.z; World = world; + + FillColor = fillColor; + FillPercentage = fillPercentage; Skeleton = Model->m_RawModel->m_Skeleton; if (world->HasComponent(Entity, "Animation") && Skeleton != nullptr) { @@ -72,6 +75,9 @@ struct ModelJob : RenderJob unsigned int EndIndex = 0; World* World; + glm::vec4 FillColor = glm::vec4(0); + float FillPercentage = 0.0; + void CalculateHash() override { Hash = TextureID; diff --git a/include/Engine/Rendering/RenderQueue.h b/include/Engine/Rendering/RenderQueue.h index b533f992..08a67ac7 100644 --- a/include/Engine/Rendering/RenderQueue.h +++ b/include/Engine/Rendering/RenderQueue.h @@ -14,6 +14,7 @@ #include "TextJob.h" #include "PointLightJob.h" #include "DirectionalLightJob.h" +#include "ExplosionEffectJob.h" struct RenderScene { diff --git a/include/Engine/Rendering/RenderSystem.h b/include/Engine/Rendering/RenderSystem.h index 005d2eb7..d9b0d779 100644 --- a/include/Engine/Rendering/RenderSystem.h +++ b/include/Engine/Rendering/RenderSystem.h @@ -29,22 +29,25 @@ private: const IRenderer* m_Renderer; RenderFrame* m_RenderFrame; Camera* m_Camera; + World* m_World; EntityWrapper m_CurrentCamera = EntityWrapper::Invalid; EntityWrapper m_LocalPlayer = EntityWrapper::Invalid; EventRelay m_ESetCamera; bool OnSetCamera(Events::SetCamera &event); + EventRelay m_EInputCommand; + bool OnInputCommand(const Events::InputCommand& e); + EventRelay m_EPlayerSpawned; + bool OnPlayerSpawned(Events::PlayerSpawned& e); + void fillText(std::list>& jobs, World* world); void fillPointLights(std::list>& jobs, World* world); void fillDirectionalLights(std::list>& jobs, World* world); - EventRelay m_EInputCommand; - bool OnInputCommand(const Events::InputCommand& e); - void fillModels(std::list>& jobs); void fillLight(std::list>& jobs); + bool isChildOfACamera(EntityWrapper entity); + bool isChildOfCurrentCamera(EntityWrapper entity); - EventRelay m_EPlayerSpawned; - bool OnPlayerSpawned(Events::PlayerSpawned& e); }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index d84f41d5..33a61edf 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -73,6 +73,8 @@ private: void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type); //--------------------ShaderPrograms-------------------// ShaderProgram* m_BasicForwardProgram; + ShaderProgram* m_ExplosionEffectProgram; + }; #endif \ No newline at end of file diff --git a/include/Game/ExplosionEffectSystem.h b/include/Game/ExplosionEffectSystem.h new file mode 100644 index 00000000..061ad221 --- /dev/null +++ b/include/Game/ExplosionEffectSystem.h @@ -0,0 +1,24 @@ +#include "Common.h" +#include "Core/System.h" + +class ExplosionEffectSystem : public PureSystem +{ +public: + ExplosionEffectSystem(World* world, EventBroker* eventBroker) + : System(world, eventBroker) + , PureSystem("ExplosionEffect") + { } + + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override + { + + if ((double)component["TimeSinceDeath"] > (double)component["ExplosionDuration"]) { + (double)component["TimeSinceDeath"] = 0.f; + } + (double&)component["TimeSinceDeath"] += dt; + + //if ((bool)Component["Gravity"] == true) { + // (bool)Component["ExponentialAccelaration"] = false; + //} + } +}; \ No newline at end of file diff --git a/include/Game/Game.h b/include/Game/Game.h index fab10a49..671edfc5 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -14,6 +14,7 @@ #include "Core/EKeyDown.h" #include "Core/EntityFilePreprocessor.h" #include "Core/SystemPipeline.h" +#include "ExplosionEffectSystem.h" #include "Editor/EditorSystem.h" #include "Core/EntityFile.h" #include "Rendering/RenderSystem.h" @@ -21,6 +22,7 @@ #include "Core/Octree.h" #include "Rendering/Font.h" #include "Systems/InterpolationSystem.h" +#include "Collision/EntityAABB.h" // Network #include #include "Network/Network.h" @@ -48,8 +50,8 @@ private: InputProxy* m_InputProxy; GUI::Frame* m_FrameStack; World* m_World; - Octree* m_OctreeCollision; - Octree* m_OctreeFrustrumCulling; + Octree* m_OctreeCollision; + Octree* m_OctreeFrustrumCulling; SystemPipeline* m_SystemPipeline; RenderFrame* m_RenderFrame; // Network variables diff --git a/include/Game/Systems/CapturePointSystem.h b/include/Game/Systems/CapturePointSystem.h index 3b459c40..18c32c76 100644 --- a/include/Game/Systems/CapturePointSystem.h +++ b/include/Game/Systems/CapturePointSystem.h @@ -40,7 +40,7 @@ private: int m_BlueTeamHomeCapturePoint = m_NotACapturePoint; int m_NumberOfCapturePoints = 0; - std::map m_CapturePointNumberToEntityIDMap; + std::map m_CapturePointNumberToEntityMap; //std::vector @@ -48,8 +48,8 @@ private: bool m_ResetTimers = false; //vectors which will keep track of enter/leave changes - std::vector> m_ETriggerTouchVector; - std::vector> m_ETriggerLeaveVector; + std::vector> m_ETriggerTouchVector; + std::vector> m_ETriggerLeaveVector; }; #endif \ No newline at end of file diff --git a/include/Game/Systems/HealthSystem.h b/include/Game/Systems/HealthSystem.h index f9843f11..3b069349 100644 --- a/include/Game/Systems/HealthSystem.h +++ b/include/Game/Systems/HealthSystem.h @@ -24,7 +24,7 @@ public: private: //methods which will take care of specific events EventRelay m_EPlayerDamage; - bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e); + bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e); EventRelay m_EPlayerHealthPickup; bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e); diff --git a/include/Game/Systems/LifetimeSystem.h b/include/Game/Systems/LifetimeSystem.h new file mode 100644 index 00000000..da88cfa2 --- /dev/null +++ b/include/Game/Systems/LifetimeSystem.h @@ -0,0 +1,21 @@ +#ifndef LifetimeSystem_h__ +#define LifetimeSystem_h__ + +#include "Core/System.h" + +class LifetimeSystem : public ImpureSystem, PureSystem +{ +public: + LifetimeSystem(World* world, EventBroker* eventBroker) + : System(world, eventBroker) + , PureSystem("Lifetime") + { } + + virtual void Update(double dt) override; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cLifetime, double dt) override; + +private: + std::vector m_Deletions; +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/PlayerHUD.h b/include/Game/Systems/PlayerHUD.h new file mode 100644 index 00000000..180f5a2a --- /dev/null +++ b/include/Game/Systems/PlayerHUD.h @@ -0,0 +1,23 @@ +#ifndef PlayerHUD_h__ +#define PlayerHUD_h__ + +#include "../../Engine/Core/System.h" +#include "../../Engine/GLM.h" +#include "../../Engine/Rendering/ESetCamera.h" +#include + +class PlayerHUD : public ImpureSystem +{ +public: + PlayerHUD(World* world, EventBroker* eventBrokerer); + ~PlayerHUD(); + + virtual void Update(double dt) override; + +private: + World* m_World; + EventBroker* m_EventBroker; + +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/WeaponSystem.h b/include/Game/Systems/WeaponSystem.h index 0397b1a3..0dd5cc54 100644 --- a/include/Game/Systems/WeaponSystem.h +++ b/include/Game/Systems/WeaponSystem.h @@ -11,6 +11,8 @@ #include "Core/EShoot.h" #include "Core/EPlayerSpawned.h" #include "Input/EInputCommand.h" +#include "Core/EntityFile.h" +#include "Core/EntityFileParser.h" #include #include @@ -33,7 +35,7 @@ private: EventRelay m_EPlayerSpawned; bool WeaponSystem::OnPlayerSpawned(const Events::PlayerSpawned& e); EventRelay m_EShoot; - bool WeaponSystem::OnShoot(const Events::Shoot& e); + bool WeaponSystem::OnShoot(Events::Shoot& e); EventRelay m_EInputCommand; bool WeaponSystem::OnInputCommand(const Events::InputCommand& e); }; diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index eeeac344..991d785d 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -12,6 +12,7 @@ + @@ -23,6 +24,10 @@ + + + + \ No newline at end of file diff --git a/resources/Schema/Components/Animation.xml b/resources/Schema/Components/Animation.xml index 01af2747..66d2865d 100644 --- a/resources/Schema/Components/Animation.xml +++ b/resources/Schema/Components/Animation.xml @@ -1,5 +1,6 @@ + 0 true diff --git a/resources/Schema/Components/CapturePoint.xsd b/resources/Schema/Components/CapturePoint.xsd index 9e96fca6..91afd366 100644 --- a/resources/Schema/Components/CapturePoint.xsd +++ b/resources/Schema/Components/CapturePoint.xsd @@ -2,18 +2,7 @@ - - - - - - - - - - - - + diff --git a/resources/Schema/Components/ExplosionEffect.xml b/resources/Schema/Components/ExplosionEffect.xml new file mode 100644 index 00000000..22692729 --- /dev/null +++ b/resources/Schema/Components/ExplosionEffect.xml @@ -0,0 +1,17 @@ + + + + 0 + 2 + + + + + 0 + 1 + + 0 + + + 0 + \ No newline at end of file diff --git a/resources/Schema/Components/ExplosionEffect.xsd b/resources/Schema/Components/ExplosionEffect.xsd new file mode 100644 index 00000000..cdde5e52 --- /dev/null +++ b/resources/Schema/Components/ExplosionEffect.xsd @@ -0,0 +1,57 @@ + + + + + + + + A component that trigger the death effect + + + + + The position in which to spawn the component + + + Seconds since death + + + How many seconds the death animation should be + + + + + + The tint the polys end with + + + Add some randomness to the explosion + + + Alter the power of the randomness + + + The velocity factors (start/end) + + + Change the color by its moved distance instead of by its time + + + + + Linear/Exponential accelaration + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/Fill.xml b/resources/Schema/Components/Fill.xml new file mode 100644 index 00000000..397f8e49 --- /dev/null +++ b/resources/Schema/Components/Fill.xml @@ -0,0 +1,5 @@ + + + 0.0 + + \ No newline at end of file diff --git a/resources/Schema/Components/Fill.xsd b/resources/Schema/Components/Fill.xsd new file mode 100644 index 00000000..2bf6548f --- /dev/null +++ b/resources/Schema/Components/Fill.xsd @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/HealthHUD.xml b/resources/Schema/Components/HealthHUD.xml new file mode 100644 index 00000000..a48b9606 --- /dev/null +++ b/resources/Schema/Components/HealthHUD.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/resources/Schema/Components/HealthHUD.xsd b/resources/Schema/Components/HealthHUD.xsd new file mode 100644 index 00000000..821a65a2 --- /dev/null +++ b/resources/Schema/Components/HealthHUD.xsd @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/HiddenForLocalPlayer.xml b/resources/Schema/Components/HiddenForLocalPlayer.xml new file mode 100644 index 00000000..5840385c --- /dev/null +++ b/resources/Schema/Components/HiddenForLocalPlayer.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/resources/Schema/Components/HiddenForLocalPlayer.xsd b/resources/Schema/Components/HiddenForLocalPlayer.xsd new file mode 100644 index 00000000..7f47fba5 --- /dev/null +++ b/resources/Schema/Components/HiddenForLocalPlayer.xsd @@ -0,0 +1,11 @@ + + + + + + + + Used to make the entity invisible if it's parented to the current local player entity (for first person player model and such) + + + \ No newline at end of file diff --git a/resources/Schema/Components/Lifetime.xml b/resources/Schema/Components/Lifetime.xml new file mode 100644 index 00000000..302429b1 --- /dev/null +++ b/resources/Schema/Components/Lifetime.xml @@ -0,0 +1,4 @@ + + + 0 + \ No newline at end of file diff --git a/resources/Schema/Components/Lifetime.xsd b/resources/Schema/Components/Lifetime.xsd new file mode 100644 index 00000000..137c1d4a --- /dev/null +++ b/resources/Schema/Components/Lifetime.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/Model.xsd b/resources/Schema/Components/Model.xsd index fb0774f8..540ab1bf 100644 --- a/resources/Schema/Components/Model.xsd +++ b/resources/Schema/Components/Model.xsd @@ -16,7 +16,7 @@ Color tint - Wether the model is visible or not + Whether the model is visible or not diff --git a/resources/Schema/Components/Team.xsd b/resources/Schema/Components/Team.xsd index a81a8978..d6e14684 100755 --- a/resources/Schema/Components/Team.xsd +++ b/resources/Schema/Components/Team.xsd @@ -2,18 +2,7 @@ - - - - - - - - - - - - + diff --git a/resources/Schema/Entities/Empty.xml b/resources/Schema/Entities/Empty.xml index c9b8924f..6efd8318 100644 --- a/resources/Schema/Entities/Empty.xml +++ b/resources/Schema/Entities/Empty.xml @@ -5,16 +5,6 @@ - - - - - - - - - - - + diff --git a/resources/Schema/Entities/GameMap.xml b/resources/Schema/Entities/GameMap.xml index 8841e3c9..97fd3f4d 100644 --- a/resources/Schema/Entities/GameMap.xml +++ b/resources/Schema/Entities/GameMap.xml @@ -123,6 +123,121 @@ + + + + + Models/Core/UnitCube.mesh + false + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + false + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/MovementTest.xml b/resources/Schema/Entities/MovementTest.xml index 40de747a..1378f623 100644 --- a/resources/Schema/Entities/MovementTest.xml +++ b/resources/Schema/Entities/MovementTest.xml @@ -146,7 +146,6 @@ - @@ -178,6 +177,123 @@ + + + + + + + + + + false + + + 5 + + + + + + + + + + + + + + + + + + + + + + + + Fonts/DroidSans.ttf,100 + + false + + + + + + + + + + + + + Models/Camera.mesh + + + + + + + + + + + + + + + Models/Camera.mesh + false + + + + + + + + + + + + Models/AssaultHeadless.mesh + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index 1ec7927b..e81ec5aa 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -2,13 +2,15 @@ + - - + + + 5 @@ -18,8 +20,7 @@ - - + @@ -37,10 +38,9 @@ Fonts/DroidSans.ttf,100 - false - + @@ -51,6 +51,7 @@ Models/Camera.mesh + false @@ -59,6 +60,67 @@ + + + + + + + + + + + 1 + + + + + Models/Core/UnitHexagon.mesh + + + + + + + + + + + + + + Models/CrosshairQuad.mesh + + + + + + + + + + + + + Models/AssaultWeapon.mesh + + + + + + + + + + + + + + + + + + @@ -77,13 +139,17 @@ + + Hold Pos + + 1 + + - Models/AssaultHeadless.mesh + Models/AssaultAnimated.mesh - - - + diff --git a/resources/Schema/Entities/RayBlue b/resources/Schema/Entities/RayBlue new file mode 100644 index 00000000..d34e185e --- /dev/null +++ b/resources/Schema/Entities/RayBlue @@ -0,0 +1,17 @@ + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + diff --git a/resources/Schema/Entities/RayBlue.xml b/resources/Schema/Entities/RayBlue.xml new file mode 100644 index 00000000..3b985a7e --- /dev/null +++ b/resources/Schema/Entities/RayBlue.xml @@ -0,0 +1,19 @@ + + + + + + 0.25 + + + Models/CylinderBullet.mesh + + + + + + + + + + diff --git a/resources/Schema/Entities/RayRed b/resources/Schema/Entities/RayRed new file mode 100644 index 00000000..d34e185e --- /dev/null +++ b/resources/Schema/Entities/RayRed @@ -0,0 +1,17 @@ + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + diff --git a/resources/Schema/Entities/RayRed.xml b/resources/Schema/Entities/RayRed.xml new file mode 100644 index 00000000..df563476 --- /dev/null +++ b/resources/Schema/Entities/RayRed.xml @@ -0,0 +1,19 @@ + + + + + + 0.25 + + + Models/CylinderBullet.mesh + + + + + + + + + + diff --git a/resources/Schema/Entities/RenderingWorld.xml b/resources/Schema/Entities/RenderingWorld.xml index e860fd04..20301d5f 100644 --- a/resources/Schema/Entities/RenderingWorld.xml +++ b/resources/Schema/Entities/RenderingWorld.xml @@ -6,34 +6,115 @@ - + - - - Models/Camera.mesh - + + 65.990005493164063 + + - - + - + - - Camera #2 - Fonts/DroidSans.ttf,64 - - - - + + Models/Assault.obj + + - - + + + + + 80 + + + Models/Camera.mesh + + + + + + + + + + + + + + + + + + + 0.65990006923675537 + + + + Models/Core/UnitHexagon.mesh + + + + + + + + + + + + + 24 + Fonts/DroidSans.ttf,60 + + + + + + + + + + + 262 + Fonts/DroidSans.ttf,60 + + + + + + + + + + + + + + + + + 65/100 + Fonts/DroidSans.ttf,60 + + + + + + + + + + + + @@ -42,7 +123,7 @@ Models/Core/UnitPlane.mesh - + @@ -52,6 +133,7 @@ Models/Assault.mesh + @@ -64,7 +146,7 @@ Welcome! Fonts/DroidSans.ttf,1280 - + @@ -75,32 +157,40 @@ - 2 - + 3 + - - + + + Models/Core/UnitSphere.obj + + - 6 + 70 0.5 + + + Models/Core/UnitSphere.obj + + - 8 + 70 @@ -112,21 +202,30 @@ + + Models/Core/UnitSphere.obj + + - 6 + 70 0.5 + + + Models/Core/UnitSphere.obj + + - 8 + 70 @@ -138,21 +237,30 @@ + + Models/Core/UnitSphere.obj + + - 6 + 70 0.5 + + + Models/Core/UnitSphere.obj + + - - 8 + + 70 @@ -164,19 +272,28 @@ + + Models/Core/UnitSphere.obj + + - 6 + 70 0.5 + + + Models/Core/UnitSphere.obj + + - 8 + 70 @@ -192,6 +309,7 @@ Models/Assault.mesh + @@ -199,46 +317,15 @@ - - - - - - Models/Camera.mesh - false - - - - - - - - - - - Taiwan #1 - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - + - 0.80000001192092896 + 0.10000000149011612 Models/DirectionalLightWidget.mesh + @@ -251,6 +338,7 @@ Models/Core/UnitCube.mesh + @@ -258,37 +346,6 @@ - - - - - asd - - - - - - - - - - - - - running - - 1 - - - Models/Animtest.mesh - - - - - - - - diff --git a/resources/Schema/Entities/Spawnpoint b/resources/Schema/Entities/Spawnpoint new file mode 100644 index 00000000..a53aaa08 --- /dev/null +++ b/resources/Schema/Entities/Spawnpoint @@ -0,0 +1,32 @@ + + + + + + + Models/Core/UnitCube.mesh + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index 1f8da1a3..2cdf4e17 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -18,6 +18,23 @@ + + + + 0 + 2 + + + + + 0 + 1 + + 0 + + + 0 + Models/Camera.mesh diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 5583b8b8..99b90caa 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -15,6 +15,7 @@ + @@ -32,6 +33,10 @@ + + + + @@ -42,7 +47,7 @@ - + @@ -50,7 +55,7 @@ - + \ No newline at end of file diff --git a/resources/Schema/Types/TeamEnum.xsd b/resources/Schema/Types/TeamEnum.xsd new file mode 100644 index 00000000..e98e06d3 --- /dev/null +++ b/resources/Schema/Types/TeamEnum.xsd @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Shaders/ExplosionEffect.frag.glsl b/resources/Shaders/ExplosionEffect.frag.glsl new file mode 100644 index 00000000..32ababe5 --- /dev/null +++ b/resources/Shaders/ExplosionEffect.frag.glsl @@ -0,0 +1,25 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform vec4 Color; + +uniform sampler2D texture0; + +in VertexData{ + vec3 Position; + vec3 Normal; + vec2 TextureCoordinate; + vec4 DiffuseColor; + vec4 ExplosionColor; +}Input; + +out vec4 fragmentColor; + + +void main() +{ + vec4 texel = texture2D(texture0, Input.TextureCoordinate); + fragmentColor = texel * Input.DiffuseColor * Color + Input.ExplosionColor; +} \ No newline at end of file diff --git a/resources/Shaders/ExplosionEffect.geom.glsl b/resources/Shaders/ExplosionEffect.geom.glsl new file mode 100644 index 00000000..cb91b545 --- /dev/null +++ b/resources/Shaders/ExplosionEffect.geom.glsl @@ -0,0 +1,179 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform vec3 ExplosionOrigin; +uniform float TimeSinceDeath; +uniform float ExplosionDuration; +uniform vec4 EndColor; +uniform bool Randomness; +uniform float RandomNumbers[50]; +uniform float RandomnessScalar; +uniform vec2 Velocity; +uniform bool ColorByDistance; +uniform bool ExponentialAccelaration; + +in VertexData{ + vec3 Position; + vec3 Normal; + vec2 TextureCoordinate; + vec4 ExplosionColor; +}Input[]; + +out VertexData{ + vec3 Position; + vec3 Normal; + vec2 TextureCoordinate; + vec4 ExplosionColor; +}Output; + +layout(triangles) in; +layout(triangle_strip, max_vertices = 3) out; + +// returns a "random" number based on input parameter +float GetRandomNumber(int polygon_index) +{ + int randomIndex = int(mod(polygon_index, 50)); + + return RandomNumbers[randomIndex]; +} + +float randomNumber = 0.0; +float randomDistance = 0.0; + +void main() +{ + // calculate middle of vectors + vec3 v1 = Input[1].Position - Input[0].Position; + vec3 v2 = Input[2].Position - Input[0].Position; + vec3 v3 = Input[2].Position - (v1 / 2); + vec3 v4 = Input[1].Position - (v2 / 2); + + // calculate intersection + + // normalize direction + vec3 dir1 = normalize(v1); + vec3 dir2 = normalize(v2); + + vec3 vecA = Input[2].Position - Input[1].Position; //o2 - o1 + vec3 vecB = cross(dir1, dir2); + + mat3 matrisA = mat3(vecA, dir2, vecB); + + float lengthA = length(vecB); + lengthA = lengthA * lengthA; + + float s = determinant(matrisA) / lengthA; + + // center position of triangle + vec3 centerOfTriangle = Input[1].Position + (s * dir1); + + // center position of triangle to origin vector + vec3 origin2TriangleCenterVector = centerOfTriangle - ExplosionOrigin; + vec3 normalizedOrigin2TriangleCenterVector = normalize(origin2TriangleCenterVector); + + // time percentage until end of explosion (0.0-1.0) + float timePercetage = TimeSinceDeath / ExplosionDuration; + + // get a random number if randomness is enabled, otherwise the random number will be zero and won't affect the other algorithms + if (Randomness == true) + { + randomDistance = GetRandomNumber(gl_PrimitiveIDIn) * RandomnessScalar; + } + + vec2 randomVelocity = Velocity * (randomDistance + 1.0); + + // accelaration to use on current frame. is a interpolation between start and end value + float currentVelocity = mix(randomVelocity.x, randomVelocity.y, timePercetage); + + if (ExponentialAccelaration == true) + { + currentVelocity = pow(currentVelocity, 2) / 2.0; + } + + // distance between origin and the center of the current triangle + float origin2TriangleCenterDistance = length(origin2TriangleCenterVector); + + // the distance from origin to the triangle center with eventual randomness added + float fullDistanceWithRandomness = origin2TriangleCenterDistance + randomDistance; + + // vector from the triangle center to the explosion's shockwave + vec3 triangleCenter2ExplosionRadius = (normalizedOrigin2TriangleCenterVector * (TimeSinceDeath * currentVelocity)) - (normalizedOrigin2TriangleCenterVector * fullDistanceWithRandomness); + + // if the triangle is inside the blast radius... + if (fullDistanceWithRandomness <= (TimeSinceDeath * currentVelocity)) + { + float maxRadius = max(TimeSinceDeath * currentVelocity, (ExplosionDuration * currentVelocity)); + + float a = (randomVelocity.y - randomVelocity.x) / ExplosionDuration; + //float t = sqrt((2 * origin2TriangleCenterDistance) / a); + + // if explosion color should be affected by distance instead of time... + if (ColorByDistance == true) + { + // calculate the max distance (s) the triangle will move + float s = (randomVelocity.x * ExplosionDuration) + (0.5 * a * pow(ExplosionDuration, 2)); + + Output.ExplosionColor = EndColor * (length(triangleCenter2ExplosionRadius) / s); + } + else + { + Output.ExplosionColor = EndColor * timePercetage; + } + + // for every vertex on the triangle... + for (int i = 0; i < gl_in.length(); i++) + { + // move the triangle to the blast radius + vec3 ExplodedPosition = Input[i].Position + triangleCenter2ExplosionRadius; + + // pass through vertex data + Output.Normal = Input[i].Normal; + Output.Position = Input[i].Position; + Output.TextureCoordinate = Input[i].TextureCoordinate; + + // convert to model space for the gravity to always be in -y + vec4 ExplodedPositionInModelSpace = M * vec4(ExplodedPosition, 1.0); + + // if there is gravity, apply it + //if (Gravity == true) + //{ + // // ---DO THIS----> //ExplodedPositionInModelSpace.y = ExplodedPositionInModelSpace.y - TimeSinceHit; + // + // ExplodedPositionInModelSpace.y = ExplodedPositionInModelSpace.y - pow(TimeSinceDeath, 2); + //} + + // convert to screen space + gl_Position = P*V * ExplodedPositionInModelSpace; + EmitVertex(); + } + } + else + { + // if explosion color should be affected by distance instead of time... + if (ColorByDistance == true) + { + Output.ExplosionColor = vec4(0.0); + } + else + { + Output.ExplosionColor = EndColor * timePercetage; + } + + // for every vertex on the triangle... + for(int i = 0; i < gl_in.length(); i++) + { + // pass through vertex data + Output.Normal = Input[i].Normal; + Output.Position = Input[i].Position; + Output.TextureCoordinate = Input[i].TextureCoordinate; + + // no change in position, pass through vertex + gl_Position = gl_in[i].gl_Position; + EmitVertex(); + } + } + + //EndPrimitive(); +} diff --git a/resources/Shaders/ExplosionEffect.vert.glsl b/resources/Shaders/ExplosionEffect.vert.glsl new file mode 100644 index 00000000..04e1bda2 --- /dev/null +++ b/resources/Shaders/ExplosionEffect.vert.glsl @@ -0,0 +1,36 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec3 Normal; +layout(location = 2) in vec3 Tangent; +layout(location = 3) in vec3 BiTangent; +layout(location = 4) in vec2 TextureCoords; +layout(location = 5) in vec4 DiffuseVertexColor; +layout(location = 6) in vec4 SpecularVertexColor; +layout(location = 7) in vec4 BoneIndices1; +layout(location = 8) in vec4 BoneIndices2; +layout(location = 9) in vec4 BoneWeights1; +layout(location = 10) in vec4 BoneWeights2; + +out VertexData{ + vec3 Position; + vec3 Normal; + vec2 TextureCoordinate; + vec4 DiffuseColor; + vec4 ExplosionColor; +}Output; + +void main() +{ + gl_Position = P*V*M * vec4(Position, 1.0); + + Output.Position = Position; + Output.TextureCoordinate = TextureCoords; + Output.Normal = Normal; + Output.DiffuseColor = DiffuseVertexColor; + Output.ExplosionColor = vec4(0.0); +} \ No newline at end of file diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index 57b1d627..42500b44 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -6,9 +6,12 @@ uniform mat4 P; uniform vec4 Color; uniform vec4 DiffuseColor; uniform vec2 ScreenDimensions; +uniform vec4 FillColor; +uniform float FillPercentage; layout (binding = 0) uniform sampler2D DiffuseTexture; layout (binding = 1) uniform sampler2D GlowMap; + #define TILE_SIZE 16 struct LightSource { @@ -47,6 +50,7 @@ in VertexData{ vec3 Position; vec3 Normal; vec2 TextureCoordinate; + vec4 ExplosionColor; }Input; out vec4 sceneColor; @@ -134,12 +138,23 @@ void main() totalLighting.Specular += light_result.Specular; } - //sceneColor += Input.DiffuseColor; - vec4 color_result = DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * diffuseTexel * Color; + + vec4 color_result = (DiffuseColor + Input.ExplosionColor) * (totalLighting.Diffuse + totalLighting.Specular) * diffuseTexel * Color; + + + float pos = ((P * vec4(Input.Position, 1)).y + 1.0)/2.0; + + if(pos <= FillPercentage) { + color_result += FillColor; + } //bloomColor = vec4(0.3, 0.8, 0.6, 1.0); sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); //These if statements should be removed if they are slow. color_result += glowTexel; + + + + bloomColor = vec4(clamp(color_result.xyz - 1.0, 0, 100), 1.0); /* if(color_result.x > 1 || color_result.y > 1 || color_result.z > 1) { @@ -147,11 +162,10 @@ void main() } else { bloomColor = vec4(0.0, 0.0, 0.0, 1.0); } */ + + - //sceneColor += Input.DiffuseColor * (totalLighting.Diffuse) * diffuseTexel * Color; - //sceneColor += Input.DiffuseColor + vec4(0.0, LightGrids.Data[currentTile].Amount/3, 0, 1); - //sceneColor = diffuseTexel * Input.DiffuseColor * Color; - //sceneColor += vec4(currentTile/3600.f, 0, 0, 1); + //Tiled Debug Code /* diff --git a/resources/Shaders/ForwardPlus.vert.glsl b/resources/Shaders/ForwardPlus.vert.glsl index c51216cb..bd7df47e 100644 --- a/resources/Shaders/ForwardPlus.vert.glsl +++ b/resources/Shaders/ForwardPlus.vert.glsl @@ -17,6 +17,7 @@ out VertexData{ vec3 Position; vec3 Normal; vec2 TextureCoordinate; + vec4 ExplosionColor; }Output; void main() @@ -36,4 +37,5 @@ void main() Output.Position = (boneTransform * vec4(Position, 1.0)).xyz; Output.TextureCoordinate = TextureCoords; Output.Normal = vec3(M * vec4(Normal, 0.0)); + Output.ExplosionColor = vec4(0.0); } \ No newline at end of file diff --git a/src/Engine/Collision/CollidableOctreeSystem.cpp b/src/Engine/Collision/CollidableOctreeSystem.cpp index e5da7910..476414dd 100644 --- a/src/Engine/Collision/CollidableOctreeSystem.cpp +++ b/src/Engine/Collision/CollidableOctreeSystem.cpp @@ -8,7 +8,7 @@ void CollidableOctreeSystem::Update(double dt) void CollidableOctreeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { if (entity.HasComponent("AABB")) { - boost::optional absoluteAABB = Collision::EntityAbsoluteAABB(entity); + boost::optional absoluteAABB = Collision::EntityAbsoluteAABB(entity); if (absoluteAABB) { m_Octree->AddDynamicObject(*absoluteAABB); } diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index b30ae927..3f5cf0d3 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -239,20 +239,6 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model return hit; } -bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon) -{ - const glm::vec3& ma1 = first.MaxCorner(); - const glm::vec3& ma2 = second.MaxCorner(); - const glm::vec3& mi1 = first.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")) { @@ -283,7 +269,7 @@ bool attachAABBComponentFromModel(World* world, EntityID id) return true; } -boost::optional EntityAbsoluteAABB(EntityWrapper& entity) +boost::optional EntityAbsoluteAABB(EntityWrapper& entity) { if (!entity.HasComponent("AABB")) { return boost::none; @@ -294,7 +280,11 @@ boost::optional EntityAbsoluteAABB(EntityWrapper& entity) glm::vec3 absScale = Transform::AbsoluteScale(entity.World, entity.ID); glm::vec3 origin = absPosition + (glm::vec3)cAABB["Origin"]; glm::vec3 size = (glm::vec3)cAABB["Size"] * absScale; - return AABB::FromOriginSize(origin, size); + + EntityAABB aabb = EntityAABB::FromOriginSize(origin, size); + aabb.Entity = entity; + + return aabb; } } diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index ba841e36..382238e7 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -9,29 +9,27 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c } ComponentWrapper& cPhysics = entity["Physics"]; - boost::optional boundingBox = Collision::EntityAbsoluteAABB(entity); + boost::optional boundingBox = Collision::EntityAbsoluteAABB(entity); if (!boundingBox) { return; } ComponentWrapper& cTransform = entity["Transform"]; - AABB& boxA = *boundingBox; + EntityAABB& boxA = *boundingBox; - //Press 'Z' to enable/disable collision. - if (zPress) { - return; - } - - // Collide against octree - std::vector octreeResult; - m_Octree->ObjectsInSameRegion(*boundingBox, octreeResult); - for (auto& boxB : octreeResult) { + // Collide against octree items + m_OctreeResult.clear(); + m_Octree->ObjectsInSameRegion(*boundingBox, m_OctreeResult); + for (auto& boxB : m_OctreeResult) { glm::vec3 resolutionVector; - if (Collision::IsSameBoxProbably(boxA, boxB)) { + if (boxA.Entity == boxB.Entity) { continue; } + if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { (glm::vec3&)cTransform["Position"] += resolutionVector; - ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; + if (resolutionVector.y > 0) { + ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; + } } } @@ -56,12 +54,4 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c // (glm::vec3&)cTransform["Position"] += resolutionVector; // } //} -} - -bool CollisionSystem::OnKeyUp(const Events::KeyUp & event) -{ - if (event.KeyCode == GLFW_KEY_Z) { - zPress = !zPress; - } - return false; -} +} \ No newline at end of file diff --git a/src/Engine/Collision/TriggerSystem.cpp b/src/Engine/Collision/TriggerSystem.cpp index ca169e16..dc7c77ff 100644 --- a/src/Engine/Collision/TriggerSystem.cpp +++ b/src/Engine/Collision/TriggerSystem.cpp @@ -3,79 +3,72 @@ #include "Core/AABB.h" #include "Rendering/Model.h" -void TriggerSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) +void TriggerSystem::UpdateComponent(EntityWrapper& triggerEntity, ComponentWrapper& cTrigger, double dt) { - //Currently only players can trigger things. - auto players = m_World->GetComponents("Player"); - if (players == nullptr) { - return; - } - EntityID tId = component.EntityID; - boost::optional triggerBox = Collision::EntityAbsoluteAABB(entity); - //The trigger *should* have a bounding box, or something, to test against so it can be triggered. + // The trigger *should* have a bounding box, or something, to test against so it can be triggered. + boost::optional triggerBox = Collision::EntityAbsoluteAABB(triggerEntity); if (!triggerBox) { return; } - for (auto& pc : *players) { - EntityID pId = pc.EntityID; - boost::optional playerBox = Collision::EntityAbsoluteAABB(EntityWrapper(m_World, pId)); - //The player can't trigger anything without an AABB. - if (!playerBox) { - 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. + + m_OctreeOut.clear(); + m_Octree->ObjectsInSameRegion(*triggerBox, m_OctreeOut); + + for (EntityAABB& colliderBox : m_OctreeOut) { + EntityWrapper colliderEntity = colliderBox.Entity; + + if (Collision::AABBVsAABB(*triggerBox, colliderBox)) { AABB completelyInsideBox; - bool playerFitsInTrigger = glm::all(glm::greaterThan((*triggerBox).Size(), (*playerBox).Size())); - if (playerFitsInTrigger) { - completelyInsideBox = AABB::FromOriginSize((*triggerBox).Origin(), (*triggerBox).Size() - 2.0f * (*playerBox).Size()); + bool colliderFitsInTrigger = glm::all(glm::greaterThan((*triggerBox).Size(), colliderBox.Size())); + if (colliderFitsInTrigger) { + completelyInsideBox = AABB::FromOriginSize((*triggerBox).Origin(), (*triggerBox).Size() - 2.0f * colliderBox.Size()); } - if (playerFitsInTrigger && Collision::AABBVsAABB(completelyInsideBox, *playerBox)) { - //Entity is completely inside the trigger. - //If it was only touching before, it is erased. - m_EntitiesTouchingTrigger[tId].erase(pId); - std::unordered_set& 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(pId, tId); + if (colliderFitsInTrigger && Collision::AABBVsAABB(completelyInsideBox, colliderBox)) { + // Entity is completely inside the trigger. + // If it was only touching before, it is erased. + m_EntitiesTouchingTrigger[triggerEntity].erase(colliderEntity); + auto& completeSet = m_EntitiesCompletelyInTrigger[triggerEntity]; + if (completeSet.count(colliderEntity) == 0) { + // If it wasn't completely in the trigger, throw Enter and add to the set. + completeSet.insert(colliderEntity); + publish(colliderEntity, triggerEntity); } } else { - //Entity is only touching the trigger. - std::unordered_set& touchSet = m_EntitiesTouchingTrigger[tId]; - std::unordered_set& completeSet = m_EntitiesCompletelyInTrigger[tId]; - const auto& it = completeSet.find(pId); + // Entity is only touching the trigger. + auto& touchSet = m_EntitiesTouchingTrigger[triggerEntity]; + auto& completeSet = m_EntitiesCompletelyInTrigger[triggerEntity]; + const auto& it = completeSet.find(colliderEntity); //If it was completely inside before. if (it != completeSet.end()) { completeSet.erase(it); - touchSet.insert(pId); + touchSet.insert(colliderEntity); //If it was completely outside before. - } else if (touchSet.count(pId) == 0) { - publish(pId, tId); - touchSet.insert(pId); + } else if (touchSet.count(colliderEntity) == 0) { + publish(colliderEntity, triggerEntity); + touchSet.insert(colliderEntity); } - //Else, it was touching the trigger last frame too and nothing is done. + // Else, it was touching the trigger last frame too and nothing is done. } + } else { + // Entity is not touching the trigger, + // Throw event if it was previously. + if (throwLeaveIfWasInTrigger(m_EntitiesTouchingTrigger[triggerEntity], colliderEntity, triggerEntity)) { + 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[triggerEntity], colliderEntity, triggerEntity); } } } -bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set& triggerSet, EntityID pId, EntityID tId) +bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set& triggerSet, EntityWrapper colliderEntity, EntityWrapper triggerEntity) { - const auto& it = triggerSet.find(pId); + const auto& it = triggerSet.find(colliderEntity); if (it != triggerSet.end()) { //If it was in the trigger, but not anymore, throw leaveEvent and erase from the set. triggerSet.erase(it); - publish(pId, tId); + publish(colliderEntity, triggerEntity); return true; } return false; diff --git a/src/Engine/Core/AABB.cpp b/src/Engine/Core/AABB.cpp index 55b362fe..13e92d9c 100644 --- a/src/Engine/Core/AABB.cpp +++ b/src/Engine/Core/AABB.cpp @@ -20,10 +20,6 @@ AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos) } } -AABB::AABB(const glm::vec4& minPos, const glm::vec4& maxPos) - : AABB(glm::vec3(minPos), glm::vec3(maxPos)) -{ } - AABB AABB::FromOriginSize(const glm::vec3& origin, const glm::vec3& size) { return AABB(origin - (size/2.f), origin + (size/2.f)); diff --git a/src/Engine/Core/EntityFile.cpp b/src/Engine/Core/EntityFile.cpp index a8e93e49..d5585317 100644 --- a/src/Engine/Core/EntityFile.cpp +++ b/src/Engine/Core/EntityFile.cpp @@ -20,7 +20,7 @@ void EntityFile::Parse(const EntityFileHandler* handler) const { using namespace xercesc; - EntityFileSAXHandler saxHandler(handler, nullptr); + EntityFileSAXHandler saxHandler(handler, m_SAX2XMLReader); setReaderFeatures(m_SAX2XMLReader); m_SAX2XMLReader->setContentHandler(&saxHandler); m_SAX2XMLReader->setErrorHandler(&saxHandler); @@ -37,6 +37,7 @@ void EntityFile::setReaderFeatures(xercesc::SAX2XMLReader* reader) reader->setFeature(XMLUni::fgSAX2CoreNameSpaces, true); reader->setFeature(XMLUni::fgXercesSchema, true); reader->setFeature(XMLUni::fgXercesSchemaFullChecking, true); + reader->setFeature(XMLUni::fgXercesCalculateSrcOfs, true); } std::size_t EntityFile::GetTypeStride(std::string typeName) @@ -111,8 +112,9 @@ void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& fie } catch (const boost::bad_lexical_cast&) { } } -EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader) : m_Handler(handler) -, m_Reader(reader) +EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader) + : m_Handler(handler) + , m_Reader(reader) { // 0 is imaginary base parent m_EntityStack.push(0); @@ -188,21 +190,29 @@ void EntityFileSAXHandler::characters(const XMLCh* const chars, const XMLSize_t void EntityFileSAXHandler::fatalError(const xercesc::SAXParseException& e) { - XS::ToString s(e.getMessage()); - LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str()); - //throw e; + std::string message = XS::ToString(e.getMessage()); + std::string systemId = XS::ToString(e.getSystemId()); + XMLFileLoc line = e.getLineNumber(); + XMLFileLoc column = e.getColumnNumber(); + LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tFatal Error: %s", systemId.c_str(), line, column, message.c_str()); } void EntityFileSAXHandler::error(const xercesc::SAXParseException& e) { - XS::ToString s(e.getMessage()); - LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str()); + std::string message = XS::ToString(e.getMessage()); + std::string systemId = XS::ToString(e.getSystemId()); + XMLFileLoc line = e.getLineNumber(); + XMLFileLoc column = e.getColumnNumber(); + LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tError: %s", systemId.c_str(), line, column, message.c_str()); } void EntityFileSAXHandler::warning(const xercesc::SAXParseException& e) { - XS::ToString s(e.getMessage()); - LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str()); + std::string message = XS::ToString(e.getMessage()); + std::string systemId = XS::ToString(e.getSystemId()); + XMLFileLoc line = e.getLineNumber(); + XMLFileLoc column = e.getColumnNumber(); + LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tWarning: %s", systemId.c_str(), line, column, message.c_str()); } void EntityFileSAXHandler::onStartEntity(const xercesc::Attributes& attrs) diff --git a/src/Engine/Core/EntityFilePreprocessor.cpp b/src/Engine/Core/EntityFilePreprocessor.cpp index 7b4b2bb7..2a1d22d6 100644 --- a/src/Engine/Core/EntityFilePreprocessor.cpp +++ b/src/Engine/Core/EntityFilePreprocessor.cpp @@ -65,6 +65,7 @@ void EntityFilePreprocessor::parseComponentInfo() // Name compInfo.Name = XS::ToString(element->getName()); + bool brk = compInfo.Name == "HiddenForLocalPlayer"; // Known allocation compInfo.Meta->Allocation = m_ComponentCounts[compInfo.Name]; // Annotation @@ -90,7 +91,7 @@ void EntityFilePreprocessor::parseComponentInfo() // auto modelGroupParticle = complexTypeDefinition->getParticle(); if (modelGroupParticle == nullptr || modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) { - //LOG_ERROR("Failed to parse component definition for \"%s\": Model group particle was null or wasn't TERM_MODELGROUP!", compInfo.Name.c_str()); + LOG_ERROR("Failed to parse component definition for \"%s\": Model group particle was null or wasn't TERM_MODELGROUP!", compInfo.Name.c_str()); continue; } auto modelGroup = modelGroupParticle->getModelGroupTerm(); diff --git a/src/Engine/Core/EntityWrapper.cpp b/src/Engine/Core/EntityWrapper.cpp index 02d9246a..071329a3 100644 --- a/src/Engine/Core/EntityWrapper.cpp +++ b/src/Engine/Core/EntityWrapper.cpp @@ -3,6 +3,11 @@ const EntityWrapper EntityWrapper::Invalid = EntityWrapper(nullptr, EntityID_Invalid); +const std::string EntityWrapper::Name() +{ + return World->GetName(ID); +} + bool EntityWrapper::HasComponent(const std::string& componentName) { if (!Valid()) { @@ -22,18 +27,7 @@ EntityWrapper EntityWrapper::Parent() EntityWrapper EntityWrapper::FirstChildByName(const std::string& name) { - auto itPair = this->World->GetChildren(this->ID); - if (itPair.first == itPair.second) { - return EntityWrapper::Invalid; - } - - for (auto it = itPair.first; it != itPair.second; ++it) { - if (this->World->GetName(it->second) == name) { - return EntityWrapper(this->World, it->second); - } - } - - return EntityWrapper::Invalid; + return firstChildByNameRecursive(name, this->ID); } EntityWrapper EntityWrapper::FirstParentWithComponent(const std::string& componentType) @@ -103,8 +97,29 @@ EntityWrapper::operator EntityID() const return this->ID; } -EntityWrapper::operator bool() +EntityWrapper EntityWrapper::firstChildByNameRecursive(const std::string& name, EntityID parent) { - return this->Valid(); + if (!this->World->ValidEntity(parent)) { + return EntityWrapper::Invalid; + } + + auto itPair = this->World->GetChildren(parent); + if (itPair.first == itPair.second) { + return EntityWrapper::Invalid; + } + + for (auto it = itPair.first; it != itPair.second; ++it) { + std::string itName = this->World->GetName(it->second); + if (itName == name) { + return EntityWrapper(this->World, it->second); + } else if (it->second != EntityID_Invalid) { + EntityWrapper result = firstChildByNameRecursive(name, it->second); + if (result != EntityWrapper::Invalid) { + return result; + } + } + } + + return EntityWrapper::Invalid; } diff --git a/src/Engine/Core/Octree.cpp b/src/Engine/Core/Octree.cpp index 18effea5..f3cafcfc 100644 --- a/src/Engine/Core/Octree.cpp +++ b/src/Engine/Core/Octree.cpp @@ -105,8 +105,7 @@ bool Child::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const 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)) { + if (Collision::AABBVsAABB(boxToTest, objBox)) { outBoxIntersected = objBox; return true; } diff --git a/src/Engine/Core/Transform.cpp b/src/Engine/Core/Transform.cpp index c9869014..31b4493f 100644 --- a/src/Engine/Core/Transform.cpp +++ b/src/Engine/Core/Transform.cpp @@ -1,5 +1,17 @@ #include "Core/Transform.h" +glm::mat4 Transform::AbsoluteTransformation(EntityWrapper entity) +{ + glm::mat4 t = glm::mat4(1.f); + + while (entity.Valid()) { + t = glm::translate((glm::vec3&)entity["Transform"]["Position"]) * glm::toMat4(glm::quat((glm::vec3&)entity["Transform"]["Orientation"])) * glm::scale((glm::vec3&)entity["Transform"]["Scale"]) * t; + entity = entity.Parent(); + } + + return t; +} + glm::vec3 Transform::AbsolutePosition(EntityWrapper entity) { return AbsolutePosition(entity.World, entity.ID); @@ -19,6 +31,19 @@ glm::vec3 Transform::AbsolutePosition(World* world, EntityID entity) return position; } +glm::vec3 Transform::AbsoluteOrientationEuler(EntityWrapper entity) +{ + glm::vec3 orientation; + + while (entity.Valid()) { + ComponentWrapper transform = entity["Transform"]; + orientation += (glm::vec3)transform["Orientation"]; + entity = entity.Parent(); + } + + return orientation; +} + glm::quat Transform::AbsoluteOrientation(EntityWrapper entity) { return AbsoluteOrientation(entity.World, entity.ID); @@ -62,6 +87,8 @@ glm::mat4 Transform::ModelMatrix(EntityWrapper entity) glm::mat4 Transform::ModelMatrix(EntityID entity, World* world) { + return AbsoluteTransformation(EntityWrapper(world, entity)); + glm::vec3 position = Transform::AbsolutePosition(world, entity); glm::quat orientation = Transform::AbsoluteOrientation(world, entity); glm::vec3 scale = Transform::AbsoluteScale(world, entity); diff --git a/src/Engine/Core/Util/Logging.cpp b/src/Engine/Core/Util/Logging.cpp index 5c88d98b..63a6f380 100644 --- a/src/Engine/Core/Util/Logging.cpp +++ b/src/Engine/Core/Util/Logging.cpp @@ -4,4 +4,40 @@ _LOG_LEVEL LOG_LEVEL = LOG_LEVEL_DEBUG; #else _LOG_LEVEL LOG_LEVEL = LOG_LEVEL_INFO; -#endif \ No newline at end of file +#endif + +const char* _LOG_LEVEL_PREFIX[] = +{ + "EE: ", + "", + "WW: ", + "DD: " +}; + +void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int line, const char* format, ...) +{ + if (logLevel > LOG_LEVEL) { + return; + } + + char* message = nullptr; + va_list args; + + va_start(args, format); + size_t size = vsnprintf(message, 0, format, args) + 1; + va_end(args); + + va_start(args, format); + message = new char[size]; + vsnprintf(message, size, format, args); + va_end(args); + + if (logLevel == LOG_LEVEL_ERROR) { + std::cerr << file << ":" << line << " " << func << std::endl; + std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; + } else { + std::cout << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl; + } + + delete[] message; +} \ No newline at end of file diff --git a/src/Engine/Core/World.cpp b/src/Engine/Core/World.cpp index 0c4c9ce4..8b212d31 100644 --- a/src/Engine/Core/World.cpp +++ b/src/Engine/Core/World.cpp @@ -54,8 +54,12 @@ ComponentWrapper World::AttachComponent(EntityID entity, const std::string& comp bool World::HasComponent(EntityID entity, const std::string& componentType) const { - ComponentPool* pool = m_ComponentPools.at(componentType); - return pool->KnowsEntity(entity); + auto it = m_ComponentPools.find(componentType); + if (it == m_ComponentPools.end()) { + return false; + } else { + return it->second->KnowsEntity(entity); + } } ComponentWrapper World::GetComponent(EntityID entity, const std::string& componentType) diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 390e69a5..01f15da9 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -1,4 +1,5 @@ #include "Editor/EditorGUI.h" +#include "Rendering/ESetCamera.h" EditorGUI::EditorGUI(World* world, EventBroker* eventBroker) : m_World(world) @@ -233,10 +234,12 @@ void EditorGUI::drawComponents(EntityWrapper entity) componentTypes.push_back(pair.first.c_str()); } } + // Sort components in alphabetical order + std::sort(componentTypes.begin(), componentTypes.end(), compareCharArray); // Draw combo box ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() - 10.f); int selectedItem = -1; - if (ImGui::Combo("", &selectedItem, componentTypes.data(), componentTypes.size())) { + if (ImGui::Combo("", &selectedItem, componentTypes.data(), componentTypes.size(), componentTypes.size())) { if (selectedItem != -1) { if (m_OnComponentAttach != nullptr) { std::string chosenComponentType(componentTypes.at(selectedItem)); @@ -282,9 +285,8 @@ bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci) // Draw component fields ComponentWrapper& component = entity.World->GetComponent(entity.ID, ci.Name); - for (auto& kv : ci.Fields) { - const std::string& fieldName = kv.first; - const ComponentInfo::Field_t& field = kv.second; + for (auto& fieldName : ci.FieldsInOrder) { + const ComponentInfo::Field_t& field = ci.Fields.at(fieldName); // Draw the field widget based on its type bool dirty = drawComponentField(component, field); @@ -305,6 +307,14 @@ bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci) } } + if (ci.Name == "Camera") { + if (ImGui::Button("Activate")) { + Events::SetCamera e; + e.CameraEntity = entity; + m_EventBroker->Publish(e); + } + } + return true; } @@ -635,6 +645,11 @@ void EditorGUI::openModal(const std::string& modal) m_ModalsToOpen.insert(modal); } +bool EditorGUI::compareCharArray(const char* c1, const char* c2) +{ + return strcmp(c1, c2) < 0; +} + void EditorGUI::SetDirty(EntityWrapper entity) { EntityWrapper baseParent = entity; diff --git a/src/Engine/Editor/EditorRenderSystem.cpp b/src/Engine/Editor/EditorRenderSystem.cpp index ed054052..7caa4044 100644 --- a/src/Engine/Editor/EditorRenderSystem.cpp +++ b/src/Engine/Editor/EditorRenderSystem.cpp @@ -12,7 +12,7 @@ EditorRenderSystem::EditorRenderSystem(World* m_World, EventBroker* eventBroker, void EditorRenderSystem::Update(double dt) { - if (m_CurrentCamera) { + if (m_CurrentCamera.Valid()) { ComponentWrapper cameraTransform = m_CurrentCamera["Transform"]; m_EditorCamera->SetPosition(cameraTransform["Position"]); m_EditorCamera->SetOrientation(glm::quat((const glm::vec3&)cameraTransform["Orientation"])); @@ -48,7 +48,7 @@ void EditorRenderSystem::Update(double dt) EntityWrapper entity(m_World, cModel.EntityID); glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World); for (auto matGroup : model->MaterialGroups()) { - std::shared_ptr modelJob = std::make_shared(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World); + std::shared_ptr modelJob = std::make_shared(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World, glm::vec4(0), 0.f); scene.ForwardJobs.push_back(modelJob); } } diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 9c0e2e47..6ffd0e24 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -203,7 +203,7 @@ bool EditorSystem::OnSetCamera(const Events::SetCamera& e) m_ActualCamera = e.CameraEntity; Events::SetCamera e2; e2.CameraEntity = m_EditorCamera; - m_EventBroker->Publish(e2); + //m_EventBroker->Publish(e2); } return true; } diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 4ebf551d..6c43cc8b 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -147,6 +147,7 @@ void Client::parsePlayersSpawned(Packet& packet) e.Player = EntityWrapper(m_World, m_ServerIDToClientID[packet.ReadPrimitive()]); e.Spawner = EntityWrapper(m_World, m_ServerIDToClientID[packet.ReadPrimitive()]); e.PlayerID = -1; + e.PlayerName = packet.ReadString(); m_EventBroker->Publish(e); } @@ -345,7 +346,7 @@ bool Client::OnPlayerDamage(const Events::PlayerDamage & e) { Packet packet(MessageType::OnPlayerDamage, m_SendPacketID); packet.WritePrimitive(e.Damage); - packet.WritePrimitive(e.Player.ID); + packet.WritePrimitive(m_ClientIDToServerID.at(e.Player.ID)); send(packet); return false; } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index a29f4f02..adf810aa 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -269,6 +269,7 @@ void Server::parseOnInputCommand(Packet& packet) Events::InputCommand e; e.Command = packet.ReadString(); e.PlayerID = player; // Set correct player id + e.Player = EntityWrapper(m_World, m_ConnectedPlayers.at(player).EntityID); e.Value = packet.ReadPrimitive(); m_EventBroker->Publish(e); //LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); @@ -405,6 +406,8 @@ bool Server::OnPlayerSpawned(const Events::PlayerSpawned & e) Packet packet = Packet(MessageType::OnPlayerSpawned); packet.WritePrimitive(e.Player.ID); packet.WritePrimitive(e.Spawner.ID); + // We don't send PlayerID here because it will always be set to -1 + packet.WriteString(m_ConnectedPlayers[e.PlayerID].Name); send(e.PlayerID, packet); return false; } diff --git a/src/Engine/Rendering/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index 44c88a16..efd206d3 100644 --- a/src/Engine/Rendering/DrawBloomPass.cpp +++ b/src/Engine/Rendering/DrawBloomPass.cpp @@ -34,7 +34,6 @@ void DrawBloomPass::InitializeShaderPrograms() void DrawBloomPass::InitializeBuffers() { - printf("x:%f\ny:%f", m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height); GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); m_GaussianFrameBuffer_horiz.AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_horiz, GL_COLOR_ATTACHMENT0))); diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index 9d36db2e..006790cd 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -25,7 +25,7 @@ void DrawFinalPass::InitializeFrameBuffers() //GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); //GenerateMipMapTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_FLOAT, 4); - + m_FinalPassFrameBuffer.AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT))); m_FinalPassFrameBuffer.AddResource(std::shared_ptr(new Texture2D(&m_SceneTexture, GL_COLOR_ATTACHMENT0))); m_FinalPassFrameBuffer.AddResource(std::shared_ptr(new Texture2D(&m_BloomTexture, GL_COLOR_ATTACHMENT1))); @@ -42,6 +42,15 @@ void DrawFinalPass::InitializeShaderPrograms() m_ForwardPlusProgram->BindFragDataLocation(0, "sceneColor"); m_ForwardPlusProgram->BindFragDataLocation(1, "bloomColor"); m_ForwardPlusProgram->Link(); + + m_ExplosionEffectProgram = ResourceManager::Load("#ExplosionEffectProgram"); + m_ExplosionEffectProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); + m_ExplosionEffectProgram->AddShader(std::shared_ptr(new GeometryShader("Shaders/ExplosionEffect.geom.glsl"))); + m_ExplosionEffectProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlus.frag.glsl"))); + m_ExplosionEffectProgram->Compile(); + m_ExplosionEffectProgram->BindFragDataLocation(0, "sceneColor"); + m_ExplosionEffectProgram->BindFragDataLocation(1, "bloomColor"); + m_ExplosionEffectProgram->Link(); } void DrawFinalPass::Draw(RenderScene& scene) @@ -49,54 +58,108 @@ void DrawFinalPass::Draw(RenderScene& scene) GLERROR("DrawFinalPass::Draw: Pre"); DrawFinalPassState* state = new DrawFinalPassState(m_FinalPassFrameBuffer.GetHandle()); - - m_ForwardPlusProgram->Bind(); - GLuint shaderHandle = m_ForwardPlusProgram->GetHandle(); - - if (scene.ClearDepth) { - glClear(GL_DEPTH_BUFFER_BIT); - } - - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO()); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO()); - - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height); + GLuint shaderHandle; //TODO: Render: Add code for more jobs than modeljobs. for (auto &job : scene.ForwardJobs) { - auto modelJob = std::dynamic_pointer_cast(job); - if(modelJob) { - //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->Matrix)); - glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color)); - glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(modelJob->DiffuseColor)); + auto explosionEffectJob = std::dynamic_pointer_cast(job); + if (explosionEffectJob) { + m_ExplosionEffectProgram->Bind(); + shaderHandle = m_ExplosionEffectProgram->GetHandle(); //--- - glActiveTexture(GL_TEXTURE0); - if(modelJob->DiffuseTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture); + GLERROR("DrawFinalPass::ExplosionEffect: 1"); + //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(explosionEffectJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(explosionEffectJob->Color)); + glUniform3fv(glGetUniformLocation(shaderHandle, "ExplosionOrigin"), 1, glm::value_ptr(explosionEffectJob->ExplosionOrigin)); + glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), explosionEffectJob->TimeSinceDeath); + glUniform1f(glGetUniformLocation(shaderHandle, "ExplosionDuration"), explosionEffectJob->ExplosionDuration); + glUniform4fv(glGetUniformLocation(shaderHandle, "EndColor"), 1, glm::value_ptr(explosionEffectJob->EndColor)); + glUniform1i(glGetUniformLocation(shaderHandle, "Randomness"), explosionEffectJob->Randomness); + glUniform1fv(glGetUniformLocation(shaderHandle, "RandomNumbers"), 50, explosionEffectJob->RandomNumbers.data()); + glUniform1f(glGetUniformLocation(shaderHandle, "RandomnessScalar"), explosionEffectJob->RandomnessScalar); + glUniform2fv(glGetUniformLocation(shaderHandle, "Velocity"), 1, glm::value_ptr(explosionEffectJob->Velocity)); + glUniform1i(glGetUniformLocation(shaderHandle, "ColorByDistance"), explosionEffectJob->ColorByDistance); + glUniform1i(glGetUniformLocation(shaderHandle, "ExponentialAccelaration"), explosionEffectJob->ExponentialAccelaration); + glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(explosionEffectJob->DiffuseColor)); + GLERROR("DrawFinalPass::ExplosionEffect: 2"); + + if (explosionEffectJob->Model->m_RawModel->m_Skeleton != nullptr) { + + if (explosionEffectJob->Animation != nullptr) { + std::vector frameBones = explosionEffectJob->Skeleton->GetFrameBones(*explosionEffectJob->Animation, explosionEffectJob->AnimationTime); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } + } + + //TODO: Renderer: bättre textur felhantering samt fler texturer stöd + if (explosionEffectJob->DiffuseTexture != nullptr) { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, explosionEffectJob->DiffuseTexture->m_Texture); } else { + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); } - glActiveTexture(GL_TEXTURE1); - if (modelJob->IncandescenceTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, modelJob->IncandescenceTexture->m_Texture); - } else { + glBindVertexArray(explosionEffectJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, explosionEffectJob->Model->ElementBuffer); + glDrawElements(GL_TRIANGLES, explosionEffectJob->EndIndex - explosionEffectJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(explosionEffectJob->StartIndex*sizeof(unsigned int))); + GLERROR("DrawFinalPass::ExplosionEffect: END"); + //m_ExplosionEffectProgram->Unbind(); + + } else { + auto modelJob = std::dynamic_pointer_cast(job); + if (modelJob) { + m_ForwardPlusProgram->Bind(); + GLERROR("1.1"); + shaderHandle = m_ForwardPlusProgram->GetHandle(); + + if (scene.ClearDepth) { + glClear(GL_DEPTH_BUFFER_BIT); + } + + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO()); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO()); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height); + + //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->Matrix)); + glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color)); + glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(modelJob->DiffuseColor)); + + glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(modelJob->FillColor)); + glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), modelJob->FillPercentage); + + + 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); + } + glActiveTexture(GL_TEXTURE1); + if (modelJob->IncandescenceTexture != nullptr) { + glBindTexture(GL_TEXTURE_2D, modelJob->IncandescenceTexture->m_Texture); + } else { + glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); + } + + /*if(modelJob->GlowMap != nullptr) { + glBindTexture(GL_TEXTURE_2D, modelJob->GlowMap->m_Texture); + } else { glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); - } + }*/ - /*if(modelJob->GlowMap != nullptr) { - glBindTexture(GL_TEXTURE_2D, modelJob->GlowMap->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); - }*/ - - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { - if (modelJob->Animation != nullptr) { - std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); + //TODO: Fixa så att modelsJobs kan spela upp olika animationer och så att den kan få in en tid istället för 1.0f - Hälsningar Johan och Andreas :) + if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + if (modelJob->Animation != nullptr) { + std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); // std::vector frameBones2 = modelJob->Skeleton->GetFrameBones(*modelJob->Skeleton->GetAnimation("Walk"), modelJob->AnimationTime); // // @@ -104,14 +167,20 @@ void DrawFinalPass::Draw(RenderScene& scene) // frameBones[i] = frameBones[i] * glm::mat4(glm::quat(glm::vec3(0.f, 0.f, 0.f)));//* frameBones2[i]; // } - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } } - } - glBindVertexArray(modelJob->Model->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); - glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int))); + glBindVertexArray(modelJob->Model->VAO); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); + glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex*sizeof(unsigned int))); + GLERROR("DrawFinalPass::Model: END"); + // m_ForwardPlusProgram->Unbind(); + + } } + } GLERROR("DrawFinalPass::Draw: END"); delete state; diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index 2ed6d1a9..3a7d5bfd 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -75,9 +75,9 @@ void PickingPass::Draw(RenderScene& scene) m_EntityColors[std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)] = glm::ivec2(pickColor[0], pickColor[1]); if (m_ColorCounter[0] > 255) { m_ColorCounter[0] = 0; - m_ColorCounter[1]++; + m_ColorCounter[1] += 5; } else { - m_ColorCounter[0]++; + m_ColorCounter[0] += 50; } } diff --git a/src/Engine/Rendering/RenderSystem.cpp b/src/Engine/Rendering/RenderSystem.cpp index 58bbd1ee..f9114350 100644 --- a/src/Engine/Rendering/RenderSystem.cpp +++ b/src/Engine/Rendering/RenderSystem.cpp @@ -4,6 +4,7 @@ RenderSystem::RenderSystem(World* world, EventBroker* eventBroker, const IRender : System(world, eventBroker) , m_Renderer(renderer) , m_RenderFrame(renderFrame) + , m_World(world) { EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &RenderSystem::OnSetCamera); EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &RenderSystem::OnInputCommand); @@ -30,6 +31,16 @@ bool RenderSystem::OnSetCamera(Events::SetCamera& e) return true; } +bool RenderSystem::isChildOfACamera(EntityWrapper entity) +{ + return entity.FirstParentWithComponent("Camera").Valid(); +} + +bool RenderSystem::isChildOfCurrentCamera(EntityWrapper entity) +{ + return entity == m_CurrentCamera || entity.IsChildOf(m_CurrentCamera); +} + void RenderSystem::fillModels(std::list>& jobs) { auto models = m_World->GetComponents("Model"); @@ -37,20 +48,25 @@ void RenderSystem::fillModels(std::list>& jobs) return; } - for (auto& modelComponent : *models) { - bool visible = modelComponent["Visible"]; + for (auto& cModel : *models) { + bool visible = cModel["Visible"]; if (!visible) { continue; } - std::string resource = modelComponent["Resource"]; + std::string resource = cModel["Resource"]; if (resource.empty()) { continue; } - EntityWrapper entity(m_World, modelComponent.EntityID); + EntityWrapper entity(m_World, cModel.EntityID); - // Don't render the local player - if (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer)) { + // Only render children of a camera if that camera is currently active + if (isChildOfACamera(entity) && !isChildOfCurrentCamera(entity)) { + continue; + } + + // Hide things parented to local player if they have the HiddenFromLocalPlayer component + if (entity.HasComponent("HiddenForLocalPlayer") && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))) { continue; } @@ -68,10 +84,44 @@ void RenderSystem::fillModels(std::list>& jobs) } } - glm::mat4 modelMatrix = Transform::ModelMatrix(modelComponent.EntityID, m_World); + + float fillPercentage = 0.f; + glm::vec4 fillColor = glm::vec4(0); + if(m_World->HasComponent(cModel.EntityID, "Fill")) { + auto fillComponent = m_World->GetComponent(cModel.EntityID, "Fill"); + fillPercentage = (float)(double)fillComponent["Percentage"]; + fillColor = (glm::vec4)fillComponent["Color"]; + } + + glm::mat4 modelMatrix = Transform::ModelMatrix(cModel.EntityID, m_World); for (auto matGroup : model->MaterialGroups()) { - std::shared_ptr modelJob = std::shared_ptr(new ModelJob(model, m_Camera, modelMatrix, matGroup, modelComponent, m_World)); - jobs.push_back(modelJob); + if (m_World->HasComponent(cModel.EntityID, "ExplosionEffect")) { + auto explosionEffectComponent = m_World->GetComponent(cModel.EntityID, "ExplosionEffect"); + std::shared_ptr explosionEffectJob = std::shared_ptr(new ExplosionEffectJob( + explosionEffectComponent, + model, + m_Camera, + modelMatrix, + matGroup, + cModel, + m_World, + fillColor, + fillPercentage + )); + jobs.push_back(explosionEffectJob); + } else { + std::shared_ptr modelJob = std::shared_ptr(new ModelJob( + model, + m_Camera, + modelMatrix, + matGroup, + cModel, + m_World, + fillColor, + fillPercentage + )); + jobs.push_back(modelJob); + } } } } @@ -156,8 +206,8 @@ void RenderSystem::fillText(std::list>& jobs, World* } glm::mat4 modelMatrix = Transform::ModelMatrix(textComponent.EntityID, world); - std::shared_ptr modelJob = std::shared_ptr(new TextJob(modelMatrix, font, textComponent)); - jobs.push_back(modelJob); + std::shared_ptr textJob = std::shared_ptr(new TextJob(modelMatrix, font, textComponent)); + jobs.push_back(textJob); } } @@ -177,7 +227,6 @@ void RenderSystem::Update(double dt) m_Camera->SetOrientation(Transform::AbsoluteOrientation(m_CurrentCamera)); } - //Only supports opaque geometry atm RenderScene scene; scene.Camera = m_Camera; diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index f419bcaa..08b30afa 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -68,6 +68,15 @@ void Renderer::InitializeWindow() void Renderer::InitializeShaders() { m_BasicForwardProgram = ResourceManager::Load("#m_BasicForwardProgram"); + m_ExplosionEffectProgram = ResourceManager::Load("#ExplosionEffectProgram"); + //m_ExplosionEffectProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ExplosionEffect.vert.glsl"))); + //m_ExplosionEffectProgram->AddShader(std::shared_ptr(new GeometryShader("Shaders/ExplosionEffect.geom.glsl"))); + //m_ExplosionEffectProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ExplosionEffect.frag.glsl"))); + //m_ExplosionEffectProgram->Compile(); + //m_ExplosionEffectProgram->Link(); + + + } void Renderer::InputUpdate(double dt) @@ -103,6 +112,7 @@ void Renderer::Draw(RenderFrame& frame) m_LightCullingPass->FillLightList(*scene); m_LightCullingPass->CullLights(*scene); m_DrawFinalPass->Draw(*scene); + //m_DrawScenePass->Draw(*scene); GLERROR("Renderer::Draw m_DrawScenePass->Draw"); diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index b22f86ff..07b4fbc8 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -1,5 +1,6 @@ #include "Game.h" #include "Collision/CollidableOctreeSystem.h" +#include "Collision/EntityAABB.h" #include "Collision/TriggerSystem.h" #include "Collision/CollisionSystem.h" #include "Systems/RaptorCopterSystem.h" @@ -12,6 +13,8 @@ #include "Game/Systems/WeaponSystem.h" #include "Rendering/AnimationSystem.h" #include "Rendering/BoneAttachmentSystem.h" +#include "Game/Systems/PlayerHUD.h" +#include "Game/Systems/LifetimeSystem.h" Game::Game(int argc, char* argv[]) { @@ -41,7 +44,7 @@ Game::Game(int argc, char* argv[]) 0, m_Config->Get("Video.Width", 1280), m_Config->Get("Video.Height", 720) - )); + )); m_Renderer->Initialize(); //m_Renderer->Camera()->SetFOV(glm::radians(m_Config->Get("Video.FOV", 90.f))); m_RenderFrame = new RenderFrame(); @@ -71,31 +74,35 @@ Game::Game(int argc, char* argv[]) // Create Octrees - m_OctreeCollision = new Octree(AABB(glm::vec3(-100), glm::vec3(100)), 4); - m_OctreeFrustrumCulling = new Octree(AABB(glm::vec3(-100), glm::vec3(100)), 4); + m_OctreeCollision = new Octree(AABB(glm::vec3(-100), glm::vec3(100)), 4); + m_OctreeFrustrumCulling = new Octree(AABB(glm::vec3(-100), glm::vec3(100)), 4); // Create system pipeline m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker); // All systems with orderlevel 0 will be updated first. unsigned int updateOrderLevel = 0; m_SystemPipeline->AddSystem(updateOrderLevel); - //m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); // Populate Octree with collidables ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); + m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); + // Collision and TriggerSystem should update after player. ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); ++updateOrderLevel; - m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_RenderFrame); ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_RenderFrame); diff --git a/src/Game/Systems/CapturePointSystem.cpp b/src/Game/Systems/CapturePointSystem.cpp index fbd20e38..43876822 100644 --- a/src/Game/Systems/CapturePointSystem.cpp +++ b/src/Game/Systems/CapturePointSystem.cpp @@ -13,27 +13,27 @@ CapturePointSystem::CapturePointSystem(World* world, EventBroker* eventBroker) //here all capturepoints will update their component //NOTE: needs to run each frame, since we're possibly modifying the captureTimer for the capturePoints by dt -void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& capturePoint, double dt) +void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, ComponentWrapper& cCapturePoint, double dt) { if (m_WinnerWasFound) { return; } - const int capturePointNumber = capturePoint["CapturePointNumber"]; - const bool hasTeamComponent = m_World->HasComponent(capturePoint.EntityID, "Team"); + const int capturePointNumber = cCapturePoint["CapturePointNumber"]; + const bool hasTeamComponent = capturePointEntity.HasComponent("Team"); //if point doesnt have a teamComponent yet, add one. since: //what if capture point has no team -> we cant get/use the team enum from it... if (!hasTeamComponent) { - m_World->AttachComponent(capturePoint.EntityID, "Team"); - ComponentWrapper& teamComponent = m_World->GetComponent(capturePoint.EntityID, "Team"); + m_World->AttachComponent(cCapturePoint.EntityID, "Team"); + ComponentWrapper& teamComponent = capturePointEntity["Team"]; teamComponent["Team"] = (int)teamComponent["Team"].Enum("Spectator"); } - ComponentWrapper& teamComponent = m_World->GetComponent(capturePoint.EntityID, "Team"); + ComponentWrapper& teamComponent = capturePointEntity["Team"]; const int redTeam = (int)teamComponent["Team"].Enum("Red"); const int blueTeam = (int)teamComponent["Team"].Enum("Blue"); const int spectatorTeam = (int)teamComponent["Team"].Enum("Spectator"); - int homePointForTeam = (int)capturePoint["HomePointForTeam"]; + int homePointForTeam = (int)cCapturePoint["HomePointForTeam"]; if (m_NumberOfCapturePoints == 0 && capturePointNumber != 0 && (homePointForTeam == redTeam || homePointForTeam == blueTeam)) { m_NumberOfCapturePoints = capturePointNumber + 1;//ex 2 -> 0,1,2 = 3 if (homePointForTeam == redTeam) { @@ -46,8 +46,8 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper } //if we havent received all capturepoints yet, just return - if (m_NumberOfCapturePoints == 0 || m_NumberOfCapturePoints != m_CapturePointNumberToEntityIDMap.size()) { - m_CapturePointNumberToEntityIDMap.insert(std::make_pair(capturePointNumber, capturePoint.EntityID)); + if (m_NumberOfCapturePoints == 0 || m_NumberOfCapturePoints != m_CapturePointNumberToEntityMap.size()) { + m_CapturePointNumberToEntityMap.insert(std::make_pair(capturePointNumber, capturePointEntity)); return; } @@ -55,9 +55,9 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper int ownedBy = teamComponent["Team"]; int redTeamPlayersStandingInside = 0; int blueTeamPlayersStandingInside = 0; - if (entity.HasComponent("Model")) { + if (capturePointEntity.HasComponent("Model")) { //Now sets team color to the capturepoint, or white if it is uncaptured. - entity["Model"]["Color"] = ownedBy == blueTeam ? glm::vec4(0, 0.2f, 1, 1) : ownedBy == redTeam ? glm::vec4(1, 0.2f, 0, 1) : glm::vec4(1, 1, 1, 1); + capturePointEntity["Model"]["Color"] = ownedBy == blueTeam ? glm::vec4(0, 0.2f, 1, 1) : ownedBy == redTeam ? glm::vec4(1, 0.2f, 0, 1) : glm::vec4(1, 1, 1, 1); } //calculate next possible capturePoint for both teams @@ -66,10 +66,10 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper nextPossibleCapturePoint["Blue"] = -1; for (size_t i = 0; i < m_NumberOfCapturePoints; i++) { - if (!m_World->HasComponent(m_CapturePointNumberToEntityIDMap[i], "Team")) { + if (m_CapturePointNumberToEntityMap[i].HasComponent("Team")) { continue; } - ComponentWrapper& capturePointOwnedBy = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team"); + ComponentWrapper& capturePointOwnedBy = m_CapturePointNumberToEntityMap[i]["Team"]; if ((int)capturePointOwnedBy["Team"] == redTeam && m_RedTeamHomeCapturePoint == 0) { nextPossibleCapturePoint["Red"] = i + 1; } @@ -79,10 +79,10 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper } for (int i = m_NumberOfCapturePoints - 1; i >= 0; i--) { - if (!m_World->HasComponent(m_CapturePointNumberToEntityIDMap[i], "Team")) { + if (!m_CapturePointNumberToEntityMap[i].HasComponent("Team")) { continue; } - ComponentWrapper& capturePointOwnedBy = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team"); + ComponentWrapper& capturePointOwnedBy = m_CapturePointNumberToEntityMap[i]["Team"]; if ((int)capturePointOwnedBy["Team"] == redTeam && m_RedTeamHomeCapturePoint != 0) { nextPossibleCapturePoint["Red"] = i - 1; } @@ -95,7 +95,7 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper if (m_ResetTimers) { for (size_t i = 0; i < m_NumberOfCapturePoints; i++) { - ComponentWrapper& capturePoint = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "CapturePoint"); + ComponentWrapper& capturePoint = m_CapturePointNumberToEntityMap[i]["CapturePoint"]; if ((int)capturePoint["CapturePointNumber"] != nextPossibleCapturePoint["Red"] && (int)capturePoint["CapturePointNumber"] != nextPossibleCapturePoint["Blue"]) { capturePoint["CaptureTimer"] = 0.0; @@ -106,34 +106,34 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper //colorize next possible capturepoint if (nextPossibleCapturePoint["Red"] == capturePointNumber) { - entity["Model"]["Color"] = glm::vec4(1, 1, 0, 1); + capturePointEntity["Model"]["Color"] = glm::vec4(1, 1, 0, 1); } if (nextPossibleCapturePoint["Blue"] == capturePointNumber) { - entity["Model"]["Color"] = glm::vec4(0, 1, 1, 1); + capturePointEntity["Model"]["Color"] = glm::vec4(0, 1, 1, 1); } //check how many players are standing inside and are healthy for (size_t i = m_ETriggerTouchVector.size(); i > 0; i--) { auto triggerTouched = m_ETriggerTouchVector[i - 1]; - if (std::get<1>(triggerTouched) == capturePoint.EntityID) { + if (std::get<1>(triggerTouched) == capturePointEntity) { //some player has touched this - lets figure out: what team, health - EntityID playerID = std::get<0>(triggerTouched); - if (!m_World->HasComponent(playerID, "Player")) { + EntityWrapper player = std::get<0>(triggerTouched); + if (!player.HasComponent("Player")) { //if a non-player has entered the capturePoint, just erase that event and continue m_ETriggerTouchVector.erase(m_ETriggerTouchVector.begin() + i - 1); continue; } - bool hasHealthComponent = m_World->HasComponent(playerID, "Health"); + bool hasHealthComponent = player.HasComponent("Health"); if (hasHealthComponent) { - double currentHealth = m_World->GetComponent(playerID, "Health")["Health"]; + double currentHealth = player["Health"]["Health"]; //check if player is dead if ((int)currentHealth == 0) { continue; } } //check team - spectatorNumber = "no team" - int teamNumber = m_World->GetComponent(playerID, "Team")["Team"]; + int teamNumber = player["Team"]["Team"]; if (teamNumber == redTeam) { redTeamPlayersStandingInside++; } else if (teamNumber == blueTeam) { @@ -169,24 +169,24 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper //B. at most one of the teams have players inside //if capturePoint is not owned by the take-over team, just modify the CaptureTimer accordingly if (ownedBy != currentTeam && canCapture) { - if (abs((double)capturePoint["CaptureTimer"]) < 0.001f) { + if (abs((double)cCapturePoint["CaptureTimer"]) < 0.001f) { LOG_DEBUG("Point is being captured by team %i", currentTeam); //Remove when we tested sufficiently. } - capturePoint["CaptureTimer"] = (double)capturePoint["CaptureTimer"] + timerDeltaChange; + cCapturePoint["CaptureTimer"] = (double)cCapturePoint["CaptureTimer"] + timerDeltaChange; } //if capturePoint is owned by the team, and the other team has been trying to take it, then increase/decrease the timer towards 0.0 - if ((ownedBy == currentTeam && currentTeam == redTeam && (double)capturePoint["CaptureTimer"] < 0.0) || - (ownedBy == currentTeam && currentTeam == blueTeam && (double)capturePoint["CaptureTimer"] > 0.0)) { - capturePoint["CaptureTimer"] = (double)capturePoint["CaptureTimer"] + timerDeltaChange; + if ((ownedBy == currentTeam && currentTeam == redTeam && (double)cCapturePoint["CaptureTimer"] < 0.0) || + (ownedBy == currentTeam && currentTeam == blueTeam && (double)cCapturePoint["CaptureTimer"] > 0.0)) { + cCapturePoint["CaptureTimer"] = (double)cCapturePoint["CaptureTimer"] + timerDeltaChange; } //check if captureTimer > m_CaptureTimeToTakeOver and if so change owner and publish the eCaptured event - if (abs((double)capturePoint["CaptureTimer"]) > abs(m_CaptureTimeToTakeOver) && canCapture) { + if (abs((double)cCapturePoint["CaptureTimer"]) > abs(m_CaptureTimeToTakeOver) && canCapture) { teamComponent["Team"] = currentTeam; - capturePoint["CaptureTimer"] = 0.0; + cCapturePoint["CaptureTimer"] = 0.0; //publish Captured event LOG_DEBUG("Point is captured by team %i!", currentTeam); //Remove when we tested sufficiently. Events::Captured e; - e.CapturePointID = capturePoint.EntityID; + e.CapturePointID = cCapturePoint.EntityID; e.TeamNumberThatCapturedCapturePoint = currentTeam; m_EventBroker->Publish(e); //NextPossibleCapturePoint will be calculated in the next update... diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 7f0bbb09..9e118070 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -45,10 +45,16 @@ void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& comp } } -bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e) +bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) { - //save the changed HP to a vector. it will be taken care of in UpdateComponent - //m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerDamagedID, -e.DamageAmount)); + ComponentWrapper cHealth = e.Player["Health"]; + double& health = cHealth["Health"]; + health -= e.Damage; + + if (health <= 0.0) { + m_World->DeleteEntity(e.Player.ID); + } + return true; } diff --git a/src/Game/Systems/LifetimeSystem.cpp b/src/Game/Systems/LifetimeSystem.cpp new file mode 100644 index 00000000..db19e88a --- /dev/null +++ b/src/Game/Systems/LifetimeSystem.cpp @@ -0,0 +1,27 @@ +#include "Systems/LifetimeSystem.h" + +void LifetimeSystem::Update(double dt) +{ + for (auto& e : m_Deletions) { + m_World->DeleteEntity(e.ID); + } + m_Deletions.clear(); +} + +void LifetimeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cLifetime, double dt) +{ + if (dt == 0.0) { + return; + } + + if (!entity.Valid()) { + return; + } + + double& lifetime = cLifetime["Lifetime"]; + lifetime -= dt; + + if (lifetime <= 0.0) { + m_Deletions.push_back(entity); + } +} \ No newline at end of file diff --git a/src/Game/Systems/PlayerHUD.cpp b/src/Game/Systems/PlayerHUD.cpp new file mode 100644 index 00000000..55d0c3f1 --- /dev/null +++ b/src/Game/Systems/PlayerHUD.cpp @@ -0,0 +1,57 @@ +#include "Game/Systems/PlayerHUD.h" + +PlayerHUD::PlayerHUD(World* world, EventBroker* eventBrokerer) + :System(world, eventBrokerer) + , m_World(world) + , m_EventBroker(eventBrokerer) +{ + + +} + +PlayerHUD::~PlayerHUD() +{ + + +} + +void PlayerHUD::Update(double dt) +{ + auto healthHUDs = m_World->GetComponents("HealthHUD"); + if (healthHUDs == nullptr) { + return; + } + + for (auto& healthHUDComponent : *healthHUDs) { + EntityWrapper entity = EntityWrapper(m_World, healthHUDComponent.EntityID); + + EntityWrapper entityIDParent = entity; + while (entityIDParent.Parent().Valid()) { + entityIDParent = entityIDParent.Parent(); + + if (entityIDParent.HasComponent("Health")) { + break; + } + } + + if (entityIDParent.HasComponent("Health")) { + + if (entity.HasComponent("Text")) { + std::string s = ""; + s = s + std::to_string((int)(double)entityIDParent["Health"]["Health"]); + s = s + "/"; + s = s + std::to_string((int)(double)entityIDParent["Health"]["MaxHealth"]); + float healthPercentage = (double)entityIDParent["Health"]["Health"]/(double)entityIDParent["Health"]["MaxHealth"]; + (glm::vec4&)entity["Text"]["Color"] = glm::vec4(1.0 - healthPercentage, 0.f, healthPercentage, 1.f); + entity["Text"]["Content"] = s; + } + + if(entity.HasComponent("Fill")) { + float healthPercentage = (double)entityIDParent["Health"]["Health"]/(double)entityIDParent["Health"]["MaxHealth"]; + (glm::vec4&)entity["Fill"]["Color"] = glm::vec4(1.0 - healthPercentage, 0.f, healthPercentage, 0.f); + (double&)entity["Fill"]["Percentage"] = healthPercentage; + + } + } + } +} diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index 5c75a673..6eab02c5 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -36,15 +36,18 @@ void PlayerMovementSystem::Update(double dt) glm::vec3& ori = cTransform["Orientation"]; ori.y += controller->Rotation().y; + float playerMovementSpeed = player["Player"]["MovementSpeed"]; + float playerCrouchSpeed = player["Player"]["CrouchSpeed"]; + if (player.HasComponent("Physics")) { ComponentWrapper cPhysics = player["Physics"]; glm::vec3 wishDirection = controller->Movement() * glm::inverse(glm::quat(ori)); float wishSpeed; if (controller->Crouching()) { - wishSpeed = player["Player"]["CrouchSpeed"]; + wishSpeed = playerCrouchSpeed; } else { - wishSpeed = player["Player"]["MovementSpeed"]; + wishSpeed = playerMovementSpeed; } glm::vec3& velocity = cPhysics["Velocity"]; ImGui::Text("velocity: (%f, %f, %f)", velocity.x, velocity.y, velocity.z); @@ -77,16 +80,41 @@ void PlayerMovementSystem::Update(double dt) velocity.y += 4.f; } - //if (player.HasComponent("AABB")) { - // glm::vec3& size = player["AABB"]["Size"]; - // if (controller->Crouching()) { - // size = glm::vec3(1.f, 1.f, 1.f); - // } else { - // size = glm::vec3(1.f, 1.6f, 1.f); - // } - //} + if (player.HasComponent("AABB")) { + glm::vec3& size = player["AABB"]["Size"]; + if (controller->Crouching()) { + size = glm::vec3(1.f, 1.f, 1.f); + } else { + size = glm::vec3(1.f, 1.6f, 1.f); + } + } + + // Animations + EntityWrapper playerModel = player.FirstChildByName("PlayerModel"); + if (playerModel.Valid()) { + ComponentWrapper cAnimation = playerModel["Animation"]; + + float movementLength = glm::length(groundVelocity); + if (glm::length(controller->Movement()) > 0.f) { + if (controller->Crouching()) { + cAnimation["Name"] = "Crouch Walk"; + (double&)cAnimation["Speed"] = 1.f * -glm::sign(controller->Movement().z); + } else { + cAnimation["Name"] = "Run"; + (double&)cAnimation["Speed"] = 2.f * -glm::sign(controller->Movement().z); + } + } else { + if (controller->Crouching()) { + cAnimation["Name"] = "Crouch"; + (double&)cAnimation["Speed"] = 1.f; + } else { + cAnimation["Name"] = "Hold Pos"; + (double&)cAnimation["Speed"] = 1.f; + } + } + } } - + controller->Reset(); } } diff --git a/src/Game/Systems/PlayerSpawnSystem.cpp b/src/Game/Systems/PlayerSpawnSystem.cpp index 84dce05c..7db6e8ff 100644 --- a/src/Game/Systems/PlayerSpawnSystem.cpp +++ b/src/Game/Systems/PlayerSpawnSystem.cpp @@ -102,10 +102,10 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e) } // TODO: Set the player name to whatever - //EntityWrapper playerName = e.Player.FirstChildByName("PlayerName"); - //if (playerName.Valid()) { - // playerName["Text"]["Content"] = ???; - //} + EntityWrapper playerName = e.Player.FirstChildByName("PlayerName"); + if (playerName.Valid()) { + playerName["Text"]["Content"] = e.PlayerName; + } return true; } \ No newline at end of file diff --git a/src/Game/Systems/SpawnerSystem.cpp b/src/Game/Systems/SpawnerSystem.cpp index 8cb5b99d..f9357113 100644 --- a/src/Game/Systems/SpawnerSystem.cpp +++ b/src/Game/Systems/SpawnerSystem.cpp @@ -50,7 +50,8 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent / // Set its position and orientation to that of the SpawnPoint spawnedEntity["Transform"]["Position"] = Transform::AbsolutePosition(spawnPoint.World, spawnPoint.ID); - spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint.World, spawnPoint.ID)); + // TODO: Quaternions, bitch + //spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint.World, spawnPoint.ID)); return spawnedEntity; } diff --git a/src/Game/Systems/WeaponSystem.cpp b/src/Game/Systems/WeaponSystem.cpp index 02d70289..4b4b8da2 100644 --- a/src/Game/Systems/WeaponSystem.cpp +++ b/src/Game/Systems/WeaponSystem.cpp @@ -37,16 +37,73 @@ bool WeaponSystem::OnInputCommand(const Events::InputCommand& e) if (e.Command == "PrimaryFire" && e.Value > 0) { Events::Shoot eShoot; - eShoot.Player = m_LocalPlayer; + if (e.PlayerID == -1) { + eShoot.Player = m_LocalPlayer; + } else { + eShoot.Player = e.Player; + } m_EventBroker->Publish(eShoot); } return true; } -bool WeaponSystem::OnShoot(const Events::Shoot& eShoot) { +bool WeaponSystem::OnShoot(Events::Shoot& eShoot) +{ + if (!eShoot.Player.Valid()) { + return false; + } + + // TODO: Weapon firing effects here + + auto rayRed = ResourceManager::Load("Schema/Entities/RayRed.xml"); + auto rayBlue = ResourceManager::Load("Schema/Entities/RayBlue.xml"); + + EntityWrapper weapon = eShoot.Player.FirstChildByName("WeaponMuzzle"); + if (weapon.Valid()) { + EntityWrapper ray; + if ((ComponentInfo::EnumType)eShoot.Player["Team"]["Team"] == eShoot.Player["Team"]["Team"].Enum("Red")) { + EntityFileParser parser(rayRed); + EntityID rayID = parser.MergeEntities(m_World); + ray = EntityWrapper(m_World, rayID); + } else { + EntityFileParser parser(rayBlue); + EntityID rayID = parser.MergeEntities(m_World); + ray = EntityWrapper(m_World, rayID); + } + + glm::mat4 transformation = Transform::AbsoluteTransformation(weapon); + glm::vec3 scale; + glm::vec3 translation; + glm::quat orientation; + glm::vec3 skew; + glm::vec4 perspective; + glm::decompose(transformation, scale, orientation, translation, skew, perspective); + + // Matrix to euler angles + glm::vec3 euler; + euler.y = glm::asin(-transformation[0][2]); + if (cos(euler.y) != 0) { + euler.x = atan2(transformation[1][2], transformation[2][2]); + euler.z = atan2(transformation[0][1], transformation[0][0]); + } else { + euler.x = atan2(-transformation[2][0], transformation[1][1]); + euler.z = 0; + } + + //LOG_DEBUG("rotation: %f %f %f", euler.x, euler.y, euler.z); + (glm::vec3&)ray["Transform"]["Position"] = translation; + (glm::vec3&)ray["Transform"]["Orientation"] = euler; + //(glm::vec3&)ray["Transform"]["Orientation"] = Transform::AbsoluteOrientationEuler(weapon); + } + + // Only run further picking code client-side! + if (eShoot.Player != m_LocalPlayer) { + return false; + } + // Screen center, based on current resolution! - //TODO: check if player has enough ammo and if weapon has a cooldown or not + // TODO: check if player has enough ammo and if weapon has a cooldown or not Rectangle screenResolution = m_Renderer->GetViewPortSize(); glm::vec2 centerScreen = glm::vec2(screenResolution.Width / 2, screenResolution.Height / 2);