diff --git a/CMakeLists.txt b/CMakeLists.txt index cbe8168a..b97bf8df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,9 @@ 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") + add_definitions(-D_CRT_SECURE_NO_WARNINGS) endif() #set(BUILD_SHARED_LIBS FALSE) @@ -34,6 +37,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 068fbb2d..091ad5c0 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 068fbb2d20682dd60f186c82172d7731e60ed7e9 +Subproject commit 091ad5c01bf7b6ef5501fc907fc610576a4a45ea diff --git a/include/Engine/Collision/CollidableOctreeSystem.h b/include/Engine/Collision/CollidableOctreeSystem.h index 0dcf5829..0aa01d2e 100644 --- a/include/Engine/Collision/CollidableOctreeSystem.h +++ b/include/Engine/Collision/CollidableOctreeSystem.h @@ -4,13 +4,14 @@ #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, const std::string& componentType) : System(world, eventBroker) - , PureSystem("Collidable") + , PureSystem(componentType) , 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/ComponentWrapper.h b/include/Engine/Core/ComponentWrapper.h index f09bbfe3..1dc131d2 100644 --- a/include/Engine/Core/ComponentWrapper.h +++ b/include/Engine/Core/ComponentWrapper.h @@ -81,7 +81,7 @@ class ComponentWrapperFactory { public: ComponentWrapperFactory() = default; - ComponentWrapperFactory(std::string componentTypeName, std::size_t allocation = 0) + ComponentWrapperFactory(std::string componentTypeName, unsigned int allocation = 0) { m_ComponentInfo.Name = componentTypeName; m_ComponentInfo.Meta->Allocation = allocation; diff --git a/include/Engine/Core/EntityFile.h b/include/Engine/Core/EntityFile.h index 2549ed06..538e9047 100644 --- a/include/Engine/Core/EntityFile.h +++ b/include/Engine/Core/EntityFile.h @@ -143,7 +143,7 @@ private: ~EntityFile(); public: - static std::size_t GetTypeStride(std::string typeName); + static unsigned int GetTypeStride(std::string typeName); static void WriteAttributeData(char* outData, const ComponentInfo::Field_t& field, const std::map& attributes); static void WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData); 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/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/FileWatcher.h b/include/Engine/Core/Util/FileWatcher.h index 01b4157d..e7f207eb 100644 --- a/include/Engine/Core/Util/FileWatcher.h +++ b/include/Engine/Core/Util/FileWatcher.h @@ -42,7 +42,7 @@ enum class FileWatcher::FileEventFlags }; inline FileWatcher::FileEventFlags operator|(FileWatcher::FileEventFlags a, FileWatcher::FileEventFlags b) { return static_cast(static_cast(a) | static_cast(b)); } -inline bool operator&(FileWatcher::FileEventFlags a, FileWatcher::FileEventFlags b) { return static_cast(a)& static_cast(b); } +inline bool operator&(FileWatcher::FileEventFlags a, FileWatcher::FileEventFlags b) { return (static_cast(a) & static_cast(b)) != 0; } class FileWatcher::Worker { @@ -54,7 +54,7 @@ public: private: struct FileInfo { - int Size; + std::size_t Size; std::time_t Timestamp; }; 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/EditorCameraInputController.h b/include/Engine/Editor/EditorCameraInputController.h index 66c7952a..4c139e01 100644 --- a/include/Engine/Editor/EditorCameraInputController.h +++ b/include/Engine/Editor/EditorCameraInputController.h @@ -23,7 +23,7 @@ public: m_SpeedMultiplier = m_Config->Get("Editor.CameraSpeed", 3.f); } - virtual const glm::vec3 Movement() const override { return m_Movement * m_SpeedMultiplier; } + virtual const glm::vec3 Movement() const override { return m_Movement * static_cast(m_SpeedMultiplier); } void Enable() { m_Enabled = true; } void Disable() { m_Enabled = false; } @@ -69,7 +69,7 @@ public: protected: ConfigFile* m_Config; bool m_Enabled = false; - float m_SpeedMultiplier = 1.f; + double m_SpeedMultiplier = 1.f; EventRelay m_EMousePress; bool OnMousePress(const Events::MousePress& e) @@ -105,7 +105,7 @@ protected: return false; } - m_SpeedMultiplier += e.DeltaY * (0.1f * m_SpeedMultiplier); + m_SpeedMultiplier += e.DeltaY * (0.1 * m_SpeedMultiplier); m_Config->Set("Editor.CameraSpeed", m_SpeedMultiplier); m_Config->SaveToDisk(); return true; diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index 973f6a90..7a0289c6 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 @@ -18,6 +19,8 @@ #include "../Core/ResourceManager.h" #include "../Core/EPause.h" #include "../Core/EKeyDown.h" +#include "../Core/ELockMouse.h" +#include "../Core/EFileDropped.h" #include "../Rendering/Texture.h" class EditorGUI @@ -32,6 +35,12 @@ public: Scale }; + enum class WidgetSpace + { + Global, + Local + }; + void Draw(); void SelectEntity(EntityWrapper entity); @@ -73,6 +82,9 @@ public: // Called when the user selects a widget mode. typedef std::function OnWidgetMode_t; void SetWidgetModeCallback(OnWidgetMode_t f) { m_OnWidgetMode = f; } + // Called when the user selects a widget space. + typedef std::function OnWidgetSpace_t; + void SetWidgetSpaceCallback(OnWidgetSpace_t f) { m_OnWidgetSpace = f; } private: World* m_World; @@ -93,8 +105,12 @@ private: EntityWrapper m_CurrentlyDragging = EntityWrapper::Invalid; std::string m_LastErrorMessage; WidgetMode m_CurrentWidgetMode = WidgetMode::Translate; + WidgetSpace m_CurrentWidgetSpace = WidgetSpace::Global; std::set m_ModalsToOpen; std::map m_ModalData; + std::string m_DroppedFile = ""; + bool m_Paused = false; + bool m_MouseLocked = false; // Callbacks OnEntitySelectedCallback_t m_OnEntitySelected = nullptr; @@ -107,10 +123,21 @@ private: OnComponentAttach_t m_OnComponentAttach = nullptr; OnComponentDelete_t m_OnComponentDelete = nullptr; OnWidgetMode_t m_OnWidgetMode = nullptr; + OnWidgetSpace_t m_OnWidgetSpace = nullptr; // Events EventRelay m_EKeyDown; bool OnKeyDown(const Events::KeyDown& e); + EventRelay m_EFileDropped; + bool OnFileDropped(const Events::FileDropped& e); + EventRelay m_EPause; + bool OnPause(const Events::Pause& e); + EventRelay m_EResume; + bool OnResume(const Events::Resume& e); + EventRelay m_ELockMouse; + bool OnLockMouse(const Events::LockMouse& e); + EventRelay m_EUnlockMouse; + bool OnUnlockMouse(const Events::UnlockMouse& e); // Utility functions boost::filesystem::path fileOpenDialog(); @@ -118,6 +145,9 @@ private: const std::string formatEntityName(EntityWrapper entity); GLuint tryLoadTexture(std::string filePath); void openModal(const std::string& modal); + void setWidgetMode(WidgetMode mode); + void toggleWidgetSpace(); + static bool compareCharArray(const char* c1, const char* c2); // Entity file handling methods void entityImport(World* world); diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 2db24ba3..accf66e4 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -41,6 +41,7 @@ private: double m_LastTime = 0.f; bool m_Enabled = true; EditorGUI::WidgetMode m_WidgetMode = EditorGUI::WidgetMode::Translate; + EditorGUI::WidgetSpace m_WidgetSpace = EditorGUI::WidgetSpace::Global; EntityWrapper m_Widget = EntityWrapper::Invalid; EntityWrapper m_CurrentSelection = EntityWrapper::Invalid; @@ -57,6 +58,7 @@ private: void OnEntityChangeName(EntityWrapper entity, const std::string& name); void OnComponentAttach(EntityWrapper entity, const std::string& componentType); void OnComponentDelete(EntityWrapper entity, const std::string& componentType); + void OnWidgetSpace(EditorGUI::WidgetSpace widgetSpace); // Events EventRelay m_EMousePress; 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/Input/FirstPersonInputController.h b/include/Engine/Input/FirstPersonInputController.h index 426670c4..d4c9071c 100644 --- a/include/Engine/Input/FirstPersonInputController.h +++ b/include/Engine/Input/FirstPersonInputController.h @@ -15,7 +15,11 @@ public: virtual const glm::vec3 Rotation() const { return m_Rotation; } virtual bool Jumping() const { return m_Jumping; } virtual bool Crouching() const { return m_Crouching; } - + virtual bool DoubleJumping() const { return m_DoubleJumping; } + virtual void SetDoubleJumping(bool isDoubleJumping) { + m_DoubleJumping = isDoubleJumping; + } + void LockMouse(); void UnlockMouse(); virtual bool OnCommand(const Events::InputCommand& e) override; @@ -27,8 +31,9 @@ protected: glm::vec3 m_Rotation; glm::vec3 m_Movement; bool m_Jumping = false; + bool m_DoubleJumping = false; bool m_Crouching = false; - + EventRelay m_ELockMouse; bool OnLockMouse(const Events::LockMouse& e); EventRelay m_EUnlockMouse; @@ -36,7 +41,7 @@ protected: }; template -FirstPersonInputController::FirstPersonInputController(EventBroker* eventBroker, int playerID) +FirstPersonInputController::FirstPersonInputController(EventBroker* eventBroker, int playerID) : InputController(eventBroker) , m_PlayerID(playerID) { @@ -113,14 +118,14 @@ bool FirstPersonInputController::OnCommand(const Events::InputComm template bool FirstPersonInputController::OnUnlockMouse(const Events::UnlockMouse& e) { - m_MouseLocked = false; + m_MouseLocked = false; return true; } template bool FirstPersonInputController::OnLockMouse(const Events::LockMouse& e) { - m_MouseLocked = true; + m_MouseLocked = true; return true; } 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/AnimationSystem.h b/include/Engine/Rendering/AnimationSystem.h new file mode 100644 index 00000000..fcdcbc92 --- /dev/null +++ b/include/Engine/Rendering/AnimationSystem.h @@ -0,0 +1,29 @@ +#ifndef AnimationSystem_h__ +#define AnimationSystem_h__ + +#include "GLM.h" + +#include "Common.h" +#include "Core/System.h" +#include "Core/ResourceManager.h" +#include "Rendering/Model.h" +#include "Rendering/EAnimationComplete.h" +#include "Rendering/Skeleton.h" + +class AnimationSystem : public PureSystem +{ +public: + AnimationSystem(World* world, EventBroker* eventBroker) + : System(world, eventBroker) + , PureSystem("Animation") + { + + } + ~AnimationSystem() { } + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt) override; +private: + + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/DrawFinalPass.h b/include/Engine/Rendering/DrawFinalPass.h index 4cf88842..74f505fe 100644 --- a/include/Engine/Rendering/DrawFinalPass.h +++ b/include/Engine/Rendering/DrawFinalPass.h @@ -30,9 +30,18 @@ public: private: void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; void GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm::vec2 dimensions, GLint format, GLenum type, GLint numMipMaps) const; + void DrawModelRenderQueues(std::list>& job, RenderScene& scene); + + void BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene); + void BindModelUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene); + + void BindExplosionTextures(std::shared_ptr& job); + void BindModelTextures(std::shared_ptr& job); Texture* m_WhiteTexture; Texture* m_BlackTexture; + Texture* m_NeutralNormalTexture; + Texture* m_GreyTexture; FrameBuffer m_FinalPassFrameBuffer; GLuint m_BloomTexture; @@ -43,6 +52,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/EAnimationComplete.h b/include/Engine/Rendering/EAnimationComplete.h new file mode 100644 index 00000000..00519a38 --- /dev/null +++ b/include/Engine/Rendering/EAnimationComplete.h @@ -0,0 +1,18 @@ +#ifndef Events_AnimationComplete_h__ +#define Events_AnimationComplete_h__ + +#include "../Core/EventBroker.h" +#include "../Core/EntityWrapper.h" + +namespace Events +{ + +struct AnimationComplete : Event +{ + EntityWrapper Entity; + std::string Name; +}; + +} + +#endif 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/IRenderer.h b/include/Engine/Rendering/IRenderer.h index 6ef189f4..b399aefa 100644 --- a/include/Engine/Rendering/IRenderer.h +++ b/include/Engine/Rendering/IRenderer.h @@ -25,21 +25,23 @@ class IRenderer { public: GLFWwindow* Window() const { return m_Window; } + //Returns screen size including window border and header Rectangle Resolution() const { return m_Resolution; } - void SetResolution(const Rectangle& resolution) { m_Resolution = resolution; } + virtual void SetResolution(const Rectangle& resolution) { m_Resolution = resolution; } bool Fullscreen() { return m_Fullscreen; } - void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; } + virtual void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; } bool VSYNC() const { return m_VSYNC; } - void SetVSYNC(bool vsync) { m_VSYNC = vsync; } + virtual void SetVSYNC(bool vsync) { m_VSYNC = vsync; } + //Returns screen size excluding window border and header + Rectangle GetViewportSize() const { return m_ViewportSize; } virtual void Initialize() = 0; virtual void Update(double dt) = 0; virtual void Draw(RenderFrame& rq) = 0; virtual PickData Pick(glm::vec2 screenCord) = 0; - World* m_World; //Temp world, untill viktor merge. - protected: Rectangle m_Resolution = Rectangle::Rectangle(1280, 720); + Rectangle m_ViewportSize = Rectangle::Rectangle(1280, 720); bool m_Fullscreen = false; bool m_VSYNC = false; int m_GLVersion[2]; diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index 01f4cca4..2cb2169c 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -13,18 +13,35 @@ #include "Camera.h" #include "../Core/World.h" #include "../Core/Transform.h" +#include "Skeleton.h" 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; TextureID = (matGroup.Texture) ? matGroup.Texture->ResourceID : 0; - DiffuseTexture = matGroup.Texture.get(); - NormalTexture = matGroup.NormalMap.get(); - SpecularTexture = matGroup.SpecularMap.get(); - IncandescenceTexture = matGroup.IncandescenceMap.get(); + if (modelComponent["DiffuseTexture"]) { + DiffuseTexture = matGroup.Texture.get(); + } else { + DiffuseTexture = nullptr; + } + if (modelComponent["NormalMap"]) { + NormalTexture = matGroup.NormalMap.get(); + } else { + NormalTexture = nullptr; + } + if (modelComponent["SpecularMap"]) { + SpecularTexture = matGroup.SpecularMap.get(); + } else { + SpecularTexture = nullptr; + } + if (modelComponent["GlowMap"]) { + IncandescenceTexture = matGroup.IncandescenceMap.get(); + } else { + IncandescenceTexture = nullptr; + } DiffuseColor = matGroup.DiffuseColor; SpecularColor = matGroup.SpecularColor; IncandescenceColor = matGroup.IncandescenceColor; @@ -37,6 +54,16 @@ struct ModelJob : RenderJob glm::vec3 worldpos = glm::vec3(camera->ViewMatrix() * glm::vec4(abspos, 1)); Depth = worldpos.z; World = world; + + FillColor = fillColor; + FillPercentage = fillPercentage; + Skeleton = Model->m_RawModel->m_Skeleton; + + if (world->HasComponent(Entity, "Animation") && Skeleton != nullptr) { + auto animationComponent = world->GetComponent(Entity, "Animation"); + Animation = model->m_RawModel->m_Skeleton->GetAnimation(animationComponent["Name"]); + AnimationTime = (double)animationComponent["Time"]; + } }; unsigned int TextureID; @@ -51,6 +78,11 @@ struct ModelJob : RenderJob float Shininess = 0.f; glm::vec4 Color; const ::Model* Model = nullptr; + ::Skeleton* Skeleton = nullptr; + const ::Skeleton::Animation* Animation = nullptr; + + float AnimationTime = 0.f; + glm::vec4 DiffuseColor; glm::vec4 SpecularColor; glm::vec4 IncandescenceColor; @@ -58,6 +90,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/PickingPass.h b/include/Engine/Rendering/PickingPass.h index 5fc88982..da3ed31b 100644 --- a/include/Engine/Rendering/PickingPass.h +++ b/include/Engine/Rendering/PickingPass.h @@ -1,8 +1,6 @@ #ifndef PickingPass_h__ #define PickingPass_h__ - - #include "IRenderer.h" #include "PickingPassState.h" #include "FrameBuffer.h" @@ -10,8 +8,7 @@ #include "Util/UnorderedMapiVec2.h" #include "../Core/EventBroker.h" #include "../Core/World.h" - - +#include "Rendering/Skeleton.h" class PickingPass { diff --git a/include/Engine/Rendering/RawModelCustom.h b/include/Engine/Rendering/RawModelCustom.h index f1bc0e24..e903f49f 100644 --- a/include/Engine/Rendering/RawModelCustom.h +++ b/include/Engine/Rendering/RawModelCustom.h @@ -75,21 +75,21 @@ private: void ReadMeshFile(std::string filePath); - void ReadMeshFileHeader(unsigned int& offset, char* fileData, unsigned int& fileByteSize); - void ReadMesh(unsigned int& offset, char* fileData, unsigned int& fileByteSize); - void ReadVertices(unsigned int& offset, char* fileData, unsigned int& fileByteSize); - void ReadIndices(unsigned int& offset, char* fileData, unsigned int& fileByteSize); + void ReadMeshFileHeader(std::size_t& offset, char* fileData); + void ReadMesh(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + void ReadVertices(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + void ReadIndices(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); void ReadMaterialFile(std::string filePath); - void ReadMaterials(unsigned int &offset, char* fileData, unsigned int& fileByteSize); - void ReadMaterialSingle(unsigned int &offset, char* fileData, unsigned int& fileByteSize); + void ReadMaterials(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + void ReadMaterialSingle(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); void ReadAnimationFile(std::string filePath); - void ReadAnimationBindPoses(unsigned int &offset, char* fileData, unsigned int& fileByteSize); - void ReadAnimationJoint(unsigned int &offset, char* fileData, unsigned int& fileByteSize); - void ReadAnimationClips(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int numberOfClips); - void ReadAnimationClipSingle(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int clipIndex); - void ReadAnimationKeyFrame(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int numberOfJoints, Skeleton::Animation& animation); + void ReadAnimationBindPoses(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + void ReadAnimationJoint(std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + void ReadAnimationClips(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int numberOfClips); + void ReadAnimationClipSingle(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int clipIndex); + void ReadAnimationKeyFrame(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int numberOfJoints, Skeleton::Animation& animation); //void CreateSkeleton(std::vector> &boneInfo, std::map &boneNameMapping, aiNode* node, int parentID); }; diff --git a/include/Engine/Rendering/RenderQueue.h b/include/Engine/Rendering/RenderQueue.h index b533f992..57371146 100644 --- a/include/Engine/Rendering/RenderQueue.h +++ b/include/Engine/Rendering/RenderQueue.h @@ -14,11 +14,13 @@ #include "TextJob.h" #include "PointLightJob.h" #include "DirectionalLightJob.h" +#include "ExplosionEffectJob.h" struct RenderScene { ::Camera* Camera = nullptr; - std::list> ForwardJobs; + std::list> OpaqueObjects; + std::list> TransparentObjects; std::list> PointLightJobs; std::list> TextJobs; std::list> DirectionalLightJobs; @@ -27,7 +29,8 @@ struct RenderScene void Clear() { - ForwardJobs.clear(); + OpaqueObjects.clear(); + TransparentObjects.clear(); PointLightJobs.clear(); TextJobs.clear(); DirectionalLightJobs.clear(); diff --git a/include/Engine/Rendering/RenderSystem.h b/include/Engine/Rendering/RenderSystem.h index 005d2eb7..d64147b9 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 fillModels(std::list>& opaqueJobs, std::list>& transparentJobs); 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 ccca080e..85d0190c 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,9 @@ private: InputProxy* m_InputProxy; GUI::Frame* m_FrameStack; World* m_World; - Octree* m_OctreeCollision; - Octree* m_OctreeFrustrumCulling; + Octree* m_OctreeCollision; + Octree* m_OctreeTrigger; + 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/DefaultInput.ini b/resources/DefaultInput.ini index d07ed6a3..a3f7d166 100644 --- a/resources/DefaultInput.ini +++ b/resources/DefaultInput.ini @@ -15,10 +15,6 @@ Space=Jump LeftControl=Crouch LeftShift=Sprint F1=ToggleEditor -1=EditorToolMove -2=EditorToolRotate -3=EditorToolScale -X=EditorToggleTransformSpace C=ConnectToServer N=SwitchToServer M=SwitchToClient diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index 12d94611..ab46b0ea 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -12,6 +12,7 @@ + @@ -23,4 +24,9 @@ + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/Animation.xml b/resources/Schema/Components/Animation.xml new file mode 100644 index 00000000..66d2865d --- /dev/null +++ b/resources/Schema/Components/Animation.xml @@ -0,0 +1,7 @@ + + + + + 0 + true + \ No newline at end of file diff --git a/resources/Schema/Components/Animation.xsd b/resources/Schema/Components/Animation.xsd new file mode 100644 index 00000000..0dd21f29 --- /dev/null +++ b/resources/Schema/Components/Animation.xsd @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/CapturePoint.xsd b/resources/Schema/Components/CapturePoint.xsd index 9e96fca6..fbdb3568 100644 --- a/resources/Schema/Components/CapturePoint.xsd +++ b/resources/Schema/Components/CapturePoint.xsd @@ -2,22 +2,11 @@ - - - - - - - - - - - - + - A Capture Point. Add a Team Component to specify who currently owns it + A Capture Point. Make sure to update the HomePoint,CapturePointNumber,Team for each 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.xml b/resources/Schema/Components/Model.xml index 8f78b9ee..4b77dacb 100644 --- a/resources/Schema/Components/Model.xml +++ b/resources/Schema/Components/Model.xml @@ -2,5 +2,10 @@ + false true + true + true + true + true \ No newline at end of file diff --git a/resources/Schema/Components/Model.xsd b/resources/Schema/Components/Model.xsd index fb0774f8..9c0cd519 100644 --- a/resources/Schema/Components/Model.xsd +++ b/resources/Schema/Components/Model.xsd @@ -15,8 +15,23 @@ Color tint + + Wether the model is transparent or not + - Wether the model is visible or not + Whether the model is visible or not + + + Whether the model should use the Diffuse texture or not + + + Whether the model should use the Normalmap or not + + + Whether the model should use the Specularmap or not + + + Whether the model should use the Glowmap 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/CapturePoint.xml b/resources/Schema/Entities/CapturePoint.xml new file mode 100644 index 00000000..9b3c5036 --- /dev/null +++ b/resources/Schema/Entities/CapturePoint.xml @@ -0,0 +1,17 @@ + + + + + + + + C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + + + + + + + + + diff --git a/resources/Schema/Entities/CaptureTestState5.xml b/resources/Schema/Entities/CaptureTestState5.xml new file mode 100644 index 00000000..f1b07a7b --- /dev/null +++ b/resources/Schema/Entities/CaptureTestState5.xml @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + + + + + + + + + + + + + + + + + + + 1 + + + C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + + + + + + + + + + + + + + + 2 + + + C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + + + + + + + + + + + + + + + + + + + 3 + + + C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + + + + + + + + + + + + + + + + + + + + + + 4 + + + C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + + + + + + + + + + + + + + + + + + + + C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitCube.mesh + + + + + + + + + + + + + + + + + + + C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitCube.mesh + + + + + + + + + + + + + + + + + C:\Users\123456\Workspace\TacticalZ\assets\Models\DummyScene.mesh + + + + + + + + + + diff --git a/resources/Schema/Entities/EditorTestWorld.xml b/resources/Schema/Entities/EditorTestWorld.xml index 5649a630..9565e2d4 100755 --- a/resources/Schema/Entities/EditorTestWorld.xml +++ b/resources/Schema/Entities/EditorTestWorld.xml @@ -6,7 +6,7 @@ - + Models/Core/UnitCube.mesh @@ -18,69 +18,51 @@ - - - - An error - - - - - - - - - - - An error - - - - - - - - - - - + - + - + + 0.80000001192092896 + Models/DirectionalLightWidget.mesh + + 1.0499999523162842 + + - + - + Models/Assault.mesh - + + - + - Models/SecondaryWeapon.fbx + Models/SecondaryWeapon.mesh @@ -91,17 +73,219 @@ - + + + + + + + + + + + + Run + + 1 + + + models/AssaultAnimated.mesh + + + + + + + + + + + Walk + + 1 + + + models/AssaultAnimated.mesh + + + + + + + + Models/Core/UnitSphere.mesh + + true + + + + + + + + + + + + + - Models/Core/UnitSphere.mesh + Models/Log.mesh - + + + + + + + + + + + + + Models/NormalMapSphere.mesh + + + + + + + + + + + Models/SpecularMapSphere.mesh + + + + + + + + + + 1 + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 3 + 1.1399998664855957 + + + + + + + + + + + + + + + + Models/IncandescenceMapSphere.mesh + + + + + + + + + + + models/NormSpecIncdMapSphere.mesh + + + + + + + + + 1 + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 3 + 1.1399998664855957 + + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 5.0100002288818359 + 0.69999998807907104 + + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 4 + 0.80000001192092896 + + + + + + + + + + + + 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/FastWorld.xml b/resources/Schema/Entities/FastWorld.xml new file mode 100644 index 00000000..1289d9d1 --- /dev/null +++ b/resources/Schema/Entities/FastWorld.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + + + + + + + + + + + Run + + 1 + + + + + 0.95625903442123672 + + + + Models/AssaultAnimated.mesh + + + + + + + + + + + pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew + Fonts/DroidSans.ttf,60 + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/PointLightWithModel.xml b/resources/Schema/Entities/PointLightWithModel.xml new file mode 100644 index 00000000..17ca950c --- /dev/null +++ b/resources/Schema/Entities/PointLightWithModel.xml @@ -0,0 +1,20 @@ + + + + + + Models/Core/UnitSphere.mesh + + + + 3 + 1.1399998664855957 + + + + + + + + + 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 796a66f0..20301d5f 100644 --- a/resources/Schema/Entities/RenderingWorld.xml +++ b/resources/Schema/Entities/RenderingWorld.xml @@ -6,34 +6,115 @@ - + - - ActionCamera - - - Models/Camera.mesh - + + 65.990005493164063 + + - - + - + - - Camera #2 - Fonts/DroidSans.ttf,64 - 0 - + + 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,6 +146,7 @@ Welcome! Fonts/DroidSans.ttf,1280 + @@ -74,32 +157,40 @@ - 2 - + 3 + - - + + + Models/Core/UnitSphere.obj + + - 6 + 70 0.5 + + + Models/Core/UnitSphere.obj + + - 8 + 70 @@ -111,21 +202,30 @@ + + Models/Core/UnitSphere.obj + + - 6 + 70 0.5 + + + Models/Core/UnitSphere.obj + + - 8 + 70 @@ -137,21 +237,30 @@ + + Models/Core/UnitSphere.obj + + - 6 + 70 0.5 + + + Models/Core/UnitSphere.obj + + - - 8 + + 70 @@ -163,19 +272,28 @@ + + Models/Core/UnitSphere.obj + + - 6 + 70 0.5 + + + Models/Core/UnitSphere.obj + + - 8 + 70 @@ -191,6 +309,7 @@ Models/Assault.mesh + @@ -198,46 +317,15 @@ - - - - MainCamera - - - - Models/Camera.mesh - false - - - - - - - - - - - Taiwan #1 - Fonts/DroidSans.ttf,64 - 0 - - - - - - - - - - - + - 0.80000001192092896 + 0.10000000149011612 Models/DirectionalLightWidget.mesh + @@ -250,6 +338,7 @@ Models/Core/UnitCube.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..de672dd1 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -6,8 +6,13 @@ 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; +layout (binding = 1) uniform sampler2D NormalMapTexture; +layout (binding = 2) uniform sampler2D SpecularMapTexture; +layout (binding = 3) uniform sampler2D GlowMapTexture; + #define TILE_SIZE 16 @@ -46,7 +51,10 @@ layout (std430, binding = 4) buffer LightIndexBuffer in VertexData{ vec3 Position; vec3 Normal; + vec3 Tangent; + vec3 BiTangent; vec2 TextureCoordinate; + vec4 ExplosionColor; }Input; out vec4 sceneColor; @@ -98,13 +106,21 @@ LightResult CalcDirectionalLightSource(vec4 direction, vec4 color, float intensi return result; } +vec4 CalcNormalMappedValue(vec3 normal, vec3 tangent, vec3 bitangent, vec2 textureCoordinate, sampler2D normalMap) +{ + mat3 TBN = mat3(tangent, bitangent, normal); + vec3 NormalMap = texture(normalMap, textureCoordinate).xyz * 2.0 - vec3(1.0); + return vec4(TBN * normalize(NormalMap), 0.0); +} void main() { vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate); - vec4 glowTexel = texture2D(GlowMap, Input.TextureCoordinate); + vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate); + vec4 specularTexel = texture2D(SpecularMapTexture, Input.TextureCoordinate); vec4 position = V * M * vec4(Input.Position, 1.0); - vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); + vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate, NormalMapTexture); + //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); vec4 viewVec = normalize(-position); vec2 tilePos; @@ -134,24 +150,19 @@ void main() totalLighting.Specular += light_result.Specular; } - //sceneColor += Input.DiffuseColor; - vec4 color_result = DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * diffuseTexel * Color; - //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) { - bloomColor = vec4(color_result.xyz, 1.0); - } 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); + vec4 color_result = (DiffuseColor + Input.ExplosionColor) * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)) * diffuseTexel * Color; + + + float pos = ((P * vec4(Input.Position, 1)).y + 1.0)/2.0; + + if(pos <= FillPercentage) { + color_result += FillColor; + } + sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); + color_result += glowTexel; + + bloomColor = vec4(clamp(color_result.xyz - 1.0, 0, 100), 1.0); //Tiled Debug Code /* diff --git a/resources/Shaders/ForwardPlus.vert.glsl b/resources/Shaders/ForwardPlus.vert.glsl index c51216cb..1a7cca12 100644 --- a/resources/Shaders/ForwardPlus.vert.glsl +++ b/resources/Shaders/ForwardPlus.vert.glsl @@ -16,7 +16,10 @@ layout(location = 6) in vec4 BoneWeights; out VertexData{ vec3 Position; vec3 Normal; + vec3 Tangent; + vec3 BiTangent; vec2 TextureCoordinate; + vec4 ExplosionColor; }Output; void main() @@ -36,4 +39,7 @@ void main() Output.Position = (boneTransform * vec4(Position, 1.0)).xyz; Output.TextureCoordinate = TextureCoords; Output.Normal = vec3(M * vec4(Normal, 0.0)); + Output.Tangent = vec3(M * vec4(Tangent, 0.0)); + Output.BiTangent = vec3(M * vec4(BiTangent, 0.0)); + Output.ExplosionColor = vec4(0.0); } \ No newline at end of file diff --git a/resources/Shaders/Gaussian_horiz.frag.glsl b/resources/Shaders/Gaussian_horiz.frag.glsl index bd48d2d5..6a9572c2 100644 --- a/resources/Shaders/Gaussian_horiz.frag.glsl +++ b/resources/Shaders/Gaussian_horiz.frag.glsl @@ -1,4 +1,5 @@ #version 430 +#extension GL_EXT_gpu_shader4 : enable layout (binding = 0) uniform sampler2D Texture; @@ -12,7 +13,7 @@ uniform float weight[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.01 void main() { - vec2 tex_offset = 1.0 / textureSize(Texture, 0); + vec2 tex_offset = 1.0 / textureSize2D(Texture, 0); vec3 result = texture(Texture, Input.TextureCoordinate).rgb * weight[0]; for(int i = 1; i < 5; ++i) { diff --git a/resources/Shaders/Gaussian_vert.frag.glsl b/resources/Shaders/Gaussian_vert.frag.glsl index 25b08f9f..8b0e861a 100644 --- a/resources/Shaders/Gaussian_vert.frag.glsl +++ b/resources/Shaders/Gaussian_vert.frag.glsl @@ -1,4 +1,5 @@ #version 430 +#extension GL_EXT_gpu_shader4 : enable layout (binding = 0) uniform sampler2D Texture; @@ -12,7 +13,7 @@ uniform float weight[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.01 void main() { - vec2 tex_offset = 1.0 / textureSize(Texture, 0); + vec2 tex_offset = 1.0 / textureSize2D(Texture, 0); vec3 result = texture(Texture, Input.TextureCoordinate).rgb * weight[0]; for(int i = 1; i < 5; ++i) { diff --git a/resources/Shaders/Picking.vert.glsl b/resources/Shaders/Picking.vert.glsl index b2857cea..205a8fdd 100644 --- a/resources/Shaders/Picking.vert.glsl +++ b/resources/Shaders/Picking.vert.glsl @@ -3,18 +3,15 @@ uniform mat4 M; uniform mat4 V; uniform mat4 P; +uniform mat4 Bones[100]; 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; +layout(location = 5) in vec4 BoneIndices; +layout(location = 6) in vec4 BoneWeights; out VertexData{ vec3 Position; @@ -22,7 +19,14 @@ out VertexData{ void main() { - gl_Position = P * V* M * vec4(Position, 1.0); + mat4 boneTransform = mat4(1); + if(BoneWeights[0] > 0.0f){ + boneTransform = BoneWeights[0] * Bones[int(BoneIndices[0])] + + BoneWeights[1] * Bones[int(BoneIndices[1])] + + BoneWeights[2] * Bones[int(BoneIndices[2])] + + BoneWeights[3] * Bones[int(BoneIndices[3])]; + } - Output.Position = Position; + gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + Output.Position = (boneTransform * vec4(Position, 1.0)).xyz; } \ 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..410a7fa1 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; @@ -83,18 +76,18 @@ bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set& trigg bool TriggerSystem::OnTouch(const Events::TriggerTouch &event) { - LOG_INFO("Player entity %i touched trigger entity %i.", event.Entity, event.Trigger); + LOG_INFO("Player entity %i touched trigger entity %i.", event.Entity.ID, event.Trigger.ID); return true; } bool TriggerSystem::OnEnter(const Events::TriggerEnter &event) { - LOG_INFO("Player entity %i entered trigger entity %i.", event.Entity, event.Trigger); + LOG_INFO("Player entity %i entered trigger entity %i.", event.Entity.ID, event.Trigger.ID); return true; } bool TriggerSystem::OnLeave(const Events::TriggerLeave &event) { - LOG_INFO("Player entity %i left trigger entity %i.", event.Entity, event.Trigger); + LOG_INFO("Player entity %i left trigger entity %i.", event.Entity.ID, event.Trigger.ID); return true; } \ No newline at end of file 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..0d97d4ae 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,11 +37,12 @@ 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) +unsigned int EntityFile::GetTypeStride(std::string typeName) { - std::map typeStrides{ + std::map typeStrides{ { "bool", sizeof(bool) }, { "int", sizeof(int) }, { "float", sizeof(float) }, @@ -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..3d5e9e41 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(); @@ -113,7 +114,7 @@ void EntityFilePreprocessor::parseComponentInfo() std::string baseType = XS::ToString(elementDeclaration->getTypeDefinition()->getBaseType()->getName()); std::string effectiveType = type; - size_t stride = EntityFile::GetTypeStride(type); + unsigned int stride = EntityFile::GetTypeStride(type); if (stride == 0) { stride = EntityFile::GetTypeStride(baseType); if (stride == 0) { 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/InputManager.cpp b/src/Engine/Core/InputManager.cpp index 941cc223..b75809b1 100644 --- a/src/Engine/Core/InputManager.cpp +++ b/src/Engine/Core/InputManager.cpp @@ -218,7 +218,7 @@ void InputManager::PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis void InputManager::PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button) { bool currentState = m_CurrentGamepadButtonState[gamepadID][static_cast(button)]; - float lastState = m_LastGamepadButtonState[gamepadID][static_cast(button)]; + bool lastState = m_LastGamepadButtonState[gamepadID][static_cast(button)]; if (currentState != lastState) { if (currentState == true) { Events::GamepadButtonDown e; 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..69c25f61 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) @@ -92,6 +96,13 @@ EntityID World::GetParent(EntityID entity) void World::SetParent(EntityID entity, EntityID parent) { + // Don't allow an entity to be a child to itself! + if (entity == parent) { + // HACK: We purposely don't check the whole hierarchy of children here, since it would be way too slow. + // This might result in infinite loops if an entity somehow ends up as a child. + return; + } + EntityID lastParent = m_EntityParents.at(entity); auto parentChildren = m_EntityChildren.equal_range(lastParent); for (auto it = parentChildren.first; it != parentChildren.second; it++) { diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 390e69a5..70775a2b 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -1,10 +1,16 @@ #include "Editor/EditorGUI.h" +#include "Rendering/ESetCamera.h" EditorGUI::EditorGUI(World* world, EventBroker* eventBroker) : m_World(world) , m_EventBroker(eventBroker) { EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &EditorGUI::OnKeyDown); + EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorGUI::OnFileDropped); + EVENT_SUBSCRIBE_MEMBER(m_EPause, &EditorGUI::OnPause); + EVENT_SUBSCRIBE_MEMBER(m_EResume, &EditorGUI::OnResume); + EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &EditorGUI::OnLockMouse); + EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &EditorGUI::OnUnlockMouse); } void EditorGUI::Draw() @@ -36,39 +42,60 @@ void EditorGUI::drawTools() return; } + // Widget modes createWidgetToolButton(WidgetMode::Translate); if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Translate"); + ImGui::SetTooltip("Translate (W)"); } ImGui::SameLine(); createWidgetToolButton(WidgetMode::Rotate); if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Rotate"); + ImGui::SetTooltip("Rotate (E)"); } ImGui::SameLine(); createWidgetToolButton(WidgetMode::Scale); if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Scale"); + ImGui::SetTooltip("Scale (R)"); } + + ImGui::SameLine(); + ImGui::ItemSize(ImVec2(5, 0)); + + // Widget space + ImGui::SameLine(); + GLuint spaceTexture = 0; + if (m_CurrentWidgetSpace == WidgetSpace::Global) { + spaceTexture = tryLoadTexture("Textures/Icons/Global.png"); + } else if (m_CurrentWidgetSpace == WidgetSpace::Local) { + spaceTexture = tryLoadTexture("Textures/Icons/Local.png"); + } + if (ImGui::ImageButton(reinterpret_cast(spaceTexture), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1))) { + toggleWidgetSpace(); + } + if (ImGui::IsItemHovered()) { + if (m_CurrentWidgetSpace == WidgetSpace::Global) { + ImGui::SetTooltip("Widget space: Global (X)"); + } else if (m_CurrentWidgetSpace == WidgetSpace::Local) { + ImGui::SetTooltip("Widget space: Local (X)"); + } + } + ImGui::SameLine(); ImGui::ItemSize(ImVec2(5, 0)); // Play button ImGui::SameLine(); - static bool paused = false; - if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Play.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (!paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { + if (ImGui::ImageButton(reinterpret_cast(tryLoadTexture("Textures/Icons/Play.png")), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (!m_Paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { Events::Resume e; e.World = m_World; m_EventBroker->Publish(e); - paused = false; } // Pause button ImGui::SameLine(); - if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Pause.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { + if (ImGui::ImageButton(reinterpret_cast(tryLoadTexture("Textures/Icons/Pause.png")), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (m_Paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { Events::Pause e; e.World = m_World; m_EventBroker->Publish(e); - paused = true; } ImGui::End(); @@ -167,10 +194,7 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity) ImGui::Text(formatEntityName(entity).c_str()); ImGui::End(); } - }/* else if (m_CurrentlyDragging == entity) { - LOG_DEBUG("Stopped dragging %i", entity.ID); - m_CurrentlyDragging = EntityWrapper::Invalid; - }*/ + } // Entity context menu std::string contextMenuUniqueID = std::string("EntityContextMenu") + std::to_string(entity.ID); if (hovered && ImGui::IsMouseClicked(1)) { @@ -233,10 +257,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(), static_cast(componentTypes.size()), static_cast(componentTypes.size()))) { if (selectedItem != -1) { if (m_OnComponentAttach != nullptr) { std::string chosenComponentType(componentTypes.at(selectedItem)); @@ -282,9 +308,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 +330,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; } @@ -426,18 +459,31 @@ bool EditorGUI::drawComponentField_bool(ComponentWrapper &c, const ComponentInfo bool EditorGUI::drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field) { + bool result = false; + auto& val = c.Field(field.Name); + char tempString[1024]; // Let's just hope this is an sufficiently large buffer for strings :) tempString[1023] = '\0'; // Null terminator just in case the string is larger than the buffer // Copy the string into the buffer, taking the null terminator into account memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString) - 1)); if (ImGui::InputText("", tempString, sizeof(tempString))) { val = std::string(tempString); - return true; - } else { - return false; + result = true; } - // TODO: Handle drag and drop of files + + // Handle file drag and drop + if (ImGui::IsItemHovered() && !m_DroppedFile.empty()) { + // Unset potential input focus or our newly set value will be overwritten! + if (ImGui::IsItemActive()) { + ImGui::SetActiveID(0, nullptr); + } + // Set the actual dropped value + val = m_DroppedFile; + m_DroppedFile = ""; + } + + return result; } void EditorGUI::drawModals() @@ -519,7 +565,7 @@ void EditorGUI::createWidgetToolButton(WidgetMode mode) break; } if (ImGui::ImageButton( - (void*)texture, + reinterpret_cast(texture), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), @@ -528,10 +574,7 @@ void EditorGUI::createWidgetToolButton(WidgetMode mode) (m_CurrentWidgetMode == mode) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1) ) ) { - if (m_OnWidgetMode != nullptr) { - m_OnWidgetMode(mode); - } - m_CurrentWidgetMode = mode; + setWidgetMode(mode); } } @@ -561,6 +604,61 @@ bool EditorGUI::OnKeyDown(const Events::KeyDown& e) } } + if (!m_MouseLocked) { + if (e.KeyCode == GLFW_KEY_W) { + setWidgetMode(WidgetMode::Translate); + } + if (e.KeyCode == GLFW_KEY_E) { + setWidgetMode(WidgetMode::Rotate); + } + if (e.KeyCode == GLFW_KEY_R) { + setWidgetMode(WidgetMode::Scale); + } + + if (e.KeyCode == GLFW_KEY_X) { + toggleWidgetSpace(); + } + } + + return true; +} + +bool EditorGUI::OnFileDropped(const Events::FileDropped& e) +{ + // Make a best effort to make the path relative to the working directory of the executable + m_DroppedFile = boost::filesystem::path(e.Path).lexically_relative(boost::filesystem::current_path()).string(); + // Compensate for Windows retardedness + std::replace(m_DroppedFile.begin(), m_DroppedFile.end(), '\\', '/'); + // Special case for when people drop from the asset folder instead of from the symlink to the asset folders in bin + boost::algorithm::replace_first(m_DroppedFile, "../assets/", ""); + return true; +} + +bool EditorGUI::OnPause(const Events::Pause& e) +{ + if (e.World == m_World) { + m_Paused = true; + } + return true; +} + +bool EditorGUI::OnResume(const Events::Resume& e) +{ + if (e.World == m_World) { + m_Paused = false; + } + return true; +} + +bool EditorGUI::OnLockMouse(const Events::LockMouse& e) +{ + m_MouseLocked = true; + return true; +} + +bool EditorGUI::OnUnlockMouse(const Events::UnlockMouse& e) +{ + m_MouseLocked = false; return true; } @@ -635,6 +733,32 @@ void EditorGUI::openModal(const std::string& modal) m_ModalsToOpen.insert(modal); } +void EditorGUI::setWidgetMode(WidgetMode mode) +{ + if (m_OnWidgetMode != nullptr) { + m_OnWidgetMode(mode); + } + m_CurrentWidgetMode = mode; +} + +void EditorGUI::toggleWidgetSpace() +{ + if (m_CurrentWidgetSpace == WidgetSpace::Global) { + m_CurrentWidgetSpace = WidgetSpace::Local; + } else if (m_CurrentWidgetSpace == WidgetSpace::Local) { + m_CurrentWidgetSpace = WidgetSpace::Global; + } + + if (m_OnWidgetSpace != nullptr) { + m_OnWidgetSpace(m_CurrentWidgetSpace); + } +} + +bool EditorGUI::compareCharArray(const char* c1, const char* c2) +{ + return strcmp(c1, c2) < 0; +} + void EditorGUI::SetDirty(EntityWrapper entity) { EntityWrapper baseParent = entity; @@ -722,7 +846,7 @@ void EditorGUI::entityDelete(EntityWrapper entity) void EditorGUI::entityChangeParent(EntityWrapper entity, EntityWrapper parent) { - if (entity == parent) { + if (entity == parent || parent.IsChildOf(entity)) { return; } diff --git a/src/Engine/Editor/EditorRenderSystem.cpp b/src/Engine/Editor/EditorRenderSystem.cpp index ed054052..67b09a21 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,8 +48,12 @@ 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); - scene.ForwardJobs.push_back(modelJob); + std::shared_ptr modelJob = std::make_shared(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World, glm::vec4(0), 0.f); + if(cModel["Transparent"]) { + scene.TransparentObjects.push_back(modelJob); + } else { + scene.OpaqueObjects.push_back(modelJob); + } } } } @@ -76,9 +80,9 @@ bool EditorRenderSystem::OnSetCamera(Events::SetCamera& e) { ComponentWrapper cTransform = e.CameraEntity["Transform"]; ComponentWrapper cCamera = e.CameraEntity["Camera"]; - m_EditorCamera->SetFOV((double)cCamera["FOV"]); - m_EditorCamera->SetNearClip((double)cCamera["NearClip"]); - m_EditorCamera->SetFarClip((double)cCamera["FarClip"]); + m_EditorCamera->SetFOV(static_cast((double)cCamera["FOV"])); + m_EditorCamera->SetNearClip(static_cast((double)cCamera["NearClip"])); + m_EditorCamera->SetFarClip(static_cast((double)cCamera["FarClip"])); m_EditorCamera->SetPosition(cTransform["Position"]); m_EditorCamera->SetOrientation(glm::quat((const glm::vec3&)cTransform["Orientation"])); m_CurrentCamera = e.CameraEntity; diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 9c0e2e47..ccbc1b48 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -31,6 +31,7 @@ EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* re m_EditorGUI->SetComponentAttachCallback(std::bind(&EditorSystem::OnComponentAttach, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetComponentDeleteCallback(std::bind(&EditorSystem::OnComponentDelete, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetWidgetModeCallback(std::bind(&EditorSystem::setWidgetMode, this, std::placeholders::_1)); + m_EditorGUI->SetWidgetSpaceCallback(std::bind(&EditorSystem::OnWidgetSpace, this, std::placeholders::_1)); EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress); EVENT_SUBSCRIBE_MEMBER(m_EWidgetDelta, &EditorSystem::OnWidgetDelta); @@ -65,7 +66,12 @@ void EditorSystem::Update(double dt) m_EditorStats->Draw(actualDelta); if (m_CurrentSelection.Valid() && m_Widget.Valid()) { - (glm::vec3&)m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID); + (glm::vec3&)m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection); + if (m_WidgetSpace == EditorGUI::WidgetSpace::Local) { + (glm::vec3&)m_Widget["Transform"]["Orientation"] = Transform::AbsoluteOrientationEuler(m_CurrentSelection); + } else { + (glm::vec3&)m_Widget["Transform"]["Orientation"] = glm::vec3(0, 0, 0); + } } m_EditorWorldSystemPipeline->Update(actualDelta); @@ -82,11 +88,22 @@ void EditorSystem::Update(double dt) void EditorSystem::Enable() { m_EditorCameraInputController->Enable(); + m_EventBroker->Publish(Events::UnlockMouse()); - Events::SetCamera e; - e.CameraEntity = m_EditorCamera; - m_EventBroker->Publish(e); - (glm::vec3&)m_EditorCamera["Transform"]["Position"] = Transform::AbsolutePosition(m_ActualCamera); + + // Enable editor camera + Events::SetCamera eSetCamera; + eSetCamera.CameraEntity = m_EditorCamera; + m_EventBroker->Publish(eSetCamera); + if (m_ActualCamera.Valid()) { + (glm::vec3&)m_EditorCamera["Transform"]["Position"] = Transform::AbsolutePosition(m_ActualCamera); + } + + // Pause the world we're editing + Events::Pause ePause; + ePause.World = m_World; + m_EventBroker->Publish(ePause); + m_Enabled = true; } @@ -154,6 +171,11 @@ void EditorSystem::OnComponentDelete(EntityWrapper entity, const std::string& co } } +void EditorSystem::OnWidgetSpace(EditorGUI::WidgetSpace widgetSpace) +{ + m_WidgetSpace = widgetSpace; +} + bool EditorSystem::OnMousePress(const Events::MousePress& e) { ImGuiIO& io = ImGui::GetIO(); @@ -170,12 +192,18 @@ bool EditorSystem::OnMousePress(const Events::MousePress& e) bool EditorSystem::OnWidgetDelta(const Events::WidgetDelta& e) { if (m_CurrentSelection.Valid()) { - glm::quat parentOrientation; - EntityWrapper parent = m_CurrentSelection.Parent(); - if (parent.Valid()) { - parentOrientation = glm::inverse(Transform::AbsoluteOrientation(parent.World, parent.ID)); + if (m_WidgetSpace == EditorGUI::WidgetSpace::Global) { + glm::quat parentOrientation; + EntityWrapper parent = m_CurrentSelection.Parent(); + if (parent.Valid()) { + parentOrientation = glm::inverse(Transform::AbsoluteOrientation(parent)); + } + (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation; + } else if (m_WidgetSpace == EditorGUI::WidgetSpace::Local) { + glm::quat selectionOri = glm::quat((glm::vec3)m_CurrentSelection["Transform"]["Orientation"]); + glm::vec3 localTranslation = selectionOri * e.Translation; + (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += localTranslation; } - (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation; m_EditorGUI->SetDirty(m_CurrentSelection); } return true; @@ -203,7 +231,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/Editor/EditorWidgetSystem.cpp b/src/Engine/Editor/EditorWidgetSystem.cpp index 479671e2..7c20a7c7 100644 --- a/src/Engine/Editor/EditorWidgetSystem.cpp +++ b/src/Engine/Editor/EditorWidgetSystem.cpp @@ -23,14 +23,18 @@ void EditorWidgetSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper Events::WidgetDelta e; - EntityWrapper moveEntity = entity.Parent(); - if (!moveEntity.Valid()) { - moveEntity = entity; + // Widget axes should have a common parent + EntityWrapper widgetBase = entity.Parent(); + if (!widgetBase.Valid()) { + widgetBase = entity; } + glm::vec3 widgetBasePos = widgetBase["Transform"]["Position"]; + glm::quat widgetBaseOri = glm::quat((glm::vec3)widgetBase["Transform"]["Orientation"]); auto camera = m_PickData.Camera; - glm::vec3 axis = cEditorWidget["Axis"]; - glm::vec2 axisScreen = camera->WorldToScreen(axis, m_Renderer->Resolution()) - camera->WorldToScreen(glm::vec3(0, 0, 0), m_Renderer->Resolution()); + glm::vec3 axis = (glm::vec3)cEditorWidget["Axis"]; + glm::vec3 axisOriented = widgetBaseOri * axis; + glm::vec2 axisScreen = camera->WorldToScreen(widgetBasePos + axisOriented, m_Renderer->GetViewportSize()) - camera->WorldToScreen(widgetBasePos, m_Renderer->GetViewportSize()); float dot = glm::dot(m_MouseDelta, glm::normalize(axisScreen)) / glm::length(axisScreen); glm::vec3 worldMovement = dot * axis; diff --git a/src/Engine/Input/MouseInputHandler.cpp b/src/Engine/Input/MouseInputHandler.cpp index 5996b43d..9346f627 100644 --- a/src/Engine/Input/MouseInputHandler.cpp +++ b/src/Engine/Input/MouseInputHandler.cpp @@ -98,7 +98,7 @@ bool MouseInputHandler::OnMouseMove(const Events::MouseMove& e) Events::InputCommand ic; ic.PlayerID = -1; std::tie(ic.Command, ic.Value) = it->second; - ic.Value *= e.DeltaX; + ic.Value *= static_cast(e.DeltaX); m_InputProxy->Publish(ic); } } @@ -109,7 +109,7 @@ bool MouseInputHandler::OnMouseMove(const Events::MouseMove& e) Events::InputCommand ic; ic.PlayerID = -1; std::tie(ic.Command, ic.Value) = it->second; - ic.Value *= e.DeltaY; + ic.Value *= static_cast(e.DeltaY); m_InputProxy->Publish(ic); } } diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 05e9da61..6c43cc8b 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -346,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 a94acd39..adf14413 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); diff --git a/src/Engine/Rendering/AnimationSystem.cpp b/src/Engine/Rendering/AnimationSystem.cpp new file mode 100644 index 00000000..2126362f --- /dev/null +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -0,0 +1,47 @@ +#include "Rendering/AnimationSystem.h" + +void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt) +{ + if(!entity.HasComponent("Model")) { + return; + } + + Model* model; + try { + model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]); + } catch (const std::exception&) { + return; + } + + + Skeleton* skeleton = model->m_RawModel->m_Skeleton; + const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["Name"]); + + if(animation != nullptr) { + double animationSpeed = (double)animationComponent["Speed"]; + + if (animationSpeed != 0.0) { + double nextTime = (double)animationComponent["Time"] + animationSpeed * dt; + + + if (!(bool)animationComponent["Loop"] && glm::abs(nextTime) > animation->Duration) { + (double&)animationComponent["Time"] = glm::sign(nextTime) * animation->Duration; + (double&)animationComponent["Speed"] = 0.0; + Events::AnimationComplete e; + e.Entity = entity; + e.Name = (std::string)animationComponent["Name"]; + m_EventBroker->Publish(e); + } else { + if (glm::abs(nextTime) > animation->Duration) { + (double&)animationComponent["Time"] = glm::abs(nextTime) - animation->Duration; + } else { + (double&)animationComponent["Time"] = nextTime; + } + } + } + } + + + +} + diff --git a/src/Engine/Rendering/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index 8fe1d807..5d8b2359 100644 --- a/src/Engine/Rendering/DrawBloomPass.cpp +++ b/src/Engine/Rendering/DrawBloomPass.cpp @@ -13,7 +13,7 @@ DrawBloomPass::DrawBloomPass(IRenderer* renderer) void DrawBloomPass::InitializeTextures() { - m_WhiteTexture = ResourceManager::Load("Textures/Core/Blank.png"); + m_WhiteTexture = ResourceManager::Load("Textures/Core/White.png"); } void DrawBloomPass::InitializeShaderPrograms() @@ -34,12 +34,12 @@ void DrawBloomPass::InitializeShaderPrograms() void DrawBloomPass::InitializeBuffers() { - GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + 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))); m_GaussianFrameBuffer_horiz.Generate(); - GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); m_GaussianFrameBuffer_vert.AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_vert, GL_COLOR_ATTACHMENT0))); m_GaussianFrameBuffer_vert.Generate(); diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index ca2a9d77..aa9da9a1 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -11,21 +11,23 @@ DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCulling void DrawFinalPass::InitializeTextures() { - m_WhiteTexture = ResourceManager::Load("Textures/Core/Blank.png"); + m_WhiteTexture = ResourceManager::Load("Textures/Core/White.png"); m_BlackTexture = ResourceManager::Load("Textures/Core/Black.png"); + m_NeutralNormalTexture = ResourceManager::Load("Textures/Core/NeutralNormalMap.png"); + m_GreyTexture = ResourceManager::Load("Textures/Core/Grey.png"); } void DrawFinalPass::InitializeFrameBuffers() { glGenRenderbuffers(1, &m_DepthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + + GenerateTexture(&m_SceneTexture, 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); + 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); - GenerateTexture(&m_SceneTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - //GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - //GenerateMipMapTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().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 +44,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,68 +60,15 @@ 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()); + DrawModelRenderQueues(scene.OpaqueObjects, scene); + GLERROR("DrawFinalPass::Draw: OpaqueObjects"); + DrawModelRenderQueues(scene.TransparentObjects, scene); + GLERROR("DrawFinalPass::Draw: TransparentObjects"); - 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->Resolution().Width, m_Renderer->Resolution().Height); - - - //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)); - - glActiveTexture(GL_TEXTURE0); - if(modelJob->DiffuseTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture); - } else { - 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); - }*/ - - //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) { - auto animation = modelJob->Model->m_RawModel->m_Skeleton->GetAnimation("running"); - if (animation != nullptr) { - std::vector frameBones = modelJob->Model->m_RawModel->m_Skeleton->GetFrameBones( - *animation, - 0.0f - ); - 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))); - } - } GLERROR("DrawFinalPass::Draw: END"); delete state; } @@ -148,4 +106,153 @@ void DrawFinalPass::GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); GLERROR("MipMap Texture initialization failed"); -} \ No newline at end of file +} + +void DrawFinalPass::DrawModelRenderQueues(std::list>& job, RenderScene& scene) +{ + GLuint forwardHandle = m_ForwardPlusProgram->GetHandle(); + GLuint explosionHandle = m_ExplosionEffectProgram->GetHandle(); + + 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()); + + for(auto &job : job) + { + auto explosionEffectJob = std::dynamic_pointer_cast(job); + if(explosionEffectJob) { + //Bind program + m_ExplosionEffectProgram->Bind(); + + //Bind uniforms + BindExplosionUniforms(explosionHandle, explosionEffectJob, scene); + + if (explosionEffectJob->Model->m_RawModel->m_Skeleton != nullptr) { + + if (explosionEffectJob->Animation != nullptr) { + std::vector frameBones = explosionEffectJob->Skeleton->GetFrameBones(*explosionEffectJob->Animation, explosionEffectJob->AnimationTime); + glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } + } + + //bind textures + BindExplosionTextures(explosionEffectJob); + //draw + 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))); + + } else { + auto modelJob = std::dynamic_pointer_cast(job); + if (modelJob) { + //bind forward program + m_ForwardPlusProgram->Bind(); + glUniform2f(glGetUniformLocation(forwardHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + + //bind uniforms + BindModelUniforms(forwardHandle, modelJob, scene); + + //bind textures + BindModelTextures(modelJob); + + if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + + if (modelJob->Animation != nullptr) { + std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); + glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } + } + + //draw + 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"); + } + } + } + +} + +void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) +{ + 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->Resolution().Width, m_Renderer->Resolution().Height); + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); + glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); + glUniform3fv(glGetUniformLocation(shaderHandle, "ExplosionOrigin"), 1, glm::value_ptr(job->ExplosionOrigin)); + glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), job->TimeSinceDeath); + glUniform1f(glGetUniformLocation(shaderHandle, "ExplosionDuration"), job->ExplosionDuration); + glUniform4fv(glGetUniformLocation(shaderHandle, "EndColor"), 1, glm::value_ptr(job->EndColor)); + glUniform1i(glGetUniformLocation(shaderHandle, "Randomness"), job->Randomness); + glUniform1f(glGetUniformLocation(shaderHandle, "RandomnessScalar"), job->RandomnessScalar); + glUniform2fv(glGetUniformLocation(shaderHandle, "Velocity"), 1, glm::value_ptr(job->Velocity)); + glUniform1i(glGetUniformLocation(shaderHandle, "ColorByDistance"), job->ColorByDistance); + glUniform1i(glGetUniformLocation(shaderHandle, "ExponentialAccelaration"), job->ExponentialAccelaration); + glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(job->DiffuseColor)); + glUniform1fv(glGetUniformLocation(shaderHandle, "RandomNumbers"), 50, job->RandomNumbers.data()); +} + +void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) +{ + 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->Resolution().Width, m_Renderer->Resolution().Height); + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); + glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); + glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(job->DiffuseColor)); + glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(job->FillColor)); + glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), job->FillPercentage); +} + + +void DrawFinalPass::BindExplosionTextures(std::shared_ptr& job) +{ + glActiveTexture(GL_TEXTURE0); + if (job->DiffuseTexture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture->m_Texture); + } else { + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + } + glActiveTexture(GL_TEXTURE1); + if (job->IncandescenceTexture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture->m_Texture); + } else { + glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); + } +} + +void DrawFinalPass::BindModelTextures(std::shared_ptr& job) +{ + glActiveTexture(GL_TEXTURE0); + if (job->DiffuseTexture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture->m_Texture); + } else { + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + } + + glActiveTexture(GL_TEXTURE1); + if (job->NormalTexture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->NormalTexture->m_Texture); + } else { + glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); + } + + glActiveTexture(GL_TEXTURE2); + if (job->SpecularTexture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->SpecularTexture->m_Texture); + } else { + glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); + } + + glActiveTexture(GL_TEXTURE3); + if (job->IncandescenceTexture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture->m_Texture); + } else { + glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); + } +} + diff --git a/src/Engine/Rendering/ImGuiRenderPass.cpp b/src/Engine/Rendering/ImGuiRenderPass.cpp index e67eea71..e0e7347f 100644 --- a/src/Engine/Rendering/ImGuiRenderPass.cpp +++ b/src/Engine/Rendering/ImGuiRenderPass.cpp @@ -134,8 +134,8 @@ bool ImGuiRenderPass::OnMouseRelease(const Events::MouseRelease& e) bool ImGuiRenderPass::OnMouseMove(const Events::MouseMove& e) { ImGuiIO& io = ImGui::GetIO(); - io.MousePos.x = e.X; - io.MousePos.y = e.Y; + io.MousePos.x = static_cast(e.X); + io.MousePos.y = static_cast(e.Y); return true; } @@ -271,7 +271,7 @@ bool ImGuiRenderPass::createFontsTexture() glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // Store our identifier - io.Fonts->TexID = (void*)g_FontTexture; + io.Fonts->TexID = reinterpret_cast(g_FontTexture); // Restore state glBindTexture(GL_TEXTURE_2D, last_texture); @@ -291,7 +291,7 @@ void ImGuiRenderPass::newFrame() io.DisplaySize = ImVec2((float)w, (float)h); io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); - io.DeltaTime = g_DeltaTime; + io.DeltaTime = static_cast(g_DeltaTime); io.KeyCtrl = glfwGetKey(g_Window, GLFW_KEY_LEFT_CONTROL) || glfwGetKey(g_Window, GLFW_KEY_RIGHT_CONTROL); io.KeyShift = glfwGetKey(g_Window, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(g_Window, GLFW_KEY_RIGHT_SHIFT); diff --git a/src/Engine/Rendering/LightCullingPass.cpp b/src/Engine/Rendering/LightCullingPass.cpp index a68fe4d1..5e6da64d 100644 --- a/src/Engine/Rendering/LightCullingPass.cpp +++ b/src/Engine/Rendering/LightCullingPass.cpp @@ -25,8 +25,8 @@ void LightCullingPass::GenerateNewFrustum(RenderScene& scene) glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); - glDispatchCompute((int)(m_Renderer->Resolution().Width/(TILE_SIZE*TILE_SIZE) + 1), (int)(m_Renderer->Resolution().Height/(TILE_SIZE*TILE_SIZE) + 1), 1); + glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glDispatchCompute((int)(m_Renderer->GetViewportSize().Width/(TILE_SIZE*TILE_SIZE) + 1), (int)(m_Renderer->GetViewportSize().Height/(TILE_SIZE*TILE_SIZE) + 1), 1); GLERROR("CalculateFrustum Error: End"); } @@ -40,7 +40,7 @@ void LightCullingPass::OnResolutionChange() void LightCullingPass::SetSSBOSizes() { - m_NumberOfTiles = (int)(m_Renderer->Resolution().Width/TILE_SIZE) * (int)(m_Renderer->Resolution().Height/TILE_SIZE); + m_NumberOfTiles = (int)(m_Renderer->GetViewportSize().Width/TILE_SIZE) * (int)(m_Renderer->GetViewportSize().Height/TILE_SIZE); m_Frustums = new Frustum[m_NumberOfTiles]; m_LightGrid = new LightGrid[m_NumberOfTiles]; @@ -67,14 +67,14 @@ void LightCullingPass::CullLights(RenderScene& scene) glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); m_LightCullProgram->Bind(); - glUniform2f(glGetUniformLocation(m_LightCullProgram->GetHandle(), "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + glUniform2f(glGetUniformLocation(m_LightCullProgram->GetHandle(), "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); glUniformMatrix4fv(glGetUniformLocation(m_LightCullProgram->GetHandle(), "V"), 1, false, glm::value_ptr(scene.Camera->ViewMatrix())); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO); - glDispatchCompute(glm::ceil(m_Renderer->Resolution().Width / TILE_SIZE), glm::ceil(m_Renderer->Resolution().Height / TILE_SIZE), 1); + glDispatchCompute(glm::ceil(m_Renderer->GetViewportSize().Width/ TILE_SIZE), glm::ceil(m_Renderer->GetViewportSize().Height / TILE_SIZE), 1); GLERROR("CullLights Error: End"); } diff --git a/src/Engine/Rendering/PNG.cpp b/src/Engine/Rendering/PNG.cpp index f1e7b06d..7ffd5c20 100644 --- a/src/Engine/Rendering/PNG.cpp +++ b/src/Engine/Rendering/PNG.cpp @@ -71,12 +71,12 @@ PNG::PNG(std::string path) png_read_update_info(png_ptr, info_ptr); } - unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr); + std::size_t row_bytes = png_get_rowbytes(png_ptr, info_ptr); this->Data = new unsigned char[height * row_bytes]; png_bytep* row_pointers = new png_bytep[height]; // Point each row to the continuous data array - for (int i = 0; i < height; ++i) { + for (unsigned int i = 0; i < height; ++i) { // Invert Y for OpenGL row_pointers[height - 1 - i] = this->Data + i * row_bytes; } diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index f063b344..792539f8 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -18,14 +18,14 @@ PickingPass::~PickingPass() void PickingPass::InitializeTextures() { GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR, - glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE); + glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE); } void PickingPass::InitializeFrameBuffers() { glGenRenderbuffers(1, &m_DepthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); m_PickingBuffer.AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT))); m_PickingBuffer.AddResource(std::shared_ptr(new Texture2D(&m_PickingTexture, GL_COLOR_ATTACHMENT0))); @@ -48,7 +48,7 @@ void PickingPass::Draw(RenderScene& scene) PickingPassState* state = new PickingPassState(m_PickingBuffer.GetHandle()); //TODO: Render: Add code for more jobs than modeljobs. - GLuint ShaderHandle = m_PickingProgram->GetHandle(); + GLuint shaderHandle = m_PickingProgram->GetHandle(); m_PickingProgram->Bind(); if (scene.ClearDepth) { @@ -56,7 +56,7 @@ void PickingPass::Draw(RenderScene& scene) } m_Camera = scene.Camera; - for (auto &job : scene.ForwardJobs) { + for (auto &job : scene.OpaqueObjects) { auto modelJob = std::dynamic_pointer_cast(job); if (modelJob) { @@ -75,22 +75,76 @@ 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; } } m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->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())); - glUniform2fv(glGetUniformLocation(ShaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->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())); + glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + + if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + + if (modelJob->Animation != nullptr) { + std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); + 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); - glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, nullptr, modelJob->StartIndex); + glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int))); + } + } + + for (auto &job : scene.TransparentObjects) { + auto modelJob = std::dynamic_pointer_cast(job); + + if (modelJob) { + int pickColor[2] = { m_ColorCounter[0], m_ColorCounter[1] }; + + PickingInfo pickInfo; + pickInfo.Entity = modelJob->Entity; + pickInfo.World = modelJob->World; + pickInfo.Camera = scene.Camera; + + auto color = m_EntityColors.find(std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)); + if (color != m_EntityColors.end()) { + pickColor[0] = color->second[0]; + pickColor[1] = color->second[1]; + } else { + 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] += 5; + } else { + m_ColorCounter[0] += 50; + } + } + + m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; + + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->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())); + glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + + if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + + if (modelJob->Animation != nullptr) { + std::vector frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime); + 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))); } } diff --git a/src/Engine/Rendering/RawModelCustom.cpp b/src/Engine/Rendering/RawModelCustom.cpp index 83f6e703..59634625 100644 --- a/src/Engine/Rendering/RawModelCustom.cpp +++ b/src/Engine/Rendering/RawModelCustom.cpp @@ -22,42 +22,42 @@ void RawModelCustom::ReadMeshFile(std::string filePath) if (!in.is_open()) { throw Resource::FailedLoadingException("Open mesh file failed"); } - unsigned int fileByteSize = in.tellg(); + unsigned int fileByteSize = static_cast(in.tellg()); in.seekg(0, std::ios_base::beg); fileData = new char[fileByteSize]; in.read(fileData, fileByteSize); in.close(); - unsigned int offset = 0; + std::size_t offset = 0; if (fileByteSize > 0) { - ReadMeshFileHeader(offset, fileData, fileByteSize); + ReadMeshFileHeader(offset, fileData); ReadMesh(offset, fileData, fileByteSize); } delete fileData; } -void RawModelCustom::ReadMeshFileHeader(unsigned int& offset, char* fileData, unsigned int& fileByteSize) +void RawModelCustom::ReadMeshFileHeader(std::size_t& offset, char* fileData) { #ifdef BOOST_LITTLE_ENDIAN - m_Vertices.resize(*(unsigned int*)(fileData + offset)); + m_Vertices.resize(static_cast(*(unsigned int*)(fileData + offset))); offset += sizeof(unsigned int); - m_Indices.resize(*(unsigned int*)(fileData + offset)); + m_Indices.resize(static_cast(*(unsigned int*)(fileData + offset))); offset += sizeof(unsigned int); #else #endif } -void RawModelCustom::ReadMesh(unsigned int& offset, char* fileData, unsigned int& fileByteSize) +void RawModelCustom::ReadMesh(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { ReadVertices(offset, fileData, fileByteSize); ReadIndices(offset, fileData, fileByteSize); } -void RawModelCustom::ReadVertices(unsigned int& offset, char* fileData, unsigned int& fileByteSize) +void RawModelCustom::ReadVertices(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { #ifdef BOOST_LITTLE_ENDIAN - if (offset + m_Vertices.size() * sizeof(Vertex) > fileByteSize) { + if (offset + m_Vertices.size() * sizeof(Vertex) > fileByteSize) { throw Resource::FailedLoadingException("Reading vertices failed"); } @@ -67,7 +67,7 @@ void RawModelCustom::ReadVertices(unsigned int& offset, char* fileData, unsigned #endif } -void RawModelCustom::ReadIndices(unsigned int& offset, char* fileData, unsigned int& fileByteSize) +void RawModelCustom::ReadIndices(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { #ifdef BOOST_LITTLE_ENDIAN if (offset + m_Indices.size() * sizeof(unsigned int) > fileByteSize) { @@ -90,35 +90,36 @@ void RawModelCustom::ReadMaterialFile(std::string filePath) if (!in.is_open()) { throw Resource::FailedLoadingException("Open material file failed"); } - unsigned int fileByteSize = in.tellg(); + + unsigned int fileByteSize = static_cast(in.tellg()); in.seekg(0, std::ios_base::beg); fileData = new char[fileByteSize]; in.read(fileData, fileByteSize); in.close(); - unsigned int offset = 0; + std::size_t offset = 0; if (fileByteSize > 0) { ReadMaterials(offset, fileData, fileByteSize); } delete fileData; } -void RawModelCustom::ReadMaterials(unsigned int& offset, char* fileData, unsigned int& fileByteSize) +void RawModelCustom::ReadMaterials(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { #ifdef BOOST_LITTLE_ENDIAN unsigned int* numMaterials = (unsigned int*)(fileData); MaterialGroups.reserve(*numMaterials); offset += sizeof(unsigned int); - for (int i = 0; i < *numMaterials; i++) { + for (unsigned int i = 0; i < *numMaterials; i++) { ReadMaterialSingle(offset, fileData, fileByteSize); } #else #endif } -void RawModelCustom::ReadMaterialSingle(unsigned int &offset, char* fileData, unsigned int& fileByteSize) +void RawModelCustom::ReadMaterialSingle(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { MaterialGroup newMaterial; @@ -210,14 +211,14 @@ void RawModelCustom::ReadAnimationFile(std::string filePath) return; } - unsigned int fileByteSize = in.tellg(); + unsigned int fileByteSize = static_cast(in.tellg()); in.seekg(0, std::ios_base::beg); fileData = new char[fileByteSize]; in.read(fileData, fileByteSize); in.close(); - unsigned int offset = 0; + std::size_t offset = 0; if (fileByteSize > 0) { m_Skeleton = new Skeleton(); @@ -235,7 +236,7 @@ void RawModelCustom::ReadAnimationFile(std::string filePath) delete fileData; } -void RawModelCustom::ReadAnimationBindPoses(unsigned int &offset, char* fileData, unsigned int& fileByteSize) +void RawModelCustom::ReadAnimationBindPoses(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { #ifdef BOOST_LITTLE_ENDIAN unsigned int* numBones = (unsigned int*)(fileData + offset); @@ -248,7 +249,7 @@ void RawModelCustom::ReadAnimationBindPoses(unsigned int &offset, char* fileData #endif } -void RawModelCustom::ReadAnimationJoint(unsigned int &offset, char* fileData, unsigned int& fileByteSize) +void RawModelCustom::ReadAnimationJoint(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { #ifdef BOOST_LITTLE_ENDIAN if (offset + sizeof(unsigned int) > fileByteSize) { @@ -290,14 +291,14 @@ void RawModelCustom::ReadAnimationJoint(unsigned int &offset, char* fileData, un #endif } -void RawModelCustom::ReadAnimationClips(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int numberOfClips) +void RawModelCustom::ReadAnimationClips(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int numberOfClips) { for (unsigned int i = 0; i < numberOfClips; i++) { ReadAnimationClipSingle(offset, fileData, fileByteSize, i); } } -void RawModelCustom::ReadAnimationClipSingle(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int clipIndex) +void RawModelCustom::ReadAnimationClipSingle(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int clipIndex) { #ifdef BOOST_LITTLE_ENDIAN Skeleton::Animation newAnimation; @@ -342,7 +343,7 @@ void RawModelCustom::ReadAnimationClipSingle(unsigned int &offset, char* fileDat #endif } -void RawModelCustom::ReadAnimationKeyFrame(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int nrOfJoints, Skeleton::Animation& animation) +void RawModelCustom::ReadAnimationKeyFrame(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int numberOfJoints, Skeleton::Animation& animation) { Skeleton::Animation::Keyframe newKeyFrame; @@ -358,12 +359,12 @@ void RawModelCustom::ReadAnimationKeyFrame(unsigned int &offset, char* fileData, newKeyFrame.Time = *(float*)(fileData + offset); offset += sizeof(float); - if (offset + sizeof(Skeleton::Animation::Keyframe::BoneProperty) * nrOfJoints> fileByteSize) { + if (offset + sizeof(Skeleton::Animation::Keyframe::BoneProperty) * numberOfJoints> fileByteSize) { throw Resource::FailedLoadingException("Reading AnimationKeyFrame joints failed"); } Skeleton::Animation::Keyframe::BoneProperty newBone; - for (unsigned int i = 0; i < nrOfJoints; i++) { + for (unsigned int i = 0; i < numberOfJoints; i++) { memcpy(&newBone, (fileData + offset), sizeof(Skeleton::Animation::Keyframe::BoneProperty)); offset += sizeof(Skeleton::Animation::Keyframe::BoneProperty); newKeyFrame.BoneProperties[newBone.ID] = newBone; diff --git a/src/Engine/Rendering/RenderSystem.cpp b/src/Engine/Rendering/RenderSystem.cpp index 58bbd1ee..a0912a45 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,27 +31,41 @@ bool RenderSystem::OnSetCamera(Events::SetCamera& e) return true; } -void RenderSystem::fillModels(std::list>& jobs) +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>& opaqueJobs, std::list>& transparentJobs) { auto models = m_World->GetComponents("Model"); if (models == nullptr) { 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 +83,58 @@ 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 + )); + if(explosionEffectJob->Color.a != 1.f || explosionEffectJob->EndColor.a != 1.f || explosionEffectJob->DiffuseColor.a != 1.f) { + cModel["Transparent"] = true; + } + + if (cModel["Transparent"]) { + transparentJobs.push_back(explosionEffectJob); + } else { + opaqueJobs.push_back(explosionEffectJob); + } + } else { + std::shared_ptr modelJob = std::shared_ptr(new ModelJob( + model, + m_Camera, + modelMatrix, + matGroup, + cModel, + m_World, + fillColor, + fillPercentage + )); + if (modelJob->Color.a != 1.f || modelJob->DiffuseColor.a != 1.f) { + cModel["Transparent"] = true; + } + if (cModel["Transparent"]) { + transparentJobs.push_back(modelJob); + } else { + opaqueJobs.push_back(modelJob); + } + } } } } @@ -156,8 +219,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,12 +240,11 @@ void RenderSystem::Update(double dt) m_Camera->SetOrientation(Transform::AbsoluteOrientation(m_CurrentCamera)); } - //Only supports opaque geometry atm RenderScene scene; scene.Camera = m_Camera; scene.Viewport = Rectangle(1280, 720); - fillModels(scene.ForwardJobs); + fillModels(scene.OpaqueObjects, scene.TransparentObjects); fillPointLights(scene.PointLightJobs, m_World); fillDirectionalLights(scene.DirectionalLightJobs, m_World); fillText(scene.TextJobs, m_World); diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 4f687a99..bec86b4a 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -58,11 +58,24 @@ void Renderer::InitializeWindow() LOG_ERROR("GLEW: Initialization failed"); exit(EXIT_FAILURE); } + + int windowSize[2]; + glfwGetWindowSize(m_Window, &windowSize[0], &windowSize[1]); + m_ViewportSize = Rectangle(windowSize[0], windowSize[1]); } 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) @@ -98,6 +111,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"); @@ -133,14 +147,14 @@ PickData Renderer::Pick(glm::vec2 screenCoord) void Renderer::InitializeTextures() { m_ErrorTexture = ResourceManager::Load("Textures/Core/ErrorTexture.png"); - m_WhiteTexture = ResourceManager::Load("Textures/Core/Blank.png"); + m_WhiteTexture = ResourceManager::Load("Textures/Core/White.png"); } void Renderer::SortRenderJobsByDepth(RenderScene &scene) { //Sort all forward jobs so transparency is good. - scene.ForwardJobs.sort(Renderer::DepthSort); + scene.TransparentObjects.sort(Renderer::DepthSort); } void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) diff --git a/src/Engine/Rendering/ShaderProgram.cpp b/src/Engine/Rendering/ShaderProgram.cpp index f713cd03..9c26c15c 100644 --- a/src/Engine/Rendering/ShaderProgram.cpp +++ b/src/Engine/Rendering/ShaderProgram.cpp @@ -21,7 +21,7 @@ GLuint Shader::CompileShader(GLenum shaderType, std::string fileName) return 0; const GLchar* shaderFiles = shaderFile.c_str(); - const GLint length = shaderFile.length(); + const GLint length = static_cast(shaderFile.length()); glShaderSource(shader, 1, &shaderFiles, &length); if (GLERROR("glShaderSource")) return 0; diff --git a/src/Engine/Rendering/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index cebabb67..851408a4 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -53,11 +53,11 @@ std::vector Skeleton::GetFrameBones(const Animation& animation, doubl const Animation::Keyframe& currentFrame = animation.Keyframes[currentKeyframeIndex]; const Animation::Keyframe& nextFrame = animation.Keyframes[(currentKeyframeIndex + 1) % animation.Keyframes.size()]; - float alpha = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + double alpha = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); //auto animationFrame = Animations[""].Keyframes[frame]; std::map frameBones; - AccumulateBoneTransforms(noRootMotion, currentFrame, nextFrame, alpha, frameBones, RootBone, glm::mat4(1)); + AccumulateBoneTransforms(noRootMotion, currentFrame, nextFrame, static_cast(alpha), frameBones, RootBone, glm::mat4(1)); std::vector finalMatrices; for (auto &kv : frameBones) { diff --git a/src/Engine/Sound/SoundSystem.cpp b/src/Engine/Sound/SoundSystem.cpp index a55c1fee..cd83d9c6 100644 --- a/src/Engine/Sound/SoundSystem.cpp +++ b/src/Engine/Sound/SoundSystem.cpp @@ -116,7 +116,11 @@ void SoundSystem::updateEmitters(double dt) setSourcePos(it->second->ALsource, nextPos); setSourceVel(it->second->ALsource, velocity); float gain; - (bool)(it->second->Type) ? gain = m_SFXVolumeChannel : gain = m_BGMVolumeChannel; + if (it->second->Type == SoundType::SFX) { + gain = m_SFXVolumeChannel; + } else if (it->second->Type == SoundType::BGM) { + gain = m_BGMVolumeChannel; + } auto emitter = m_World->GetComponent(it->first, "SoundEmitter"); setSoundProperties(it->second->ALsource, &emitter); diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 7ce66710..c26510ec 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" @@ -10,6 +11,9 @@ #include "Core/EntityFileWriter.h" #include "Game/Systems/CapturePointSystem.h" #include "Game/Systems/WeaponSystem.h" +#include "Game/Systems/PlayerHUD.h" +#include "Game/Systems/LifetimeSystem.h" +#include "../Engine/Rendering/AnimationSystem.h" Game::Game(int argc, char* argv[]) { @@ -39,7 +43,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(); @@ -69,29 +73,36 @@ 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_OctreeTrigger = 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_OctreeCollision, "Collidable"); + m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeTrigger, "Player"); + m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); + // Collision and TriggerSystem should update after player. ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); - m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); + m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeTrigger); ++updateOrderLevel; - m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_RenderFrame); ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_RenderFrame); @@ -114,6 +125,7 @@ Game::~Game() delete m_SoundSystem; delete m_OctreeFrustrumCulling; delete m_OctreeCollision; + delete m_OctreeTrigger; delete m_World; delete m_FrameStack; delete m_InputProxy; diff --git a/src/Game/Systems/CapturePointSystem.cpp b/src/Game/Systems/CapturePointSystem.cpp index fbd20e38..d26dde5f 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,21 +55,21 @@ 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 std::map nextPossibleCapturePoint; nextPossibleCapturePoint["Red"] = -1; nextPossibleCapturePoint["Blue"] = -1; - for (size_t i = 0; i < m_NumberOfCapturePoints; i++) + for (int 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; } @@ -93,9 +93,9 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper //reset timers and reset the bool that triggers this if (m_ResetTimers) { - for (size_t i = 0; i < m_NumberOfCapturePoints; i++) + for (int 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,35 @@ 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); + //check if its really a player that has triggered the touch + 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 +170,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..72900d7a 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); @@ -73,20 +76,51 @@ void PlayerMovementSystem::Update(double dt) ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity)); } - if (controller->Jumping() && !controller->Crouching() && velocity.y == 0.f) { + if (controller->Jumping() && !controller->Crouching() && (velocity.y == 0.f || !controller->DoubleJumping())) { + if (velocity.y == 0.f) { + controller->SetDoubleJumping(false); + } + else { + controller->SetDoubleJumping(true); + } 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..7a0a13c9 100644 --- a/src/Game/Systems/SpawnerSystem.cpp +++ b/src/Game/Systems/SpawnerSystem.cpp @@ -30,7 +30,7 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent / if (spawnPoints.size() > 1) { static std::random_device randomDevice; static std::mt19937 randomGenerator(randomDevice()); - std::uniform_int_distribution<> distribution(0, std::distance(spawnPoints.begin(), spawnPoints.end()) - 1); + std::uniform_int_distribution<> distribution(0, static_cast(std::distance(spawnPoints.begin(), spawnPoints.end())) - 1); auto randomSpawnPointIt = spawnPoints.begin(); std::advance(randomSpawnPointIt, distribution(randomGenerator)); spawnPoint = *randomSpawnPointIt; @@ -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 f72fd7dd..1613cb7a 100644 --- a/src/Game/Systems/WeaponSystem.cpp +++ b/src/Game/Systems/WeaponSystem.cpp @@ -37,17 +37,74 @@ 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 - Rectangle screenResolution = m_Renderer->Resolution(); + // 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); // TODO: check if player has enough ammo and if weapon has a cooldown or not