diff --git a/.gitignore b/.gitignore index 0df2db42..23056510 100755 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ tools/MayaExporter/x64/Debug/ tools/MayaExporter/MayaExporter/Debug/ tools/MayaExporter/MayaExporter/GeneratedFiles/ + +tools/MayaExporter/MayaExporter/x64/* +tools/MayaExporter/x64/* diff --git a/assets b/assets index c4898d82..8ffd0a99 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c4898d8281b5584d89b1caf14dab8e5fac120321 +Subproject commit 8ffd0a99b9a2e5c140307d382a25c4a470cc8f33 diff --git a/deps b/deps index bf83f099..ed45883a 160000 --- a/deps +++ b/deps @@ -1 +1 @@ -Subproject commit bf83f099ba16f0a87f9bebe8cfc5fd4e59fee805 +Subproject commit ed45883a444c6de548b6211a83a079ff2ecfce15 diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 6e4858b2..c3759393 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -64,7 +64,7 @@ bool RayVsModel(const Ray& ray, float& outVCoord); bool AABBvsTriangles(const AABB& box, - const std::vector& modelVertices, + const RawModel::Vertex* modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& boxVelocity, @@ -79,7 +79,8 @@ bool AABBVsAABB(const AABB& a, const AABB& b); bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation); // Calculates an absolute AABB from an entity AABB component -boost::optional EntityAbsoluteAABB(EntityWrapper& entity); +boost::optional EntityAbsoluteAABB(EntityWrapper& entity, bool takeModelBox = false); +boost::optional AbsoluteAABBExplosionEffect(EntityWrapper& entity); } diff --git a/include/Engine/Collision/CollisionSystem.h b/include/Engine/Collision/CollisionSystem.h index f3a7e4fe..c963e6b8 100644 --- a/include/Engine/Collision/CollisionSystem.h +++ b/include/Engine/Collision/CollisionSystem.h @@ -13,8 +13,8 @@ class CollisionSystem : public PureSystem { public: - CollisionSystem(World* world, EventBroker* eventBroker, Octree* octree) - : System(world, eventBroker) + CollisionSystem(SystemParams params, Octree* octree) + : System(params) , PureSystem("Collidable") , m_Octree(octree) { } diff --git a/include/Engine/Collision/CollidableOctreeSystem.h b/include/Engine/Collision/FillFrustumOctreeSystem.h similarity index 51% rename from include/Engine/Collision/CollidableOctreeSystem.h rename to include/Engine/Collision/FillFrustumOctreeSystem.h index 0aa01d2e..430b4037 100644 --- a/include/Engine/Collision/CollidableOctreeSystem.h +++ b/include/Engine/Collision/FillFrustumOctreeSystem.h @@ -1,17 +1,17 @@ -#ifndef CollidableOctreeSystem_h__ -#define CollidableOctreeSystem_h__ +#ifndef FillFrustumOctreeSystem_h__ +#define FillFrustumOctreeSystem_h__ #include "../Core/System.h" #include "../Core/Octree.h" #include "Collision.h" #include "EntityAABB.h" -class CollidableOctreeSystem : public ImpureSystem, public PureSystem +class FillFrustumOctreeSystem : public ImpureSystem, public PureSystem { public: - CollidableOctreeSystem(World* world, EventBroker* eventBroker, Octree* octree, const std::string& componentType) - : System(world, eventBroker) - , PureSystem(componentType) + FillFrustumOctreeSystem(SystemParams params, Octree* octree) + : System(params) + , PureSystem("Model") , m_Octree(octree) { } diff --git a/include/Engine/Collision/FillOctreeSystem.h b/include/Engine/Collision/FillOctreeSystem.h new file mode 100644 index 00000000..9c75878b --- /dev/null +++ b/include/Engine/Collision/FillOctreeSystem.h @@ -0,0 +1,25 @@ +#ifndef FillOctreeSystem_h__ +#define FillOctreeSystem_h__ + +#include "../Core/System.h" +#include "../Core/Octree.h" +#include "Collision.h" +#include "EntityAABB.h" + +class FillOctreeSystem : public ImpureSystem, public PureSystem +{ +public: + FillOctreeSystem(SystemParams params, Octree* octree, const std::string& fillComponentType) + : System(params) + , PureSystem(fillComponentType) + , m_Octree(octree) + { } + + virtual void Update(double dt) override; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; + +private: + Octree* m_Octree; +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Collision/TriggerSystem.h b/include/Engine/Collision/TriggerSystem.h index fa322ddd..d71fad08 100644 --- a/include/Engine/Collision/TriggerSystem.h +++ b/include/Engine/Collision/TriggerSystem.h @@ -15,8 +15,8 @@ class AABB; class TriggerSystem : public PureSystem { public: - TriggerSystem(World* world, EventBroker* eventBroker, Octree* octree) - : System(world, eventBroker) + TriggerSystem(SystemParams params, Octree* octree) + : System(params) , PureSystem("Trigger") , m_Octree(octree) { diff --git a/include/Engine/Core/ComponentInfo.h b/include/Engine/Core/ComponentInfo.h index 49ed2a3f..d9799059 100644 --- a/include/Engine/Core/ComponentInfo.h +++ b/include/Engine/Core/ComponentInfo.h @@ -13,6 +13,7 @@ struct ComponentInfo unsigned int Allocation = 0; std::map FieldAnnotations; std::map> FieldEnumDefinitions; + bool NetworkReplicated = true; }; struct Field_t diff --git a/include/Engine/Core/ComponentWrapper.h b/include/Engine/Core/ComponentWrapper.h index df16dca9..0b9f7357 100644 --- a/include/Engine/Core/ComponentWrapper.h +++ b/include/Engine/Core/ComponentWrapper.h @@ -1,6 +1,7 @@ #ifndef ComponentWrapper_h__ #define ComponentWrapper_h__ +#include #include "../Common.h" #include "Entity.h" #include "ComponentInfo.h" @@ -81,6 +82,18 @@ struct ComponentWrapper SubscriptProxy operator[](std::string propertyName) { return SubscriptProxy(this, propertyName); } }; +// A component wrapper that "owns" its data through a shared pointer +struct SharedComponentWrapper : ComponentWrapper +{ + SharedComponentWrapper(const ComponentInfo& componentInfo, boost::shared_array data) + : ComponentWrapper(componentInfo, data.get()) + , m_DataReference(data) + { } + +private: + boost::shared_array m_DataReference; +}; + // TODO: Move this to Tests once entity importing is finished class ComponentWrapperFactory { diff --git a/include/Engine/Core/EntityFilePreprocessor.h b/include/Engine/Core/EntityFilePreprocessor.h index 3139169f..b46bd383 100644 --- a/include/Engine/Core/EntityFilePreprocessor.h +++ b/include/Engine/Core/EntityFilePreprocessor.h @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include diff --git a/include/Engine/Core/EntityWrapper.h b/include/Engine/Core/EntityWrapper.h index bf34b9be..b0e65d9e 100644 --- a/include/Engine/Core/EntityWrapper.h +++ b/include/Engine/Core/EntityWrapper.h @@ -25,11 +25,12 @@ struct EntityWrapper const std::string Name(); bool HasComponent(const std::string& componentType); + void AttachComponent(const char* componentName); EntityWrapper Parent(); EntityWrapper FirstChildByName(const std::string& name); EntityWrapper FirstParentWithComponent(const std::string& componentType); bool IsChildOf(EntityWrapper potentialParent); - bool Valid(); + bool Valid() const; ComponentWrapper operator[](const char* componentName); bool operator==(const EntityWrapper& e) const; diff --git a/include/Engine/Core/EventBroker.h b/include/Engine/Core/EventBroker.h index dc1babc0..20d3b60c 100644 --- a/include/Engine/Core/EventBroker.h +++ b/include/Engine/Core/EventBroker.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "../Common.h" #include "Event.h" @@ -107,7 +108,7 @@ private: typedef std::unordered_map ContextRelays_t; ContextRelays_t m_ContextRelays; std::vector m_RelaysToSubscribe; - std::vector> m_RelaysToUnsubscribe; + std::unordered_map> m_RelaysToUnsubscribe; typedef std::list>> EventQueue_t; std::shared_ptr m_EventQueueRead; diff --git a/include/Engine/Core/Frustum.h b/include/Engine/Core/Frustum.h new file mode 100644 index 00000000..c2d83b23 --- /dev/null +++ b/include/Engine/Core/Frustum.h @@ -0,0 +1,77 @@ +#ifndef Frustum_h__ +#define Frustum_h__ + +#include "../GLM.h" +#include "AABB.h" +#include + +//A frustum defined by 6 planes. +struct Frustum +{ + //Contains points P in: dot(normal, P) + d = 0 + struct Plane + { + glm::vec3 Normal; + float Distance; + }; + + enum class Output + { + Inside, + Outside, + Intersects + }; + Plane Planes[6]; + + Frustum() = default; + Frustum(glm::mat4x4 viewProjMatrix) + { + //Order: Right, left, top, bottom, far, near. + int sign = 1; + for (int i = 0; i < 6; ++i) { + sign = -sign; + int index = i / 2; + Plane& plane = Planes[i]; + plane.Normal.x = viewProjMatrix[0].w + sign * viewProjMatrix[0][index]; + plane.Normal.y = viewProjMatrix[1].w + sign * viewProjMatrix[1][index]; + plane.Normal.z = viewProjMatrix[2].w + sign * viewProjMatrix[2][index]; + plane.Distance = viewProjMatrix[3].w + sign * viewProjMatrix[3][index]; + float divByNormalLength = 1.0f / glm::length(plane.Normal); + plane.Normal *= divByNormalLength; + plane.Distance *= divByNormalLength; + } + } + + Output VsAABB(const AABB& box) const + { + const glm::vec3& maxCorner = box.MaxCorner(); + const glm::vec3& minCorner = box.MinCorner(); + bool completelyInside = true; + for (const Plane& p : Planes) { + bool anyWasInside = false; + bool anyWasOutside = false; + //If points are on both sides of the plane, we can stop. + for (int i = 0; i < 8 && (!anyWasInside || !anyWasOutside); ++i) { + std::bitset<3> bits(i); + glm::vec3 corner; + corner.x = bits.test(0) ? maxCorner.x : minCorner.x; + corner.y = bits.test(1) ? maxCorner.y : minCorner.y; + corner.z = bits.test(2) ? maxCorner.z : minCorner.z; + if (glm::dot(p.Normal, corner) > -p.Distance) { + anyWasInside = true; + } else { + anyWasOutside = true; + } + } + if (!anyWasInside) { + return Output::Outside; + } + if (anyWasOutside) { + completelyInside = false; + } + } + return completelyInside ? Output::Inside : Output::Intersects; + } +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Core/Octree.h b/include/Engine/Core/Octree.h index 907d5736..b011a518 100644 --- a/include/Engine/Core/Octree.h +++ b/include/Engine/Core/Octree.h @@ -5,9 +5,8 @@ #include "../Common.h" #include "AABB.h" - -//Fwd declarations. -class Ray; +#include "Frustum.h" +#include "Ray.h" namespace OctSpace { @@ -40,6 +39,8 @@ public: //The type Box must be AABB, or inherit from AABB. template void ObjectsInSameRegion(const Box& box, std::vector& outObjects); + //Get the objects that are inside the frustum, the objects are put in outObjects. + void ObjectsInFrustum(const Frustum& frustum, std::vector& outObjects); //Empty the tree of all objects, static and dynamic. void ClearObjects(); //Empty the tree of all dynamic objects. Static objects remain in the tree. @@ -97,6 +98,8 @@ struct Child void AddStaticObject(const AABB& box); template void ObjectsInSameRegion(const Box& box, std::vector& outObjects) const; + template + void ObjectsInFrustum(const Frustum& frustum, std::vector& outObjects, bool takeAllDontTest) const; void ClearObjects(); void ClearDynamicObjects(); bool RayCollides(const Ray& ray, Output& data) const; @@ -154,6 +157,13 @@ void Octree::ObjectsInSameRegion(const Box& box, std::vector& outObjects) m_Root->ObjectsInSameRegion(box, outObjects); } +template +void Octree::ObjectsInFrustum(const Frustum& frustum, std::vector& outObjects) +{ + falsifyObjectChecks(); + m_Root->ObjectsInFrustum(frustum, outObjects, false); +} + template void Octree::ClearObjects() { @@ -230,4 +240,46 @@ void OctSpace::Child::ObjectsInSameRegion(const Box& box, std::vector& outObj } } +template +void OctSpace::Child::ObjectsInFrustum(const Frustum& frustum, std::vector& outObjects, bool takeAllDontTest) const +{ + if (hasChildren()) { + for (const Child* c : m_Children) { + Frustum::Output out = Frustum::Output::Inside; + if (!takeAllDontTest) { + out = frustum.VsAABB(c->m_Box); + if (out == Frustum::Output::Outside) { + continue; + } + } + c->ObjectsInFrustum(frustum, outObjects, out == Frustum::Output::Inside); + } + } else { + size_t startIndex = outObjects.size(); + int numDuplicates = 0; + outObjects.resize(outObjects.size() + m_StaticObjIndices.size() + m_DynamicObjIndices.size()); + for (size_t i = 0; i < m_StaticObjIndices.size(); ++i) { + ContainedObject& obj = m_StaticObjectsRef[m_StaticObjIndices[i]]; + if (obj.Checked || frustum.VsAABB(*obj.Box) == Frustum::Output::Outside) { + ++numDuplicates; + } else { + obj.Checked = true; + outObjects[startIndex + i - numDuplicates] = *static_cast(obj.Box.get()); + } + } + for (size_t i = 0; i < m_DynamicObjIndices.size(); ++i) { + ContainedObject& obj = m_DynamicObjectsRef[m_DynamicObjIndices[i]]; + if (obj.Checked || frustum.VsAABB(*obj.Box) == Frustum::Output::Outside) { + ++numDuplicates; + } else { + obj.Checked = true; + outObjects[startIndex + i - numDuplicates] = *static_cast(obj.Box.get()); + } + } + for (size_t i = 0; i < numDuplicates; ++i) { + outObjects.pop_back(); + } + } +} + #endif \ No newline at end of file diff --git a/include/Engine/Core/System.h b/include/Engine/Core/System.h index ec57f5fc..1a387855 100644 --- a/include/Engine/Core/System.h +++ b/include/Engine/Core/System.h @@ -5,21 +5,55 @@ #include "World.h" #include "EntityWrapper.h" #include "ComponentWrapper.h" +#include "EPlayerSpawned.h" + +struct SystemParams +{ + SystemParams(::World* World, ::EventBroker* EventBroker, bool IsClient, bool IsServer) + : World(World) + , EventBroker(EventBroker) + , IsClient(IsClient) + , IsServer(IsServer) + { } + + ::World* World; + ::EventBroker* EventBroker; + bool IsClient = false; + bool IsServer = false; +}; class System { friend class SystemPipeline; protected: - System(World* world, EventBroker) { } - System(World* world, EventBroker* eventBroker) - : m_World(world) - , m_EventBroker(eventBroker) - { } + System(SystemParams params) + : m_World(params.World) + , m_EventBroker(params.EventBroker) + , IsClient(params.IsClient) + , IsServer(params.IsServer) + { + if (IsClient) { + EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &System::setLocalPlayer); + } + } virtual ~System() = default; World* m_World; EventBroker* m_EventBroker; + bool IsClient = false; + bool IsServer = false; + EntityWrapper LocalPlayer = EntityWrapper::Invalid; + +private: + EventRelay m_EPlayerSpawned; + virtual bool setLocalPlayer(Events::PlayerSpawned& e) + { + if (e.PlayerID == -1) { + LocalPlayer = e.Player; + } + return true; + } }; class PureSystem : public virtual System @@ -34,7 +68,7 @@ protected: const std::string m_ComponentType; - virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) = 0; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPlayer, double dt) = 0; }; class ImpureSystem : public virtual System diff --git a/include/Engine/Core/SystemPipeline.h b/include/Engine/Core/SystemPipeline.h index 90303f12..5f7aee0b 100644 --- a/include/Engine/Core/SystemPipeline.h +++ b/include/Engine/Core/SystemPipeline.h @@ -10,9 +10,11 @@ class SystemPipeline { public: - SystemPipeline(World* world, EventBroker* eventBroker) + SystemPipeline(World* world, EventBroker* eventBroker, bool isClient, bool isServer) : m_World(world) , m_EventBroker(eventBroker) + , m_IsClient(isClient) + , m_IsServer(isServer) { EVENT_SUBSCRIBE_MEMBER(m_EPause, &SystemPipeline::OnPause); EVENT_SUBSCRIBE_MEMBER(m_EResume, &SystemPipeline::OnResume); @@ -35,7 +37,7 @@ public: m_OrderedSystemGroups.resize(updateOrderLevel + 1); } UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel]; - System* system = new T(m_World, m_EventBroker, args...); + System* system = new T(SystemParams(m_World, m_EventBroker, m_IsClient, m_IsServer), args...); group.Systems[typeid(T).name()] = system; PureSystem* pureSystem = dynamic_cast(system); @@ -59,6 +61,9 @@ public: dt = 0.0; } + // Process utility events for the System base class + m_EventBroker->Process(); + for (UnorderedSystems& group : m_OrderedSystemGroups) { // Process events for (auto& pair : group.Systems) { @@ -88,6 +93,8 @@ public: private: World* m_World; EventBroker* m_EventBroker; + bool m_IsClient = false; + bool m_IsServer = false; bool m_Paused = false; struct UnorderedSystems diff --git a/include/Engine/Core/UniformScaleSystem.h b/include/Engine/Core/UniformScaleSystem.h index 0ebc0672..cd679fed 100644 --- a/include/Engine/Core/UniformScaleSystem.h +++ b/include/Engine/Core/UniformScaleSystem.h @@ -8,7 +8,7 @@ class UniformScaleSystem : public PureSystem { public: - UniformScaleSystem(World* world, EventBroker* eventBroker); + UniformScaleSystem(SystemParams params); virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) override; diff --git a/include/Engine/Core/Util/IfDebug.h b/include/Engine/Core/Util/IfDebug.h index 79cb3a4c..85b64c8d 100644 --- a/include/Engine/Core/Util/IfDebug.h +++ b/include/Engine/Core/Util/IfDebug.h @@ -4,7 +4,7 @@ // } // NOTE: condition statement is not executed at all in release mode. #ifndef DEBUG_IF -#ifndef DEBUG +#ifdef DEBUG #define DEBUG_IF(c) if(c) #else #define DEBUG_IF(c) if(false) diff --git a/include/Engine/Editor/EditorRenderSystem.h b/include/Engine/Editor/EditorRenderSystem.h index 361669ba..a42ad779 100644 --- a/include/Engine/Editor/EditorRenderSystem.h +++ b/include/Engine/Editor/EditorRenderSystem.h @@ -10,7 +10,7 @@ class EditorRenderSystem : public ImpureSystem { public: - EditorRenderSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame); + EditorRenderSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame); virtual void Update(double dt) override; diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index accf66e4..fcaa2e47 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -17,7 +17,7 @@ class EditorSystem : public ImpureSystem { public: - EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame); + EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame); ~EditorSystem(); void Update(double dt); diff --git a/include/Engine/Editor/EditorWidgetSystem.h b/include/Engine/Editor/EditorWidgetSystem.h index a060bdd5..57e653d6 100644 --- a/include/Engine/Editor/EditorWidgetSystem.h +++ b/include/Engine/Editor/EditorWidgetSystem.h @@ -25,7 +25,7 @@ struct WidgetDelta : Event class EditorWidgetSystem : public ImpureSystem, PureSystem { public: - EditorWidgetSystem(World* world, EventBroker* eventBroker, IRenderer* renderer); + EditorWidgetSystem(SystemParams params, IRenderer* renderer); virtual void Update(double dt) override; virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cEditorWidget, double dt) override; diff --git a/include/Engine/GUI/TextureFrame.h b/include/Engine/GUI/TextureFrame.h index 2c6d34dd..77967b4d 100644 --- a/include/Engine/GUI/TextureFrame.h +++ b/include/Engine/GUI/TextureFrame.h @@ -3,6 +3,7 @@ #include "Frame.h" #include "../Rendering/Texture.h" +#include "../Rendering/Util/CommonFunctions.h" namespace GUI { @@ -55,10 +56,10 @@ public: return; } - m_Texture = ResourceManager::Load(resourceName); + m_Texture = CommonFunctions::LoadTexture(resourceName, false); m_TextureName = resourceName; if (m_Texture == nullptr) { - m_Texture = ResourceManager::Load("Textures/Core/ErrorTexture.png"); + m_Texture = CommonFunctions::LoadTexture("Textures/Core/ErrorTexture.png", false); } SizeToTexture(); diff --git a/include/Engine/Input/FirstPersonInputController.h b/include/Engine/Input/FirstPersonInputController.h index 2bbd768d..5529185a 100644 --- a/include/Engine/Input/FirstPersonInputController.h +++ b/include/Engine/Input/FirstPersonInputController.h @@ -4,6 +4,7 @@ #include "../GLM.h" #include "../Core/InputController.h" #include "../Core/ELockMouse.h" +#include "../Game/Events/EDashAbility.h" #include "InputHandler.h" template @@ -54,6 +55,7 @@ protected: //specialabilitys bool m_MovementKeyDown = false; bool m_SpecialAbilityKeyDown = false; + int m_NumberOfMovementKeysDown = 0; EventRelay m_ELockMouse; bool OnLockMouse(const Events::LockMouse& e); @@ -131,6 +133,7 @@ bool FirstPersonInputController::OnCommand(const Events::InputComm } //if value = 0 then you have just released this key if (e.Value != 0) { + m_NumberOfMovementKeysDown++; m_MovementKeyDown = true; //if you pressed the same key within m_AssaultDashDoubleTapSensitivityTimer then you have doubletapped it if (m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer && m_AssaultDashTapDirection == m_CurrentDirectionVector) { @@ -138,10 +141,14 @@ bool FirstPersonInputController::OnCommand(const Events::InputComm } } else { //== 0 - m_MovementKeyDown = false; - //you have just released the key, store what key it was and reset the doubletap-sensitivity-timer - m_AssaultDashTapDirection = m_CurrentDirectionVector; - m_AssaultDashDoubleTapDeltaTime = 0.f; + m_NumberOfMovementKeysDown--; + if (m_NumberOfMovementKeysDown == 0) { + m_MovementKeyDown = false; + } + //you have just released the key, store what key it was and reset the doubletap-sensitivity-timer + m_AssaultDashTapDirection = m_CurrentDirectionVector; + m_AssaultDashDoubleTapDeltaTime = 0.f; + } } @@ -201,12 +208,6 @@ void FirstPersonInputController::AssaultDashCheck(double dt, bool m_AssaultDashCoolDownTimer = assaultDashCoolDownMaxTimer; m_AssaultDashDoubleTapped = true; m_AssaultDashDoubleTapDeltaTime = 0.f; - //moving to the side has priority - return; - } - - //dashing with doubletap - check if doubletap to dash enabled - if (ResourceManager::Load("Input.ini")->Get("Keyboard.DoubleTapToDash", false)) { return; } @@ -215,6 +216,11 @@ void FirstPersonInputController::AssaultDashCheck(double dt, bool m_AssaultDashDoubleTapped = false; } + //dashing with doubletap - check if doubletap to dash enabled + if (!ResourceManager::Load("Input.ini")->Get("Keyboard.DoubleTapToDash", false)) { + return; + } + //check if we have received a valid doubletap if (!m_ValidDoubleTap) { return; @@ -230,6 +236,9 @@ void FirstPersonInputController::AssaultDashCheck(double dt, bool m_AssaultDashDoubleTapped = true; m_AssaultDashDoubleTapDeltaTime = 0.f; m_AssaultDashCoolDownTimer = assaultDashCoolDownMaxTimer; + + Events::DashAbility e; + m_EventBroker->Publish(e); } #endif \ No newline at end of file diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 7d1d5bba..fb367874 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -20,16 +20,22 @@ #include "Input/EInputCommand.h" #include "Core/EPlayerDamage.h" #include "Network/EInterpolate.h" +#include "Network/SnapshotFilter.h" #include "Core/EPlayerSpawned.h" class Client : public Network { public: - Client(ConfigFile* config); + Client(World* world, EventBroker* eventBroker); + Client(World* world, EventBroker* eventBroker, std::unique_ptr snapshotFilter); ~Client(); - void Start(World* world, EventBroker* eventBroker) override; + + void Connect(std::string address, int port); void Update() override; + private: + std::unique_ptr m_SnapshotFilter = nullptr; + // Assio UDP logic boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; @@ -45,10 +51,8 @@ private: PacketID m_SendPacketID = 0; // Game logic - World* m_World; std::string m_PlayerName; PlayerID m_PlayerID = -1; - EntityID m_ServerEntityID = std::numeric_limits::max(); bool m_IsConnected = false; EntityWrapper m_LocalPlayer = EntityWrapper::Invalid; // Server Client Lookup map @@ -74,7 +78,9 @@ private: void connect(); void disconnect(); void parseMessageType(Packet& packet); - void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType); + void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID); + SharedComponentWrapper createSharedComponent(Packet& packet, EntityID entityID, const ComponentInfo& componentInfo); + void ignoreFields(Packet& packet, const ComponentInfo& componentInfo); void parseConnect(Packet& packet); void parsePlayerConnected(Packet& packet); void parsePing(); @@ -99,7 +105,6 @@ private: void deleteFromServerClientMaps(EntityID serverEntityID, EntityID clientEntityID); // Events - EventBroker* m_EventBroker; EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); EventRelay m_EPlayerDamage; diff --git a/include/Engine/Network/EInterpolate.h b/include/Engine/Network/EInterpolate.h index 93bf1a5c..79af840d 100644 --- a/include/Engine/Network/EInterpolate.h +++ b/include/Engine/Network/EInterpolate.h @@ -11,8 +11,13 @@ namespace Events struct Interpolate : Event { - EntityID Entity; - boost::shared_array DataArray; + Interpolate(EntityWrapper Entity, SharedComponentWrapper Component) + : Entity(Entity) + , Component(Component) + { } + + EntityWrapper Entity; + SharedComponentWrapper Component; }; } diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h index 874e3377..0dbc4915 100644 --- a/include/Engine/Network/Network.h +++ b/include/Engine/Network/Network.h @@ -19,10 +19,15 @@ typedef unsigned int PacketID; class Network { public: + Network(World* world, EventBroker* eventBroker); virtual ~Network() { }; - virtual void Start(World* m_world, EventBroker *eventBroker) = 0; + virtual void Update() = 0; + protected: + World* m_World; + EventBroker* m_EventBroker; + // For Debug bool isReadingData = false; NetworkData m_NetworkData; @@ -32,7 +37,6 @@ protected: double m_TimeoutMs; void saveToFile(); void updateNetworkData(); - void initialize(); }; #endif \ No newline at end of file diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 90b9e922..f16c6c16 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -22,15 +22,17 @@ class Server : public Network { public: - Server(); + Server(World* world, EventBroker* eventBroker, int port); ~Server(); - void Start(World* m_world, EventBroker *eventBroker) override; + void Update() override; + private: + int m_Port = 27666; // UDP logic boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::io_service m_IOService; - boost::asio::ip::udp::socket m_Socket; + std::unique_ptr m_Socket; // Sending messages to client logic std::map m_ConnectedPlayers; @@ -46,13 +48,10 @@ private: float snapshotInterval; int checkTimeOutInterval = 100; int m_NextPlayerID = 0; + std::vector m_InputCommandsToBroadcast; //Timers std::clock_t m_StartPingTime; - - // Game logic - World* m_World; - EventBroker* m_EventBroker; // Packet loss logic PacketID m_PacketID = 0; @@ -66,6 +65,7 @@ private: void broadcast(Packet& packet); void sendSnapshot(); void addChildrenToPacket(Packet& packet, EntityID entityID); + void addInputCommandsToPacket(Packet& packet); void sendPing(); void checkForTimeOuts(); void disconnect(PlayerID playerID); diff --git a/include/Engine/Network/SnapshotFilter.h b/include/Engine/Network/SnapshotFilter.h new file mode 100644 index 00000000..4e63c4b1 --- /dev/null +++ b/include/Engine/Network/SnapshotFilter.h @@ -0,0 +1,19 @@ +#ifndef SnapshotFilter_h__ +#define SnapshotFilter_h__ + +#include "../Core/EntityWrapper.h" +#include "../Core/ComponentWrapper.h" + +class SnapshotFilter +{ +public: + // Filters an incoming snapshot. + // Modify the component and return true if the component snapshot should be applied. + // Otherwise return false and it will be ignored. + virtual bool FilterComponent(EntityWrapper entity, SharedComponentWrapper& component) + { + return true; + } +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/AnimationSystem.h b/include/Engine/Rendering/AnimationSystem.h index fcdcbc92..dbe4b3fc 100644 --- a/include/Engine/Rendering/AnimationSystem.h +++ b/include/Engine/Rendering/AnimationSystem.h @@ -9,12 +9,13 @@ #include "Rendering/Model.h" #include "Rendering/EAnimationComplete.h" #include "Rendering/Skeleton.h" +#include class AnimationSystem : public PureSystem { public: - AnimationSystem(World* world, EventBroker* eventBroker) - : System(world, eventBroker) + AnimationSystem(SystemParams params) + : System(params) , PureSystem("Animation") { @@ -23,7 +24,6 @@ public: virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt) override; private: - }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/BoneAttachmentSystem.h b/include/Engine/Rendering/BoneAttachmentSystem.h new file mode 100644 index 00000000..55c2a1c8 --- /dev/null +++ b/include/Engine/Rendering/BoneAttachmentSystem.h @@ -0,0 +1,29 @@ +#ifndef BoneAttachmentSystem_h__ +#define BoneAttachmentSystem_h__ + +#include "GLM.h" + +#include "Common.h" +#include "Core/System.h" +#include "Core/ResourceManager.h" +#include "Rendering/Model.h" +#include "Rendering/Skeleton.h" + +//Needs to be a higher orderlevel than AnimationSystem +class BoneAttachmentSystem : public PureSystem +{ +public: + BoneAttachmentSystem(SystemParams params) + : System(params) + , PureSystem("BoneAttachment") + { + + } + ~BoneAttachmentSystem() { } + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& BoneAttachmentComponent, double dt) override; +private: + + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/DrawColorCorrectionPass.h b/include/Engine/Rendering/DrawColorCorrectionPass.h index fcde73d7..231e2d33 100644 --- a/include/Engine/Rendering/DrawColorCorrectionPass.h +++ b/include/Engine/Rendering/DrawColorCorrectionPass.h @@ -17,7 +17,7 @@ public: void InitializeFrameBuffers(); void InitializeShaderPrograms(); - void Draw(GLuint sceneTexture, GLuint bloomTexture, GLfloat gamma, GLfloat exposure); + void Draw(GLuint sceneTexture, GLuint bloomTexture, GLuint sceneTextureLowRes, GLuint bloomTextureLowRes, GLfloat gamma, GLfloat exposure); private: const IRenderer* m_Renderer; diff --git a/include/Engine/Rendering/DrawFinalPass.h b/include/Engine/Rendering/DrawFinalPass.h index 867ec844..bf8d4d76 100644 --- a/include/Engine/Rendering/DrawFinalPass.h +++ b/include/Engine/Rendering/DrawFinalPass.h @@ -7,6 +7,7 @@ #include "FrameBuffer.h" #include "ShaderProgram.h" #include "Util/UnorderedMapVec2.h" +#include "Util/CommonFunctions.h" #include "Texture.h" class DrawFinalPass @@ -22,39 +23,67 @@ public: //Return the texture that is used in later stages to apply the bloom effect GLuint BloomTexture() const { return m_BloomTexture; } + GLuint BloomTextureLowRes() const { return m_BloomTextureLowRes; } //Return the texture with diffuse and lighting of the scene. GLuint SceneTexture() const { return m_SceneTexture; } + GLuint SceneTextureLowRes() const { return m_SceneTextureLowRes; } + //Return the framebuffer used in the scene rendering stage. FrameBuffer* FinalPassFrameBuffer() { return &m_FinalPassFrameBuffer; } + FrameBuffer* FinalPassFrameBufferLowRes() { return &m_FinalPassFrameBufferLowRes; } 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 DrawSprites(std::list>&jobs, RenderScene& scene); + void DrawModelRenderQueues(std::list>& jobs, RenderScene& scene); + void DrawShieldToStencilBuffer(std::list>& jobs, RenderScene& scene); + void DrawShieldedModelRenderQueue(std::list>& jobs, RenderScene& scene); + void DrawToDepthBuffer(std::list>& jobs, 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); + void BindExplosionTextures(GLuint shaderHandle, std::shared_ptr& job); + void BindModelTextures(GLuint shaderHandle, std::shared_ptr& job); Texture* m_WhiteTexture; Texture* m_BlackTexture; Texture* m_NeutralNormalTexture; Texture* m_GreyTexture; + Texture* m_ErrorTexture; FrameBuffer m_FinalPassFrameBuffer; + FrameBuffer m_FinalPassFrameBufferLowRes; GLuint m_BloomTexture; GLuint m_SceneTexture; + GLuint m_BloomTextureLowRes; + GLuint m_SceneTextureLowRes; GLuint m_DepthBuffer; + GLuint m_DepthBufferLowRes; + + //maqke this component based i guess? + GLuint m_ShieldPixelRate = 16; const IRenderer* m_Renderer; const LightCullingPass* m_LightCullingPass; ShaderProgram* m_ForwardPlusProgram; ShaderProgram* m_ExplosionEffectProgram; + ShaderProgram* m_ExplosionEffectSplatMapProgram; ShaderProgram* m_SpriteProgram; + ShaderProgram* m_ForwardPlusSplatMapProgram; + ShaderProgram* m_ShieldToStencilProgram; + ShaderProgram* m_FillDepthBufferProgram; + + + ShaderProgram* m_ForwardPlusSkinnedProgram; + ShaderProgram* m_ExplosionEffectSkinnedProgram; + ShaderProgram* m_ExplosionEffectSplatMapSkinnedProgram; + ShaderProgram* m_ForwardPlusSplatMapSkinnedProgram; + ShaderProgram* m_ShieldToStencilSkinnedProgram; + ShaderProgram* m_FillDepthBufferSkinnedProgram; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/DrawFinalPassState.h b/include/Engine/Rendering/DrawFinalPassState.h index 10b840e9..91fc4cf4 100644 --- a/include/Engine/Rendering/DrawFinalPassState.h +++ b/include/Engine/Rendering/DrawFinalPassState.h @@ -12,4 +12,11 @@ private: }; +class DrawStencilState : public RenderState +{ +public: + DrawStencilState(GLuint frameBuffer); + ~DrawStencilState(); +}; + #endif \ No newline at end of file diff --git a/include/Engine/Rendering/ExplosionEffectJob.h b/include/Engine/Rendering/ExplosionEffectJob.h index 89b1342b..8f339526 100644 --- a/include/Engine/Rendering/ExplosionEffectJob.h +++ b/include/Engine/Rendering/ExplosionEffectJob.h @@ -15,7 +15,7 @@ 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) + ExplosionEffectJob(ComponentWrapper explosionEffectComponent, ::Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialProperties matGroup, ComponentWrapper modelComponent, ::World* world, glm::vec4 fillColor, float fillPercentage) : ModelJob(model, camera, matrix, matGroup, modelComponent, world, fillColor, fillPercentage) { ExplosionOrigin = (glm::vec3)explosionEffectComponent["ExplosionOrigin"]; diff --git a/include/Engine/Rendering/IRenderer.h b/include/Engine/Rendering/IRenderer.h index b399aefa..4441bb7d 100644 --- a/include/Engine/Rendering/IRenderer.h +++ b/include/Engine/Rendering/IRenderer.h @@ -32,6 +32,8 @@ public: virtual void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; } bool VSYNC() const { return m_VSYNC; } virtual void SetVSYNC(bool vsync) { m_VSYNC = vsync; } + std::string WindowTitle() const { return m_WindowTitle; } + virtual void SetWindowTitle(const std::string& title) { glfwSetWindowTitle(m_Window, title.c_str()); m_WindowTitle = title; } //Returns screen size excluding window border and header Rectangle GetViewportSize() const { return m_ViewportSize; } virtual void Initialize() = 0; @@ -47,6 +49,7 @@ protected: int m_GLVersion[2]; std::string m_GLVendor; GLFWwindow* m_Window = nullptr; + std::string m_WindowTitle; }; #endif // Renderer_h__ diff --git a/include/Engine/Rendering/Model.h b/include/Engine/Rendering/Model.h index f751a8cc..4c63b922 100644 --- a/include/Engine/Rendering/Model.h +++ b/include/Engine/Rendering/Model.h @@ -2,8 +2,10 @@ #define Model_h__ #include "Rendering/RawModelCustom.h" +#include "Util/CommonFunctions.h" //#include "Rendering/RawModelAssimp.h" #include "../OpenGL.h" +#include "Core/AABB.h" class Model : public ThreadUnsafeResource { @@ -14,16 +16,19 @@ private: public: ~Model(); - const std::vector& MaterialGroups() const { return m_RawModel->MaterialGroups; } + const std::vector& MaterialGroups() const { return m_RawModel->m_Materials; } const glm::mat4& Matrix() const { return m_RawModel->m_Matrix; } - const std::vector& Vertices() const { return m_RawModel->m_Vertices; } - + const RawModel::Vertex* Vertices() const { return m_RawModel->Vertices(); } + unsigned int NumberOfVertices() const { return m_RawModel->NumVertices(); } + const AABB& Box() const { return m_Box; } + bool IsSkinned() const { return m_RawModel->IsSkinned(); } GLuint VAO; GLuint ElementBuffer; RawModel* m_RawModel; private: - + AABB m_Box; + GLuint VertexBuffer; GLuint NormalBuffer; GLuint TangentNormalsBuffer; diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index 2cb2169c..4bb1b51f 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -14,39 +14,98 @@ #include "../Core/World.h" #include "../Core/Transform.h" #include "Skeleton.h" +#include "ShaderProgram.h" struct ModelJob : RenderJob { - ModelJob(Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialGroup matGroup, ComponentWrapper modelComponent, World* world, glm::vec4 fillColor, float fillPercentage) + ModelJob(Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialProperties matProp, ComponentWrapper modelComponent, World* world, glm::vec4 fillColor, float fillPercentage) : RenderJob() { Model = model; - TextureID = (matGroup.Texture) ? matGroup.Texture->ResourceID : 0; - 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; - StartIndex = matGroup.StartIndex; - EndIndex = matGroup.EndIndex; + ModelID = model->ResourceID; + Type = matProp.type; + ::RawModel::MaterialBasic* matGroup = matProp.material; + switch(matProp.type){ + case ::RawModel::MaterialType::Basic: + if (Model->IsSkinned()) { + ShaderID = ResourceManager::Load("#ForwardPlusSkinnedProgram")->ResourceID; + } + else { + ShaderID = ResourceManager::Load("#ForwardPlusProgram")->ResourceID; + } + TextureID = 0; + break; + case ::RawModel::MaterialType::SingleTextures: + { + if (Model->IsSkinned()) { + ShaderID = ResourceManager::Load("#ForwardPlusSkinnedProgram")->ResourceID; + } + else { + ShaderID = ResourceManager::Load("#ForwardPlusProgram")->ResourceID; + } + ::RawModel::MaterialSingleTextures* singleTextures = static_cast<::RawModel::MaterialSingleTextures*>(matProp.material); + TextureID = (singleTextures->ColorMap.Texture) ? singleTextures->ColorMap.Texture->ResourceID : 0; + if (modelComponent["DiffuseTexture"]) { + DiffuseTexture.push_back(&singleTextures->ColorMap); + } + + if (modelComponent["NormalMap"]) { + NormalTexture.push_back(&singleTextures->NormalMap); + } + + if (modelComponent["SpecularMap"]) { + SpecularTexture.push_back(&singleTextures->SpecularMap); + } + + if (modelComponent["GlowMap"]) { + IncandescenceTexture.push_back(&singleTextures->IncandescenceMap); + } + } + break; + case ::RawModel::MaterialType::SplatMapping: + { + if (Model->IsSkinned()) { + ShaderID = ResourceManager::Load("#ForwardPlusSplatMapSkinnedProgram")->ResourceID; + } + else { + ShaderID = ResourceManager::Load("#ForwardPlusSplatMapProgram")->ResourceID; + } + ::RawModel::MaterialSplatMapping* SplatTextures = static_cast<::RawModel::MaterialSplatMapping*>(matProp.material); + + SplatMap = &SplatTextures->SplatMap; + + TextureID = (SplatTextures->ColorMaps[0].Texture) ? SplatTextures->ColorMaps[0].Texture->ResourceID : 0; + if (modelComponent["DiffuseTexture"]) { + for (auto& texture : SplatTextures->ColorMaps) { + DiffuseTexture.push_back(&texture); + } + } + + if (modelComponent["NormalMap"]) { + for (auto& texture : SplatTextures->NormalMaps) { + NormalTexture.push_back(&texture); + } + } + + if (modelComponent["SpecularMap"]) { + for (auto& texture : SplatTextures->SpecularMaps) { + SpecularTexture.push_back(&texture); + } + } + + if (modelComponent["GlowMap"]) { + for (auto& texture : SplatTextures->IncandescenceMaps) { + IncandescenceTexture.push_back(&texture); + } + } + } + break; + } + DiffuseColor = matGroup->DiffuseColor; + SpecularColor = matGroup->SpecularColor; + IncandescenceColor = matGroup->IncandescenceColor; + StartIndex = matGroup->StartIndex; + EndIndex = matGroup->EndIndex; Matrix = matrix; Color = modelComponent["Color"]; Entity = modelComponent.EntityID; @@ -57,31 +116,34 @@ struct ModelJob : RenderJob 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"]; + + if (model->IsSkinned()) { + Skeleton = Model->m_RawModel->m_Skeleton; } + }; unsigned int TextureID; unsigned int ShaderID; + unsigned int ModelID; + ::RawModel::MaterialType Type; EntityID Entity; glm::mat4 Matrix; - const Texture* DiffuseTexture; - const Texture* NormalTexture; - const Texture* SpecularTexture; - const Texture* IncandescenceTexture; + const ::RawModel::TextureProperties* SplatMap; + std::vector DiffuseTexture; + std::vector NormalTexture; + std::vector SpecularTexture; + std::vector IncandescenceTexture; float Shininess = 0.f; glm::vec4 Color; const ::Model* Model = nullptr; ::Skeleton* Skeleton = nullptr; - const ::Skeleton::Animation* Animation = nullptr; + // const ::Skeleton::Animation* Animation = nullptr; + + - float AnimationTime = 0.f; glm::vec4 DiffuseColor; glm::vec4 SpecularColor; @@ -95,7 +157,7 @@ struct ModelJob : RenderJob void CalculateHash() override { - Hash = TextureID; + Hash = TextureID + ModelID << 10 + ShaderID << 20; } }; diff --git a/include/Engine/Rendering/PNG.h b/include/Engine/Rendering/PNG.h index f2cbf157..a45e9e7c 100644 --- a/include/Engine/Rendering/PNG.h +++ b/include/Engine/Rendering/PNG.h @@ -6,9 +6,10 @@ #include #include "../Common.h" +#include "../Core/ResourceManager.h" #include "Image.h" -class PNG : public Image +class PNG : public Image, public Resource { public: PNG(std::string path); diff --git a/include/Engine/Rendering/PickingPass.h b/include/Engine/Rendering/PickingPass.h index da3ed31b..2ce2e78d 100644 --- a/include/Engine/Rendering/PickingPass.h +++ b/include/Engine/Rendering/PickingPass.h @@ -40,6 +40,7 @@ private: const IRenderer* m_Renderer; ShaderProgram* m_PickingProgram; + ShaderProgram* m_PickingSkinnedProgram; Camera* m_Camera; struct PickingInfo diff --git a/include/Engine/Rendering/RawModelCustom.h b/include/Engine/Rendering/RawModelCustom.h index e903f49f..ebf8da2b 100644 --- a/include/Engine/Rendering/RawModelCustom.h +++ b/include/Engine/Rendering/RawModelCustom.h @@ -33,18 +33,27 @@ protected: public: ~RawModelCustom(); - struct Vertex - { - glm::vec3 Position; - glm::vec3 Normal; - glm::vec3 Tangent; - glm::vec3 BiNormal; - glm::vec2 TextureCoords; + struct Vertex + { + glm::vec3 Position; + glm::vec3 Normal; + glm::vec3 Tangent; + glm::vec3 BiNormal; + glm::vec2 TextureCoords; + }; + + struct SkinedVertex : public Vertex { glm::vec4 BoneIndices; glm::vec4 BoneWeights; }; - struct MaterialGroup + struct TextureProperties { + std::string TexturePath; + glm::vec2 UVRepeat; + Texture* Texture; + }; + + struct MaterialBasic { float SpecularExponent; float ReflectionFactor; @@ -54,25 +63,69 @@ public: unsigned int StartIndex; unsigned int EndIndex; //float Transparency; - std::string TexturePath; - std::shared_ptr<::Texture> Texture; - std::string NormalMapPath; - std::shared_ptr<::Texture> NormalMap; - std::string SpecularMapPath; - std::shared_ptr<::Texture> SpecularMap; - std::string IncandescenceMapPath; - std::shared_ptr<::Texture> IncandescenceMap; }; - std::vector MaterialGroups; + struct MaterialSplatMapping : public MaterialBasic + { + TextureProperties SplatMap; + std::vector ColorMaps; + std::vector NormalMaps; + std::vector SpecularMaps; + std::vector IncandescenceMaps; + }; + + struct MaterialSingleTextures : public MaterialBasic + { + TextureProperties ColorMap; + TextureProperties NormalMap; + TextureProperties SpecularMap; + TextureProperties IncandescenceMap; + }; + + enum class MaterialType { Basic = 1, SplatMapping, SingleTextures }; + + struct MaterialProperties { + MaterialType type; + MaterialBasic* material; + }; + + const Vertex* Vertices() const { + if (hasSkin) { + return m_SkinedVertices.data(); + } else { + return m_Vertices.data(); + } + }; + + unsigned int VertexSize() const { + if (hasSkin) { + return sizeof(SkinedVertex); + } + else { + return sizeof(Vertex); + } + }; + + unsigned int NumVertices() const { + if (hasSkin) { + return m_SkinedVertices.size(); + } else { + return m_Vertices.size(); + } + }; + + bool IsSkinned() const { return hasSkin; }; + + std::vector m_Materials; - std::vector m_Vertices; std::vector m_Indices; Skeleton* m_Skeleton = nullptr; glm::mat4 m_Matrix; private: - + bool hasSkin; + std::vector m_Vertices; + std::vector m_SkinedVertices; void ReadMeshFile(std::string filePath); void ReadMeshFileHeader(std::size_t& offset, char* fileData); @@ -83,13 +136,17 @@ private: void ReadMaterialFile(std::string filePath); 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 ReadMaterialBasic(MaterialBasic* Material, std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + void ReadMaterialSingleTexture(MaterialSingleTextures* Material, std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + void ReadMaterialSplatMapping(MaterialSplatMapping* Material, std::size_t& offset, char* fileData, const unsigned int& fileByteSize); + void ReadMaterialTextureProperties(TextureProperties& texture, std::size_t& offset, char* fileData, const unsigned int& fileByteSize); void ReadAnimationFile(std::string filePath); 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 ReadAnimationKeyFrame(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, std::vector& 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 47b15b63..647adab8 100644 --- a/include/Engine/Rendering/RenderQueue.h +++ b/include/Engine/Rendering/RenderQueue.h @@ -20,12 +20,17 @@ struct RenderScene { ::Camera* Camera = nullptr; - std::list> OpaqueObjects; - std::list> TransparentObjects; - std::list> PointLightJobs; - std::list> TextJobs; - std::list> DirectionalLightJobs; - std::list> SpriteJobs; + struct Queues { + std::list> OpaqueObjects; + std::list> TransparentObjects; + std::list> OpaqueShieldedObjects; + std::list> TransparentShieldedObjects; + std::list> ShieldObjects; + std::list> SpriteJob; + std::list> PointLight; + std::list> Text; + std::list> DirectionalLight; + } Jobs; Rectangle Viewport; bool ClearDepth = false; @@ -33,12 +38,13 @@ struct RenderScene void Clear() { - OpaqueObjects.clear(); - TransparentObjects.clear(); - PointLightJobs.clear(); - TextJobs.clear(); - DirectionalLightJobs.clear(); - SpriteJobs.clear(); + Jobs.OpaqueObjects.clear(); + Jobs.TransparentObjects.clear(); + Jobs.OpaqueShieldedObjects.clear(); + Jobs.TransparentShieldedObjects.clear(); + Jobs.ShieldObjects.clear(); + Jobs.SpriteJob.clear(); + Jobs.DirectionalLight.clear(); } }; diff --git a/include/Engine/Rendering/RenderState.h b/include/Engine/Rendering/RenderState.h index 688ef520..c1886247 100644 --- a/include/Engine/Rendering/RenderState.h +++ b/include/Engine/Rendering/RenderState.h @@ -2,6 +2,7 @@ #define RenderState_h__ #include +#include #include "../Common.h" #include "../OpenGL.h" #include "../GLM.h" @@ -19,6 +20,9 @@ public: bool BindFramebuffer(GLint framebuffer); bool BlendEquation(GLenum mode); bool BlendFunc(GLenum sfactor, GLenum dfactor); + bool StencilOp(GLenum sfail, GLenum dpfail, GLenum dppass); + bool StencilFunc(GLenum func, GLint ref, GLuint mask); + bool StencilMask(GLuint mask); bool DepthMask(GLboolean flag); private: diff --git a/include/Engine/Rendering/RenderSystem.h b/include/Engine/Rendering/RenderSystem.h index 6ab4b98b..d73d8680 100644 --- a/include/Engine/Rendering/RenderSystem.h +++ b/include/Engine/Rendering/RenderSystem.h @@ -16,11 +16,13 @@ #include "PointLightJob.h" #include "../Core/Transform.h" #include "../Core/EPlayerSpawned.h" +#include "../Core/Octree.h" +#include "../Collision/EntityAABB.h" class RenderSystem : public ImpureSystem { public: - RenderSystem(World* world, EventBroker* eventBrokerer, const IRenderer* renderer, RenderFrame* renderFrame); + RenderSystem(SystemParams params, const IRenderer* renderer, RenderFrame* renderFrame, Octree* frustumCullOctree); ~RenderSystem(); virtual void Update(double dt) override; @@ -29,9 +31,9 @@ private: const IRenderer* m_Renderer; RenderFrame* m_RenderFrame; Camera* m_Camera; - World* m_World; EntityWrapper m_CurrentCamera = EntityWrapper::Invalid; EntityWrapper m_LocalPlayer = EntityWrapper::Invalid; + Octree* m_Octree; EventRelay m_ESetCamera; bool OnSetCamera(Events::SetCamera &event); @@ -40,7 +42,7 @@ private: EventRelay m_EPlayerSpawned; bool OnPlayerSpawned(Events::PlayerSpawned& e); - void fillModels(std::list>& opaqueJobs, std::list>& transparentJobs); + void fillModels(RenderScene::Queues &jobs); void fillText(std::list>& jobs, World* world); void fillPointLights(std::list>& jobs, World* world); void fillDirectionalLights(std::list>& jobs, World* world); @@ -48,7 +50,6 @@ private: void fillSprites(std::list>& jobs, World* world); bool isChildOfACamera(EntityWrapper entity); bool isChildOfCurrentCamera(EntityWrapper entity); - }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 33a61edf..04754514 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -22,6 +22,7 @@ #include "../Core/Transform.h" #include "imgui/imgui.h" #include "TextPass.h" +#include "Util/CommonFunctions.h" class Renderer : public IRenderer { diff --git a/include/Engine/Rendering/Skeleton.h b/include/Engine/Rendering/Skeleton.h index 3b89b89b..a8dd982d 100644 --- a/include/Engine/Rendering/Skeleton.h +++ b/include/Engine/Rendering/Skeleton.h @@ -5,6 +5,7 @@ #include "Common.h" #include "../GLM.h" #include +#include //struct Bone //{ @@ -53,22 +54,39 @@ public: { struct BoneProperty { - int ID; - glm::vec3 Position; - glm::quat Rotation; + glm::vec3 Position; + glm::quat Rotation; glm::vec3 Scale = glm::vec3(1); }; - int Index = 0; - double Time = 0.0; - std::map BoneProperties; + int Index = 0; + double Time = 0.0; + BoneProperty BoneProperties; }; - - std::string Name; - double Duration; - std::vector Keyframes; + std::string Name; + double Duration; + std::map> JointAnimations; }; + struct AnimationData + { + const Animation* animation; + float time; + float weight; + }; + + struct JointFrameTransform { + glm::vec3 PositionInterp = glm::vec3(0); + glm::quat RotationInterp = glm::quat(); + glm::vec3 ScaleInterp = glm::vec3(0); + float Weight; + }; + + struct AnimationOffset { + const Animation* animation; + float time; + }; + Skeleton() { } ~Skeleton(); @@ -82,17 +100,50 @@ public: int GetBoneID(std::string name); - const Animation* GetAnimation(std::string name); - std::vector GetFrameBones(const Animation& animation, double time, bool noRootMotion = false); - void AccumulateBoneTransforms(bool noRootMotion, const Animation::Keyframe& currentFrame, const Animation::Keyframe& nextFrame, float progress, std::map& boneMatrices, const Bone* bone, glm::mat4 parentMatrix); - void PrintSkeleton(); + void CalculateFrameBones(std::vector animations, AnimationOffset animationOffset, bool noRootMotion = false); + void CalculateFrameBones(std::vector animations, bool noRootMotion = false); + + const Animation* GetAnimation(std::string name); + + void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, const Bone* bone, glm::mat4 parentMatrix); + void AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, const Bone* bone, glm::mat4 parentMatrix); + + void PrintSkeleton(); void PrintSkeleton(const Bone* parent, int depthCount); std::map Animations; -private: - std::map m_BonesByName; + glm::mat4 GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix); + int GetKeyframe(const Animation& animation, double time); - int GetKeyframe(const Animation& animation, double time); + + std::vector GetBones() + { + std::vector finalMatrices; + for (auto &kv : m_BoneLocalTransforms) { + finalMatrices.push_back(kv.second); + } + return finalMatrices;; + } + + glm::mat4 GetBoneTransformSuper(int boneID) + { + if(m_BoneTransforms.find(boneID) != m_BoneTransforms.end()) { + return m_BoneTransforms.at(boneID); + } else { + return glm::mat4(1); + } + } + +private: + + glm::mat4 GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset); + + std::map m_BonesByName; + float aim = 0.f; + + + std::map m_BoneLocalTransforms; + std::map m_BoneTransforms; }; #endif diff --git a/include/Engine/Rendering/SpriteJob.h b/include/Engine/Rendering/SpriteJob.h index a20d0395..3bb43a1c 100644 --- a/include/Engine/Rendering/SpriteJob.h +++ b/include/Engine/Rendering/SpriteJob.h @@ -17,31 +17,28 @@ struct SpriteJob : RenderJob { - SpriteJob(ComponentWrapper cSprite, Camera* camera, glm::mat4 matrix, World* world, glm::vec4 fillColor, float fillPercentage) + SpriteJob(ComponentWrapper cSprite, Camera* camera, glm::mat4 matrix, World* world, glm::vec4 fillColor, float fillPercentage, bool depthSorted) : RenderJob() { Model = ResourceManager::Load<::Model>("Models/Core/UnitQuad.mesh"); - ::RawModel::MaterialGroup matGroup = Model->MaterialGroups().front(); - TextureID = (matGroup.Texture) ? matGroup.Texture->ResourceID : 0; + ::RawModel::MaterialProperties matProp = Model->MaterialGroups().front(); + TextureID = 0; - if (cSprite["DiffuseTexture"]) { - DiffuseTexture = ResourceManager::Load(cSprite["DiffuseTexture"]); - } else { - DiffuseTexture = nullptr; - } - if (cSprite["GlowMap"]) { - IncandescenceTexture = ResourceManager::Load(cSprite["GlowMap"]); - } else { - IncandescenceTexture = nullptr; - } - StartIndex = matGroup.StartIndex; - EndIndex = matGroup.EndIndex; + DiffuseTexture = CommonFunctions::LoadTexture(cSprite["DiffuseTexture"], true); + + IncandescenceTexture = CommonFunctions::LoadTexture(cSprite["GlowMap"], true); + + StartIndex = matProp.material->StartIndex; + EndIndex = matProp.material->EndIndex; Matrix = matrix; Color = cSprite["Color"]; Entity = cSprite.EntityID; - glm::vec3 abspos = Transform::AbsolutePosition(world, cSprite.EntityID); - glm::vec3 viewpos = glm::vec3(camera->ViewMatrix() * glm::vec4(abspos, 1)); - Depth = viewpos.z; + Position = Transform::AbsolutePosition(world, cSprite.EntityID); + Depth = 0; + if (depthSorted) { + glm::vec3 viewpos = glm::vec3(camera->ViewMatrix() * glm::vec4(Position, 1)); + Depth = viewpos.z; + } World = world; FillColor = fillColor; @@ -58,6 +55,7 @@ struct SpriteJob : RenderJob const Texture* IncandescenceTexture; float Shininess = 0.f; glm::vec4 Color; + glm::vec3 Position; const ::Model* Model = nullptr; unsigned int StartIndex = 0; unsigned int EndIndex = 0; diff --git a/include/Engine/Rendering/Util/CommonFunctions.h b/include/Engine/Rendering/Util/CommonFunctions.h index b262568c..e178f52d 100644 --- a/include/Engine/Rendering/Util/CommonFunctions.h +++ b/include/Engine/Rendering/Util/CommonFunctions.h @@ -4,14 +4,11 @@ #include "../../Common.h" #include "../../OpenGL.h" #include "../../GLM.h" +#include "../Texture.h" -class CommonFuntions -{ -public: - CommonFuntions() = delete; - -private: - +namespace CommonFunctions +{ +Texture* LoadTexture(std::string path, bool threaded); }; #endif \ No newline at end of file diff --git a/include/Engine/Sound/EPlayQueueOnEntity.h b/include/Engine/Sound/EPlayQueueOnEntity.h new file mode 100644 index 00000000..e880819a --- /dev/null +++ b/include/Engine/Sound/EPlayQueueOnEntity.h @@ -0,0 +1,18 @@ +#ifndef Events_PlayQueueOnEntity_h__ +#define Events_PlayQueueOnEntity_h__ + +#include "../Core/Event.h" +#include "../Core/EntityWrapper.h" + +namespace Events +{ + +struct PlayQueueOnEntity : public Event +{ + EntityWrapper Emitter; + std::vector FilePaths; +}; + +} + +#endif diff --git a/include/Engine/Sound/Sound.h b/include/Engine/Sound/Sound.h index 6b2aac04..cccbdf07 100644 --- a/include/Engine/Sound/Sound.h +++ b/include/Engine/Sound/Sound.h @@ -1,6 +1,9 @@ #ifndef Sound_h__ #define Sound_h__ +#include +#include + #include "Core/ResourceManager.h" class Sound : public Resource diff --git a/include/Engine/Sound/SoundSystem.h b/include/Engine/Sound/SoundManager.h similarity index 57% rename from include/Engine/Sound/SoundSystem.h rename to include/Engine/Sound/SoundManager.h index b9cc2589..5b027c62 100644 --- a/include/Engine/Sound/SoundSystem.h +++ b/include/Engine/Sound/SoundManager.h @@ -1,17 +1,23 @@ -#ifndef SoundSystem_h__ -#define SoundSystem_h__ +#ifndef SoundManager_h__ +#define SoundManager_h__ #include +#include #include "glm/common.hpp" #include "glm/gtx/rotate_vector.hpp" // Calculate Up vector #include "OpenAL/al.h" #include "OpenAL/alc.h" +#include "imgui/imgui.h" + #include "Core/World.h" #include "Core/EventBroker.h" +#include "../Engine/Core/ResourceManager.h" +#include "../Engine/Core/ConfigFile.h" #include "Core/Transform.h" // Absolute transform #include "Sound/Sound.h" +#include "../Engine/Sound/EPlayQueueOnEntity.h" #include "Sound/EPlaySoundOnEntity.h" #include "Sound/EPlaySoundOnPosition.h" #include "Sound/EPlayBackgroundMusic.h" @@ -20,6 +26,11 @@ #include "Sound/EStopSound.h" #include "Sound/ESetBGMGain.h" #include "Sound/ESetSFXGain.h" +#include "Core/EPause.h" +#include "Core/EComponentAttached.h" +#include "../Core/EPlayerSpawned.h" + +typedef std::pair> QueuedBuffers; enum class SoundType { SFX, @@ -34,14 +45,15 @@ struct Source SoundType Type; }; -class SoundSystem +class SoundManager { public: - SoundSystem() { } - SoundSystem(World* world, EventBroker* eventBroker, bool editorMode); - ~SoundSystem(); + SoundManager() { } + SoundManager(World* world, EventBroker* eventBroker); + ~SoundManager(); // Update emitters / listener void Update(double dt); + private: // Help functions for working with OpenaAL void setListenerPos(glm::vec3 pos) { alListener3f(AL_POSITION, pos.x, pos.y, pos.z); }; @@ -56,46 +68,62 @@ private: // Logic void initOpenAL(); void updateEmitters(double dt); - void updateListener(double dt); void deleteInactiveEmitters(); - void addNewEmitters(double dt); - Source* createSource(std::string filePath); - void playSound(Source* source); - void stopSound(Source* source); void stopEmitters(); + void updateListener(double dt); ALenum getSourceState(ALuint source); void setGain(Source* source, float gain); - void setSoundProperties(ALuint source, ComponentWrapper* soundComponent); + void setSoundProperties(Source* source, ComponentWrapper* soundComponent); + + // Specific logic + void playSound(Source* source); + // Need to be the same format (sample rate etc) + void playQueue(QueuedBuffers qb); + void stopSound(Source* source); + Source* createSource(std::string filePath); + std::unordered_map m_Sources; + + // Logic + World* m_World = nullptr; + EventBroker* m_EventBroker = nullptr; // OpenAL system variables ALCdevice* m_ALCdevice = nullptr; ALCcontext* m_ALCcontext = nullptr; - // Logic - World* m_World = nullptr; - EventBroker* m_EventBroker = nullptr; - std::unordered_map m_Sources; float m_BGMVolumeChannel = 1.0f; - float m_SFXVolumeChannel = 1.f; - bool m_EditorEnabled = false; - + float m_SFXVolumeChannel = 1.0f; + EntityWrapper m_LocalPlayer = EntityWrapper(); + // Events - EventRelay m_EPlaySoundOnEntity; + EventRelay m_EPlaySoundOnEntity; bool OnPlaySoundOnEntity(const Events::PlaySoundOnEntity &e); - EventRelay m_EPlaySoundOnPosition; + EventRelay m_EPlaySoundOnPosition; bool OnPlaySoundOnPosition(const Events::PlaySoundOnPosition &e); - EventRelay m_EPlayBackgroundMusic; + EventRelay m_EPlayBackgroundMusic; bool OnPlayBackgroundMusic(const Events::PlayBackgroundMusic &e); - EventRelay m_EPauseSound; + EventRelay m_EPauseSound; bool OnPauseSound(const Events::PauseSound &e); - EventRelay m_EStopSound; + EventRelay m_EStopSound; bool OnStopSound(const Events::StopSound &e); - EventRelay m_EContinueSound; + EventRelay m_EContinueSound; bool OnContinueSound(const Events::ContinueSound &e); - EventRelay m_ESetBGMGain; - bool OnSetBGMGain(const Events::SetBGMGain &e); // Not tested - EventRelay m_ESetSFXGain; - bool OnSetSFXGain(const Events::SetSFXGain &e); // Not tested + EventRelay m_ESetBGMGain; + bool OnSetBGMGain(const Events::SetBGMGain &e); + EventRelay m_ESetSFXGain; + bool OnSetSFXGain(const Events::SetSFXGain &e); + EventRelay m_EComponentAttached; + bool OnComponentAttached(const Events::ComponentAttached &e); + EventRelay m_EPause; + bool OnPause(const Events::Pause &e); + EventRelay m_EResume; + bool OnResume(const Events::Resume &e); + EventRelay m_EPlayerSpawned; + bool OnPlayerSpawned(const Events::PlayerSpawned &e); + EventRelay m_EPlayQueueOnEntity; + bool OnPlayQueueOnEntity(const Events::PlayQueueOnEntity &e); + + }; #endif \ No newline at end of file diff --git a/include/Game/Events/EDashAbility.h b/include/Game/Events/EDashAbility.h new file mode 100644 index 00000000..62a2b935 --- /dev/null +++ b/include/Game/Events/EDashAbility.h @@ -0,0 +1,13 @@ +#ifndef Events_DashAbility_h__ +#define Events_DashAbility_h__ + +#include "Core/Event.h" + +namespace Events +{ + +struct DashAbility : public Event { }; + +} + +#endif \ No newline at end of file diff --git a/include/Game/Events/EDoubleJump.h b/include/Game/Events/EDoubleJump.h new file mode 100644 index 00000000..767d5b39 --- /dev/null +++ b/include/Game/Events/EDoubleJump.h @@ -0,0 +1,16 @@ +#ifndef Events_DoubleJump_h__ +#define Events_DoubleJump_h__ + +#include "Core/Event.h" + +namespace Events +{ + +struct DoubleJump : public Event +{ + +}; + +} + +#endif diff --git a/include/Game/ExplosionEffectSystem.h b/include/Game/ExplosionEffectSystem.h deleted file mode 100644 index 061ad221..00000000 --- a/include/Game/ExplosionEffectSystem.h +++ /dev/null @@ -1,24 +0,0 @@ -#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 37267a68..baf15656 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -1,6 +1,8 @@ #ifndef Game_h__ #define Game_h__ +#include + #include "Core/ResourceManager.h" #include "Core/ConfigFile.h" #include "Core/EventBroker.h" @@ -14,7 +16,7 @@ #include "Core/EKeyDown.h" #include "Core/EntityFilePreprocessor.h" #include "Core/SystemPipeline.h" -#include "ExplosionEffectSystem.h" +#include "Systems/ExplosionEffectSystem.h" #include "Editor/EditorSystem.h" #include "Core/EntityFile.h" #include "Rendering/RenderSystem.h" @@ -30,7 +32,8 @@ #include "Network/Client.h" // Sound -#include "Sound/SoundSystem.h" +#include "Sound/SoundManager.h" +#include "Systems/SoundSystem.h" class Game { @@ -42,7 +45,9 @@ public: void Tick(); private: - double m_LastTime; + std::string m_NetworkAddress; + int m_NetworkPort = 0; + ConfigFile* m_Config = nullptr; EventBroker* m_EventBroker; IRenderer* m_Renderer; @@ -55,24 +60,15 @@ private: Octree* m_OctreeFrustrumCulling; SystemPipeline* m_SystemPipeline; RenderFrame* m_RenderFrame; - // Network variables - boost::thread m_NetworkThread; + Client* m_NetworkClient = nullptr; + Server* m_NetworkServer = nullptr; + SoundManager* m_SoundManager; + double m_LastTime; - // Network methods - void networkFunction(); - Network* m_ClientOrServer; - bool m_IsClientOrServer = false; - - // Sound - SoundSystem* m_SoundSystem; - - //EventRelay m_EInputCommand; - //bool debugOnInputCommand(const Events::InputCommand& e); - - void debugInitialize(); - void debugTick(double dt); - EventRelay m_EKeyDown; + bool m_IsClient = false; + bool m_IsServer = false; + int parseArgs(int argc, char* argv[]); }; #endif diff --git a/include/Game/Network/MultiplayerSnapshotFilter.h b/include/Game/Network/MultiplayerSnapshotFilter.h new file mode 100644 index 00000000..32c82e01 --- /dev/null +++ b/include/Game/Network/MultiplayerSnapshotFilter.h @@ -0,0 +1,25 @@ +#ifndef MultiplayerSnapshotFilter_h__ +#define MultiplayerSnapshotFilter_h__ + +#include "Core/EventBroker.h" +#include "Core/EPlayerSpawned.h" +#include "Network/SnapshotFilter.h" +#include "Network/EInterpolate.h" + +class MultiplayerSnapshotFilter : public SnapshotFilter +{ +public: + MultiplayerSnapshotFilter(EventBroker* eventBroker); + + virtual bool FilterComponent(EntityWrapper entity, SharedComponentWrapper& component) override; + +private: + EventBroker* m_EventBroker; + + EntityWrapper m_LocalPlayer = EntityWrapper::Invalid; + + EventRelay m_EPlayerSpawned; + bool OnPlayerSpawned(Events::PlayerSpawned ePlayerSpawned); +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/CapturePointHUDSystem.h b/include/Game/Systems/CapturePointHUDSystem.h new file mode 100644 index 00000000..41db0c12 --- /dev/null +++ b/include/Game/Systems/CapturePointHUDSystem.h @@ -0,0 +1,22 @@ +#ifndef CapturePointHUDSystem_h__ +#define CapturePointHUDSystem_h__ + +#include +#include +#include + +#include "Common.h" +#include "Core/System.h" +#include "Engine/Collision/ETrigger.h" + +class CapturePointHUDSystem : public ImpureSystem +{ +public: + CapturePointHUDSystem(SystemParams params); + + virtual void Update(double dt) override; + +private: +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/CapturePointSystem.h b/include/Game/Systems/CapturePointSystem.h index 18c32c76..22e7e3d5 100644 --- a/include/Game/Systems/CapturePointSystem.h +++ b/include/Game/Systems/CapturePointSystem.h @@ -17,7 +17,7 @@ class CapturePointSystem : public PureSystem { public: //WARNING: on new map, destroy all info in the vectors, as well as reset all variables (just make new?) - CapturePointSystem(World* world, EventBroker* eventBroker); + CapturePointSystem(SystemParams params); //updatecomponent virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& capturePoint, double dt) override; diff --git a/include/Game/Systems/ExplosionEffectSystem.h b/include/Game/Systems/ExplosionEffectSystem.h new file mode 100644 index 00000000..24eee955 --- /dev/null +++ b/include/Game/Systems/ExplosionEffectSystem.h @@ -0,0 +1,18 @@ +#ifndef ExplosionEffectSystem_h__ +#define ExplosionEffectSystem_h__ + +#include "Common.h" +#include "Core/System.h" + +class ExplosionEffectSystem : public PureSystem +{ +public: + ExplosionEffectSystem(SystemParams params) + : System(params) + , PureSystem("ExplosionEffect") + { } + + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; +}; + +#endif \ No newline at end of file diff --git a/include/Game/Systems/HealthSystem.h b/include/Game/Systems/HealthSystem.h index 61456d5d..b66d8eb0 100644 --- a/include/Game/Systems/HealthSystem.h +++ b/include/Game/Systems/HealthSystem.h @@ -17,7 +17,7 @@ class HealthSystem : public PureSystem { public: - HealthSystem(World* world, EventBroker* eventBroker); + HealthSystem(SystemParams params); //updatecomponent virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; diff --git a/include/Game/Systems/InterpolationSystem.h b/include/Game/Systems/InterpolationSystem.h index 96236f62..758609c8 100644 --- a/include/Game/Systems/InterpolationSystem.h +++ b/include/Game/Systems/InterpolationSystem.h @@ -16,38 +16,47 @@ #include "Network/EInterpolate.h" -class InterpolationSystem : public PureSystem +class InterpolationSystem : public ImpureSystem { - struct Transform - { - glm::vec3 Position; - glm::vec3 Scale; - glm::quat Orientation; - float interpolationTime; - }; public: - InterpolationSystem(World* world, EventBroker* eventBroker); + InterpolationSystem(SystemParams params); ~InterpolationSystem() { } - virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt) override; -private: - std::unordered_map m_NextTransform; - std::unordered_map m_LastReceivedTransform; - EntityWrapper m_LocalPlayer = EntityWrapper::Invalid; - //glm::vec3 vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime); + virtual void Update(double dt) override; + +private: + template + struct Interpolation + { + Interpolation(const ComponentWrapper& Component, const std::string& Field, const T& Start, const T& Goal) + : Component(Component) + , Field(Field) + , Start(Start) + , Goal(Goal) + { } + + ComponentWrapper Component; + std::string Field; + T Start; + T Goal; + double Alpha = 0.0; + }; + + float m_SnapshotInterval; + std::unordered_map> m_InterpolatePosition; + std::unordered_map> m_InterpolateOrientation; + std::unordered_map> m_InterpolateVelocity; + + EventRelay m_EInterpolate; + bool InterpolationSystem::OnInterpolate(Events::Interpolate& e); + template T vectorInterpolation(T prev, T next, double currentTime) { T difference = next - prev; - T vector = (difference / m_SnapshotInterval) * static_cast(currentTime); + T vector = difference * (static_cast(currentTime) / m_SnapshotInterval); return vector; } - float m_SnapshotInterval; - - EventRelay m_EInterpolate; - bool InterpolationSystem::OnInterpolate(const Events::Interpolate& e); - EventRelay m_EPlayerSpawned; - bool OnPlayerSpawned(Events::PlayerSpawned& e); }; #endif diff --git a/include/Game/Systems/LifetimeSystem.h b/include/Game/Systems/LifetimeSystem.h index da88cfa2..6dee644d 100644 --- a/include/Game/Systems/LifetimeSystem.h +++ b/include/Game/Systems/LifetimeSystem.h @@ -6,10 +6,12 @@ class LifetimeSystem : public ImpureSystem, PureSystem { public: - LifetimeSystem(World* world, EventBroker* eventBroker) - : System(world, eventBroker) + LifetimeSystem(SystemParams params) + : System(params) , PureSystem("Lifetime") - { } + { + LOG_INFO("ASDASDASSA"); + } virtual void Update(double dt) override; virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cLifetime, double dt) override; diff --git a/include/Game/Systems/PickupSpawnSystem.h b/include/Game/Systems/PickupSpawnSystem.h index 24cee2b9..f912e8ff 100644 --- a/include/Game/Systems/PickupSpawnSystem.h +++ b/include/Game/Systems/PickupSpawnSystem.h @@ -14,7 +14,7 @@ class PickupSpawnSystem : public ImpureSystem { public: - PickupSpawnSystem(World* world, EventBroker* eventBroker); + PickupSpawnSystem(SystemParams params); virtual void Update(double dt) override; diff --git a/include/Game/Systems/PlayerDeathSystem.h b/include/Game/Systems/PlayerDeathSystem.h index 988dad57..112c202e 100644 --- a/include/Game/Systems/PlayerDeathSystem.h +++ b/include/Game/Systems/PlayerDeathSystem.h @@ -15,7 +15,7 @@ class PlayerDeathSystem : public ImpureSystem { public: - PlayerDeathSystem(World* world, EventBroker* eventBroker); + PlayerDeathSystem(SystemParams params); virtual void Update(double dt) override; diff --git a/include/Game/Systems/PlayerHUD.h b/include/Game/Systems/PlayerHUDSystem.h similarity index 58% rename from include/Game/Systems/PlayerHUD.h rename to include/Game/Systems/PlayerHUDSystem.h index 180f5a2a..50b6a258 100644 --- a/include/Game/Systems/PlayerHUD.h +++ b/include/Game/Systems/PlayerHUDSystem.h @@ -6,18 +6,14 @@ #include "../../Engine/Rendering/ESetCamera.h" #include -class PlayerHUD : public ImpureSystem +class PlayerHUDSystem : public ImpureSystem { public: - PlayerHUD(World* world, EventBroker* eventBrokerer); - ~PlayerHUD(); + PlayerHUDSystem(SystemParams params) + : System(params) + { } 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/PlayerMovementSystem.h b/include/Game/Systems/PlayerMovementSystem.h index 34862e90..2bcae866 100644 --- a/include/Game/Systems/PlayerMovementSystem.h +++ b/include/Game/Systems/PlayerMovementSystem.h @@ -4,21 +4,40 @@ #include "Core/EPlayerSpawned.h" #include "Input/FirstPersonInputController.h" #include +#include "Events/EDoubleJump.h" +#include "../Engine/Sound/EPlaySoundOnEntity.h" -class PlayerMovementSystem : public ImpureSystem, PureSystem +#include "Core/EntityFile.h" +#include "Core/EntityFileParser.h" + +class PlayerMovementSystem : public ImpureSystem { public: - PlayerMovementSystem(World* world, EventBroker* eventBroker); + PlayerMovementSystem(SystemParams params); ~PlayerMovementSystem(); virtual void Update(double dt) override; - virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt); private: // State std::unordered_map*> m_PlayerInputControllers; + EntityWrapper m_LocalPlayer = EntityWrapper::Invalid; + // Walking logic + // Keeps track of how far the player has walked within this "key press session". + float m_DistanceMoved = 0.0f; + // How far a step is (How often the step sound will be played). + const float m_PlayerStepLength = 1.75f; + // Determine what sound file to play. + bool m_LeftFoot = false; + // To get a difference when calculating the walking state. + glm::vec3 m_LastPosition = glm::vec3(); + // The logic for making the sound play when player is moving + void playerStep(double dt); + EventRelay m_EPlayerSpawned; bool OnPlayerSpawned(Events::PlayerSpawned& e); + void updateMovementControllers(double dt); + void updateVelocity(double dt); }; \ No newline at end of file diff --git a/include/Game/Systems/PlayerSpawnSystem.h b/include/Game/Systems/PlayerSpawnSystem.h index f5aa7b82..c68bb21f 100644 --- a/include/Game/Systems/PlayerSpawnSystem.h +++ b/include/Game/Systems/PlayerSpawnSystem.h @@ -10,7 +10,7 @@ class PlayerSpawnSystem : public ImpureSystem { public: - PlayerSpawnSystem(World* world, EventBroker* eventBroker); + PlayerSpawnSystem(SystemParams params); virtual void Update(double dt) override; diff --git a/include/Game/Systems/RaptorCopterSystem.h b/include/Game/Systems/RaptorCopterSystem.h index 8bb18de6..b3589dcd 100644 --- a/include/Game/Systems/RaptorCopterSystem.h +++ b/include/Game/Systems/RaptorCopterSystem.h @@ -4,8 +4,8 @@ class RaptorCopterSystem : public PureSystem { public: - RaptorCopterSystem(World* world, EventBroker* eventBroker) - : System(world, eventBroker) + RaptorCopterSystem(SystemParams params) + : System(params) , PureSystem("RaptorCopter") { } diff --git a/include/Game/Systems/SoundSystem.h b/include/Game/Systems/SoundSystem.h new file mode 100644 index 00000000..962eb085 --- /dev/null +++ b/include/Game/Systems/SoundSystem.h @@ -0,0 +1,65 @@ +#ifndef Systems_SoundSystem_h__ +#define Systems_SoundSystem_h__ + +#include + +#include "../Engine/Core/System.h" +#include "../Engine/Core/ResourceManager.h" +#include "../Engine/Core/ConfigFile.h" +#include "../Engine/Sound/Sound.h" +#include "../Engine/Sound/EPlayQueueOnEntity.h" +#include "../Engine/Core/EPlayerSpawned.h" +#include "../Engine/Input/EInputCommand.h" +#include "../Engine/Core/EShoot.h" +#include "../Engine/Core/EPlayerSpawned.h" +#include "../Engine/Input/EInputCommand.h" +#include "../Engine/Core/ECaptured.h" +#include "../Engine/Core/EPlayerDamage.h" +#include "../Engine/Core/EPlayerDeath.h" +#include "../Engine/Core/EPlayerHealthPickup.h" +#include "../Engine/Collision/ETrigger.h" +#include "../Engine/Sound/EPlaySoundOnEntity.h" +#include "../Engine/Sound/EPlayBackgroundMusic.h" +#include "../Game/Events/EDoubleJump.h" +#include "../Game/Events/EDashAbility.h" + + +class SoundSystem : public PureSystem, ImpureSystem +{ +public: + SoundSystem(SystemParams params); + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) override; + virtual void Update(double dt) override; +private: + std::string m_Announcer = ""; + // Logic for playing a sound when a player jumps + void playerJumps(); + + // Temporary solution for play test. + bool m_DrumsIsPlaying = false; + double m_DrumTimer = 0.0; + bool drumTimer(double dt); + + std::default_random_engine generator; + + EventRelay m_EPlayerSpawned; + bool OnPlayerSpawned(const Events::PlayerSpawned &e); + EventRelay m_InputCommand; + bool OnInputCommand(const Events::InputCommand &e); + EventRelay m_EDoubleJump; + bool OnDoubleJump(const Events::DoubleJump &e); + EventRelay m_EDashAbility; + bool OnDashAbility(const Events::DashAbility &e); + EventRelay m_ETriggerTouch; + bool OnTriggerTouch(const Events::TriggerTouch &e); + EventRelay m_ECaptured; + bool OnCaptured(const Events::Captured &e); + EventRelay m_EPlayerDamage; + bool OnPlayerDamage(const Events::PlayerDamage &e); + EventRelay m_EPlayerDeath; + bool OnPlayerDeath(const Events::PlayerDeath &e); + EventRelay m_EPlayerHealthPickup; + bool OnPlayerHealthPickup(const Events::PlayerHealthPickup &e); +}; + +#endif diff --git a/include/Game/Systems/SpawnerSystem.h b/include/Game/Systems/SpawnerSystem.h index 62f6b09a..9cb4bd06 100644 --- a/include/Game/Systems/SpawnerSystem.h +++ b/include/Game/Systems/SpawnerSystem.h @@ -13,7 +13,7 @@ class SpawnerSystem : public System { public: - SpawnerSystem(World* world, EventBroker* eventBroker); + SpawnerSystem(SystemParams params); static EntityWrapper Spawn(EntityWrapper spawner, EntityWrapper parent = EntityWrapper::Invalid); diff --git a/include/Game/Systems/WeaponSystem.h b/include/Game/Systems/WeaponSystem.h index 0dd5cc54..b118b8cd 100644 --- a/include/Game/Systems/WeaponSystem.h +++ b/include/Game/Systems/WeaponSystem.h @@ -13,31 +13,180 @@ #include "Input/EInputCommand.h" #include "Core/EntityFile.h" #include "Core/EntityFileParser.h" +#include "Core/Octree.h" +#include "Collision/EntityAABB.h" +#include "Systems/SpawnerSystem.h" +#include "Sound/EPlaySoundOnEntity.h" -#include -#include +class WeaponBehaviour; - -class WeaponSystem : public ImpureSystem +class WeaponSystem : public PureSystem, ImpureSystem { public: - WeaponSystem(World* world, EventBroker* eventBroker, IRenderer* renderer); + WeaponSystem(SystemParams params, IRenderer* renderer, Octree* collisionOctree); virtual void Update(double dt) override; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPlayer, double dt) override; private: + SystemParams m_SystemParams; IRenderer* m_Renderer; + Octree* m_CollisionOctree; - // State - EntityWrapper m_LocalPlayer = EntityWrapper::Invalid; + std::unordered_map> m_ActiveWeapons; // Events EventRelay m_EPlayerSpawned; - bool WeaponSystem::OnPlayerSpawned(const Events::PlayerSpawned& e); + bool OnPlayerSpawned(Events::PlayerSpawned& e); EventRelay m_EShoot; - bool WeaponSystem::OnShoot(Events::Shoot& e); + bool OnShoot(Events::Shoot& e); EventRelay m_EInputCommand; - bool WeaponSystem::OnInputCommand(const Events::InputCommand& e); + bool OnInputCommand(Events::InputCommand& e); + + void selectWeapon(EntityWrapper player, ComponentInfo::EnumType slot); +}; + +class WeaponBehaviour : public System +{ +public: + WeaponBehaviour(SystemParams systemParams, Octree* collisionOctree, EntityWrapper weaponEntity) + : System(systemParams) + , m_CollisionOctree(collisionOctree) + , m_Entity(weaponEntity) + { } + virtual ~WeaponBehaviour() = default; + + WeaponBehaviour(const WeaponBehaviour&) = delete; + WeaponBehaviour& operator=(const WeaponBehaviour &) = delete; + + virtual void Fire() = 0; + virtual void CeaseFire() { } + virtual void Reload() { } + virtual void Update(double dt) { } + +protected: + Octree* m_CollisionOctree; + EntityWrapper m_Entity; +}; + +class AssaultWeaponBehaviour : public WeaponBehaviour +{ +public: + AssaultWeaponBehaviour(SystemParams systemParams, Octree* collisionOctree, EntityWrapper weaponEntity) + : WeaponBehaviour(systemParams, collisionOctree, weaponEntity) + { } + + virtual void Fire() override + { + m_TimeSinceLastFire = 0.0; + m_Firing = true; + fireRound(); + } + + virtual void CeaseFire() override + { + m_Firing = false; + } + + virtual void Reload() override + { + ComponentWrapper& cAssaultWeapon = m_Entity["AssaultWeapon"]; + + int& magAmmo = cAssaultWeapon["MagazineAmmo"]; + int magSize = cAssaultWeapon["MagazineSize"]; + int& ammo = cAssaultWeapon["Ammo"]; + + // Don't reload if we're already fully loaded + if (magAmmo == magSize) { + return; + } + + // Throw away rounds in magazine to incentivise ammo sharing + int toLoad = glm::min(magSize, ammo); + magAmmo = toLoad; + ammo -= toLoad; + } + + virtual void Update(double dt) override + { + if (!m_Firing) { + return; + } + + m_TimeSinceLastFire += dt; + + ComponentWrapper& cAssaultWeapon = m_Entity["AssaultWeapon"]; + if (m_TimeSinceLastFire >= 1.0 / ((double)cAssaultWeapon["RPM"] / 60.0)) { + fireRound(); + } + } + +private: + bool m_Firing = false; + double m_TimeSinceLastFire = 0.0; + EntityFile* m_RayRed = nullptr; + EntityFile* m_RayBlue = nullptr; + + void fireRound() + { + ComponentWrapper& cAssaultWeapon = m_Entity["AssaultWeapon"]; + + int& magAmmo = cAssaultWeapon["MagazineAmmo"]; + int ammo = cAssaultWeapon["Ammo"]; + + // Reload if our magazine is empty + if (magAmmo <= 0) { + Reload(); + return; + } + + // Fire + magAmmo -= 1; + spawnTracer(); + playSound(); + + m_TimeSinceLastFire = 0.0; + } + + void spawnTracer() + { + if (!IsClient) { + return; + } + + EntityWrapper spawner; + if (m_Entity == LocalPlayer) { + spawner = m_Entity.FirstChildByName("WeaponMuzzle"); + } else { + spawner = m_Entity.FirstChildByName("ThirdPersonWeaponMuzzle"); + } + + if (!spawner.Valid()) { + return; + } + + Events::SpawnerSpawn e; + e.Spawner = spawner; + m_EventBroker->Publish(e); + } + + float traceRayDistance(glm::vec3 origin, glm::vec3 direction) + { + // TODO: Cast a ray and size tracer appropriately + return 100.f; + } + + void playSound() + { + if (!IsClient) { + return; + } + + Events::PlaySoundOnEntity e; + e.EmitterID = m_Entity.ID; + e.FilePath = "Audio/laser/laser1.wav"; + m_EventBroker->Publish(e); + } }; #endif \ No newline at end of file diff --git a/resources/DefaultConfig.ini b/resources/DefaultConfig.ini index 86dc735c..12ec06c8 100644 --- a/resources/DefaultConfig.ini +++ b/resources/DefaultConfig.ini @@ -29,3 +29,8 @@ TimeoutMs=15000 [Multithreading] ResourceLoading=true + +[Sound] +BGMVolume=1.0 +SFXVolume=1.0 +Announcer=female \ No newline at end of file diff --git a/resources/DefaultInput.ini b/resources/DefaultInput.ini index 589dfb3f..683d48e2 100644 --- a/resources/DefaultInput.ini +++ b/resources/DefaultInput.ini @@ -2,6 +2,9 @@ Sensitivity=0.5 InvertPitch=false +[Keyboard] +DoubleTapToDash=false + [Bindings] MouseLeft=PrimaryFire MouseX=Yaw @@ -15,6 +18,8 @@ Space=Jump LeftControl=Crouch RightShift=Sprint LeftShift=SpecialAbility +1=SelectWeapon,1 +2=SelectWeapon,2 F1=ToggleEditor C=ConnectToServer N=SwitchToServer diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index 85024bae..f950e8c8 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -28,9 +28,15 @@ + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/Animation.xml b/resources/Schema/Components/Animation.xml index 66d2865d..ae42009d 100644 --- a/resources/Schema/Components/Animation.xml +++ b/resources/Schema/Components/Animation.xml @@ -1,7 +1,18 @@ - - - 0 - true + + 1.0 + 0 + 0 + true + + 1.0 + 0 + 0 + true + + 1.0 + 0 + 0 + true \ No newline at end of file diff --git a/resources/Schema/Components/Animation.xsd b/resources/Schema/Components/Animation.xsd index 0dd21f29..f39aac18 100644 --- a/resources/Schema/Components/Animation.xsd +++ b/resources/Schema/Components/Animation.xsd @@ -6,11 +6,23 @@ - - - - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/AnimationOffset.xml b/resources/Schema/Components/AnimationOffset.xml new file mode 100644 index 00000000..4aef8219 --- /dev/null +++ b/resources/Schema/Components/AnimationOffset.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/AnimationOffset.xsd b/resources/Schema/Components/AnimationOffset.xsd new file mode 100644 index 00000000..c3430cc2 --- /dev/null +++ b/resources/Schema/Components/AnimationOffset.xsd @@ -0,0 +1,17 @@ + + + + + + + + Aim animation offset for the skeleton + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/AssaultWeapon.xml b/resources/Schema/Components/AssaultWeapon.xml new file mode 100755 index 00000000..902795c1 --- /dev/null +++ b/resources/Schema/Components/AssaultWeapon.xml @@ -0,0 +1,9 @@ + + + 32 + 32 + 360 + 360 + 5 + 120 + \ No newline at end of file diff --git a/resources/Schema/Components/AssaultWeapon.xsd b/resources/Schema/Components/AssaultWeapon.xsd new file mode 100755 index 00000000..1b2704ea --- /dev/null +++ b/resources/Schema/Components/AssaultWeapon.xsd @@ -0,0 +1,28 @@ + + + + + + + + + + Ammo currently loaded into the magazine + + + Max number of rounds in a magazine + + + Current ammo carried + + + Maximum ammo able to be carried + + + + Rate of fire in rounds per minute + + + + + diff --git a/resources/Schema/Components/BoneAttachment.xml b/resources/Schema/Components/BoneAttachment.xml new file mode 100644 index 00000000..47df9e40 --- /dev/null +++ b/resources/Schema/Components/BoneAttachment.xml @@ -0,0 +1,10 @@ + + + + + + + true + true + false + \ No newline at end of file diff --git a/resources/Schema/Components/BoneAttachment.xsd b/resources/Schema/Components/BoneAttachment.xsd new file mode 100644 index 00000000..aee1868f --- /dev/null +++ b/resources/Schema/Components/BoneAttachment.xsd @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/CapturePointHUD.xml b/resources/Schema/Components/CapturePointHUD.xml new file mode 100644 index 00000000..2943d57b --- /dev/null +++ b/resources/Schema/Components/CapturePointHUD.xml @@ -0,0 +1,5 @@ + + + 0 + + \ No newline at end of file diff --git a/resources/Schema/Components/CapturePointHUD.xsd b/resources/Schema/Components/CapturePointHUD.xsd new file mode 100644 index 00000000..7984fc50 --- /dev/null +++ b/resources/Schema/Components/CapturePointHUD.xsd @@ -0,0 +1,24 @@ + + + + + + + Hud element for tracking capture points. + + + + + + Corresponds to the number on the capture point it should track. + + + + + Specify the team that own this capturePoint. + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/Collidable.xsd b/resources/Schema/Components/Collidable.xsd index 84c66f11..93f7ac24 100644 --- a/resources/Schema/Components/Collidable.xsd +++ b/resources/Schema/Components/Collidable.xsd @@ -4,5 +4,8 @@ + + Needs a Model or AABB component to work, uses AABB if both are attached. + \ No newline at end of file diff --git a/resources/Schema/Components/Shield.xml b/resources/Schema/Components/Shield.xml new file mode 100644 index 00000000..161f09bc --- /dev/null +++ b/resources/Schema/Components/Shield.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/resources/Schema/Components/Shield.xsd b/resources/Schema/Components/Shield.xsd new file mode 100644 index 00000000..9831cbfc --- /dev/null +++ b/resources/Schema/Components/Shield.xsd @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/Shielded.xml b/resources/Schema/Components/Shielded.xml new file mode 100644 index 00000000..0d95fb0a --- /dev/null +++ b/resources/Schema/Components/Shielded.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/resources/Schema/Components/Shielded.xsd b/resources/Schema/Components/Shielded.xsd new file mode 100644 index 00000000..b2348cf5 --- /dev/null +++ b/resources/Schema/Components/Shielded.xsd @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/Sprite.xml b/resources/Schema/Components/Sprite.xml index c2a2057f..ce4a6e1b 100644 --- a/resources/Schema/Components/Sprite.xml +++ b/resources/Schema/Components/Sprite.xml @@ -4,4 +4,5 @@ true + true diff --git a/resources/Schema/Components/Sprite.xsd b/resources/Schema/Components/Sprite.xsd index c8f0c187..3c3d124a 100644 --- a/resources/Schema/Components/Sprite.xsd +++ b/resources/Schema/Components/Sprite.xsd @@ -21,6 +21,9 @@ Whether the model is visible or not + + Whether the sprite should be sorted with depth or not. Only use false for textures that are on HUD + diff --git a/resources/Schema/Components/Transform.xsd b/resources/Schema/Components/Transform.xsd index f0db2472..555b336c 100644 --- a/resources/Schema/Components/Transform.xsd +++ b/resources/Schema/Components/Transform.xsd @@ -4,9 +4,6 @@ - - It's a transform thingy! - @@ -15,6 +12,7 @@ + diff --git a/resources/Schema/Components/Trigger.xsd b/resources/Schema/Components/Trigger.xsd index a8bc8865..8119b966 100644 --- a/resources/Schema/Components/Trigger.xsd +++ b/resources/Schema/Components/Trigger.xsd @@ -4,5 +4,8 @@ + + Needs a Model or AABB component to work, uses AABB if both are attached. + \ No newline at end of file diff --git a/resources/Schema/Components/Weapon.xml b/resources/Schema/Components/Weapon.xml new file mode 100644 index 00000000..38c6fce9 --- /dev/null +++ b/resources/Schema/Components/Weapon.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/resources/Schema/Components/Weapon.xsd b/resources/Schema/Components/Weapon.xsd new file mode 100644 index 00000000..8bddd8a9 --- /dev/null +++ b/resources/Schema/Components/Weapon.xsd @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Entities/AnimatedArmy.xml b/resources/Schema/Entities/AnimatedArmy.xml index b711a0fe..67accc40 100644 --- a/resources/Schema/Entities/AnimatedArmy.xml +++ b/resources/Schema/Entities/AnimatedArmy.xml @@ -20,7 +20,7 @@ - models/dummyscene.mesh + Models/Test/DummyScene.mesh @@ -31,7 +31,7 @@ - models/animtest. + Models/Test/AnimTest.mesh @@ -42,7 +42,7 @@ - models/animTest.mesh + Models/Test/AnimTest.mesh @@ -53,7 +53,7 @@ - models/animTest.mesh + Models/Test/AnimTest.mesh @@ -64,7 +64,7 @@ - models/animTest.mesh + Models/Test/AnimTest.mesh @@ -91,7 +91,7 @@ - + @@ -154,7 +154,7 @@ - + diff --git a/resources/Schema/Entities/AnimationTests.xml b/resources/Schema/Entities/AnimationTests.xml new file mode 100644 index 00000000..77c87e64 --- /dev/null +++ b/resources/Schema/Entities/AnimationTests.xml @@ -0,0 +1,377 @@ + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + + + Models/DirectionalLightWidget.mesh + + + + + + + + + + + + Crouch + + 1 + + + Models/Asstest.mesh + + + + + + + + + + R_Leg_Top + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Leg_Bottom + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Foot + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Foot + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Leg_Bottom + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Leg_Top + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Hip + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_1 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_2 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_3 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Neck + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Shoulder + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Arm + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Hand + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Chin + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Hand + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/AnimationTests2.xml b/resources/Schema/Entities/AnimationTests2.xml new file mode 100644 index 00000000..6536a839 --- /dev/null +++ b/resources/Schema/Entities/AnimationTests2.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + Models/Widgets/Lights/DirectionalLightWidget.mesh + + + + + + + + + + + + Run + 0.5 + 0.78014858943309839 + 1 + 1 + StrafeRight + 0.5 + 0.78620929522779459 + ShootFastRifle + 0.13809128482706701 + 1 + + + AimRifle + + + + Models/Characters/Assault/AssaultAnimations.mesh + + true + + + + + + + + + + R_Arm_Weapon_Joint + + + + Models/Weapons/Blue/AssaultWeapon.mesh + + true + + + + + + + + + + + + + + 10 + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + + diff --git a/resources/Schema/Entities/AnimationTests3.xml b/resources/Schema/Entities/AnimationTests3.xml new file mode 100644 index 00000000..bd985b2d --- /dev/null +++ b/resources/Schema/Entities/AnimationTests3.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + Models/Widgets/Lights/DirectionalLightWidget.mesh + + + + + + + + + + + + Run + 0.5 + 0.97312056690160276 + 1 + 1 + ReloadSwitch + 0.91310356788604263 + LeftRight + 0 + 0.040207288496060478 + 1 + + + DownUp + + + + Models/Characters/Assault/FirstPerson.mesh + + true + + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeapon.mesh + + + + + + + + + + + + + + + + + + + + + 10 + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + + diff --git a/resources/Schema/Entities/AssetPedistal.xml b/resources/Schema/Entities/AssetPedistal.xml index 728a3028..3c816149 100644 --- a/resources/Schema/Entities/AssetPedistal.xml +++ b/resources/Schema/Entities/AssetPedistal.xml @@ -35,7 +35,7 @@ - Models/AssaultWeaponBlue.mesh + Models/Weapons/Blue/AssaultWeaponBlue.mesh diff --git a/resources/Schema/Entities/BoneMarker b/resources/Schema/Entities/BoneMarker new file mode 100644 index 00000000..eda56d56 --- /dev/null +++ b/resources/Schema/Entities/BoneMarker @@ -0,0 +1,22 @@ + + + + + + R_Leg_Top + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + diff --git a/resources/Schema/Entities/CapturePointHUDGroup b/resources/Schema/Entities/CapturePointHUDGroup new file mode 100644 index 00000000..9dce0ffb --- /dev/null +++ b/resources/Schema/Entities/CapturePointHUDGroup @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 2 + + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 3 + + + 0.80222018197612788 + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 4 + + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/CapturePointHUDHexagon.xml b/resources/Schema/Entities/CapturePointHUDHexagon.xml new file mode 100644 index 00000000..68cf42a7 --- /dev/null +++ b/resources/Schema/Entities/CapturePointHUDHexagon.xml @@ -0,0 +1,34 @@ + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + + 0.5 + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + diff --git a/resources/Schema/Entities/CaptureTest.xml b/resources/Schema/Entities/CaptureTest.xml index 5f657e51..3d678bd7 100644 --- a/resources/Schema/Entities/CaptureTest.xml +++ b/resources/Schema/Entities/CaptureTest.xml @@ -9,7 +9,7 @@ - ../assets/Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -41,7 +41,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -61,7 +61,7 @@ 1 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -81,7 +81,7 @@ 2 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -102,7 +102,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -120,7 +120,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -138,7 +138,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh diff --git a/resources/Schema/Entities/CaptureTestState1.xml b/resources/Schema/Entities/CaptureTestState1.xml index ffabd5c2..64999074 100644 --- a/resources/Schema/Entities/CaptureTestState1.xml +++ b/resources/Schema/Entities/CaptureTestState1.xml @@ -9,7 +9,7 @@ - ../assets/Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -42,7 +42,7 @@ 6.9158446328696002 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -63,7 +63,7 @@ 1 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -83,7 +83,7 @@ 2 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -104,7 +104,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -122,7 +122,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -140,7 +140,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh diff --git a/resources/Schema/Entities/CaptureTestState2.xml b/resources/Schema/Entities/CaptureTestState2.xml index 29abdfbd..6ddb306f 100644 --- a/resources/Schema/Entities/CaptureTestState2.xml +++ b/resources/Schema/Entities/CaptureTestState2.xml @@ -9,7 +9,7 @@ - ../assets/Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -41,7 +41,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -61,7 +61,7 @@ 1 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -79,7 +79,7 @@ 2 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -98,7 +98,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -116,7 +116,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -134,7 +134,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh diff --git a/resources/Schema/Entities/CaptureTestState3.xml b/resources/Schema/Entities/CaptureTestState3.xml index ff875dc4..3bed3624 100644 --- a/resources/Schema/Entities/CaptureTestState3.xml +++ b/resources/Schema/Entities/CaptureTestState3.xml @@ -9,7 +9,7 @@ - ../assets/Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -41,7 +41,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -61,7 +61,7 @@ 1 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -81,7 +81,7 @@ 2 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -101,7 +101,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -122,7 +122,7 @@ 4 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -140,7 +140,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -158,7 +158,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -176,7 +176,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -194,7 +194,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh diff --git a/resources/Schema/Entities/CaptureTestState4.xml b/resources/Schema/Entities/CaptureTestState4.xml index 740d7e7b..30db23aa 100644 --- a/resources/Schema/Entities/CaptureTestState4.xml +++ b/resources/Schema/Entities/CaptureTestState4.xml @@ -9,7 +9,7 @@ - ../assets/Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -41,7 +41,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -61,7 +61,7 @@ 1 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -79,7 +79,7 @@ 2 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -96,7 +96,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -115,7 +115,7 @@ 4 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -133,7 +133,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -151,7 +151,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -169,7 +169,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -187,7 +187,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh diff --git a/resources/Schema/Entities/CaptureTestState5.xml b/resources/Schema/Entities/CaptureTestState5.xml index f1b07a7b..8fe85068 100644 --- a/resources/Schema/Entities/CaptureTestState5.xml +++ b/resources/Schema/Entities/CaptureTestState5.xml @@ -17,7 +17,7 @@ - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -39,7 +39,7 @@ 1 - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -57,7 +57,7 @@ 2 - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -79,7 +79,7 @@ 3 - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -104,7 +104,7 @@ 4 - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -124,7 +124,7 @@ - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitCube.mesh + Models/Core/UnitCube.mesh @@ -143,7 +143,7 @@ - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitCube.mesh + Models/Core/UnitCube.mesh @@ -160,7 +160,7 @@ - C:\Users\123456\Workspace\TacticalZ\assets\Models\DummyScene.mesh + Models/Test/DummyScene.mesh diff --git a/resources/Schema/Entities/DoubleJumpHexagon.xml b/resources/Schema/Entities/DoubleJumpHexagon.xml new file mode 100644 index 00000000..c1aaec34 --- /dev/null +++ b/resources/Schema/Entities/DoubleJumpHexagon.xml @@ -0,0 +1,30 @@ + + + + + + Models/Effects/JumpEffectHexagon.mesh + + true + + + + + + + 0.5 + + + true + + + true + 0.5 + + true + + + + + + diff --git a/resources/Schema/Entities/EditorTestWorld.xml b/resources/Schema/Entities/EditorTestWorld.xml index 4727c777..46e6d54d 100755 --- a/resources/Schema/Entities/EditorTestWorld.xml +++ b/resources/Schema/Entities/EditorTestWorld.xml @@ -37,7 +37,7 @@ 0.80000001192092896 - Models/DirectionalLightWidget.mesh + Models/Widgets/Lights/DirectionalLightWidget.mesh 1 @@ -62,7 +62,7 @@ 3 - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -73,7 +73,7 @@ - Models/AssaultWeaponRed.mesh + Models/Weapons/Red/AssaultWeaponRed.mesh true @@ -86,7 +86,7 @@ - Models/DefenderGunRed.mesh + Models/Weapons/Red/DefenderGunRed.mesh true false @@ -115,7 +115,7 @@ 1 - models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh @@ -131,7 +131,7 @@ 1 - models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh @@ -157,7 +157,7 @@ - Models/Log.mesh + Models/Props/TreeLog.mesh @@ -176,7 +176,7 @@ - models/NormSpecIncdMapSphere.mesh + Models/Test/NormSpecIncdMapSphere.mesh @@ -260,7 +260,7 @@ - Models/NormalMapSphere.mesh + Models/Test/NormalMapSphere.mesh @@ -271,7 +271,7 @@ - Models/SpecularMapSphere.mesh + Models/Test/SpecularMapSphere.mesh @@ -313,7 +313,7 @@ - Models/IncandescenceMapSphere.mesh + Models/Test/IncandescenceMapSphere.mesh diff --git a/resources/Schema/Entities/EditorWidgetRotate.xml b/resources/Schema/Entities/EditorWidgetRotate.xml index 88452aac..1276f3e4 100644 --- a/resources/Schema/Entities/EditorWidgetRotate.xml +++ b/resources/Schema/Entities/EditorWidgetRotate.xml @@ -18,7 +18,7 @@ - Models/RotationWidgetX.mesh + Models/Widgets/Rotate/RotationWidgetX.mesh @@ -33,7 +33,7 @@ - Models/RotationWidgetY.mesh + Models/Widgets/Rotate/RotationWidgetY.mesh @@ -48,7 +48,7 @@ - Models/RotationWidgetZ.mesh + Models/Widgets/Rotate/RotationWidgetZ.mesh diff --git a/resources/Schema/Entities/EditorWidgetScale.xml b/resources/Schema/Entities/EditorWidgetScale.xml index 786b079e..65cb2b86 100644 --- a/resources/Schema/Entities/EditorWidgetScale.xml +++ b/resources/Schema/Entities/EditorWidgetScale.xml @@ -3,7 +3,7 @@ - Models/ScaleWidgetOrigin.mesh + Models/Widgets/Scale/ScalingWidgetOrigin.mesh @@ -20,7 +20,7 @@ - Models/ScaleWidgetX.mesh + Models/Widgets/Scale/ScalingWidgetX.mesh @@ -34,7 +34,7 @@ - Models/ScaleWidgetY.mesh + Models/Widgets/Scale/ScalingWidgetY.mesh @@ -48,7 +48,7 @@ - Models/ScaleWidgetZ.mesh + Models/Widgets/Scale/ScalingWidgetZ.mesh diff --git a/resources/Schema/Entities/EditorWidgetTranslate.xml b/resources/Schema/Entities/EditorWidgetTranslate.xml index c6dba4d9..e177b7e9 100644 --- a/resources/Schema/Entities/EditorWidgetTranslate.xml +++ b/resources/Schema/Entities/EditorWidgetTranslate.xml @@ -3,7 +3,7 @@ - Models/TranslationWidgetOrigin.mesh + Models/Widgets/Translate/TranslationWidgetOrigin.mesh @@ -18,7 +18,7 @@ - Models/TranslationWidgetX.mesh + Models/Widgets/Translate/TranslationWidgetX.mesh @@ -30,7 +30,7 @@ - Models/TranslationWidgetY.mesh + Models/Widgets/Translate/TranslationWidgetY.mesh @@ -42,7 +42,7 @@ - Models/TranslationWidgetZ.mesh + Models/Widgets/Translate/TranslationWidgetZ.mesh @@ -54,7 +54,7 @@ - Models/WidgetPlaneX.mesh + Models/Widgets/Translate/TranslationWidgetPlaneX.mesh @@ -66,7 +66,7 @@ - Models/WidgetPlaneY.mesh + Models/Widgets/Translate/TranslationWidgetPlaneY.mesh @@ -78,7 +78,7 @@ - Models/WidgetPlaneZ.mesh + Models/Widgets/Translate/TranslationWidgetPlaneZ.mesh diff --git a/resources/Schema/Entities/FastWorld.xml b/resources/Schema/Entities/FastWorld.xml index 1289d9d1..94df077d 100644 --- a/resources/Schema/Entities/FastWorld.xml +++ b/resources/Schema/Entities/FastWorld.xml @@ -3,7 +3,7 @@ - + @@ -18,23 +18,17 @@ - + - Run - - 1 + Crouch Walk + + 8 - - - - 0.95625903442123672 - - Models/AssaultAnimated.mesh diff --git a/resources/Schema/Entities/FirstPersonArms b/resources/Schema/Entities/FirstPersonArms new file mode 100644 index 00000000..bf749a4e --- /dev/null +++ b/resources/Schema/Entities/FirstPersonArms @@ -0,0 +1,57 @@ + + + + + + Run + 0.5 + 0.97312056690160276 + 1 + 1 + ReloadSwitch + 0.91310356788604263 + LeftRight + 0 + 0.040207288496060478 + 1 + + + DownUp + + + + Models/Characters/Assault/FirstPerson.mesh + + true + + + + + + + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeapon.mesh + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/GameMap.xml b/resources/Schema/Entities/GameMap.xml index e73cb69d..84a1e363 100644 --- a/resources/Schema/Entities/GameMap.xml +++ b/resources/Schema/Entities/GameMap.xml @@ -9,11 +9,12 @@ - + + - Models\MapVersion1.mesh + Models/LevelBase/MapVersion1.mesh @@ -25,7 +26,7 @@ 2 - Models/DirectionalLightWidget.mesh + Models/Widgets/Lights/DirectionalLightWidget.mesh false diff --git a/resources/Schema/Entities/Model.xml b/resources/Schema/Entities/Model.xml index 57856cbd..bee6b7e1 100644 --- a/resources/Schema/Entities/Model.xml +++ b/resources/Schema/Entities/Model.xml @@ -19,7 +19,7 @@ - models/animTest.mesh + Models/Test/AnimTest.mesh diff --git a/resources/Schema/Entities/MovementTest.xml b/resources/Schema/Entities/MovementTest.xml index f5197830..16a28684 100644 --- a/resources/Schema/Entities/MovementTest.xml +++ b/resources/Schema/Entities/MovementTest.xml @@ -26,7 +26,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -39,7 +39,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -52,9 +52,10 @@ + - Models/DirectionalLightWidget.mesh + sModels/Widgets/Lights/DirectionalLightWidget.mesh @@ -65,9 +66,6 @@ - - - Models/Test/ObstacleCourse.mesh @@ -96,7 +94,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -109,7 +107,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -171,7 +169,7 @@ - Models/Camera.mesh + Models/Widgets/Camera.mesh @@ -186,7 +184,7 @@ - Models/Camera.mesh + Models/Widgets/Camera.mesh false @@ -199,7 +197,7 @@ - Models/AssaultHeadless.mesh + Models/Characters/Assault/AssaultHeadless.mesh diff --git a/resources/Schema/Entities/NewMap.xml b/resources/Schema/Entities/NewMap.xml new file mode 100644 index 00000000..a79fee7b --- /dev/null +++ b/resources/Schema/Entities/NewMap.xml @@ -0,0 +1,2396 @@ + + + + + + + + + + + + + + + + + + Models/Props/Ground.mesh + + + + + + + + + Models/Props/Highground1.mesh + + + + + + + + + + Models/Props/Highground2.mesh + + + + + + + + + + Models/Props/Highground1.mesh + + + + + + + + + + + + Models/Props/Highground2.mesh + + + + + + + + + + + + Models/Props/Highground3.mesh + + + + + + + + + + Models/Props/Highground4.mesh + + + + + + + + + + Models/Props/Highground5.mesh + + + + + + + + + + Models/Props/Highground6.mesh + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar3.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar1.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar3.mesh + + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2.mesh + + + + + + + + + + + + + Models/Props/Pillars/SciFiPillar2.mesh + + + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + Models/Props/Pillars/StonePillar.mesh + + + + + + + + + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall4.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall3.mesh + + + + + + + + + + + + + Models/Props/Walls/SmallWall4.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall4.mesh + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + + + + Models/Props/Walls/SmallWall2.mesh + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + Models/Props/Walls/BigWall.mesh + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + + + + + + + + Models/Props/Bridges/WoodenBridge.mesh + + + + + + + + + + + + + + Models/Props/Bridges/WoodenBridge.mesh + + + + + + + + + + + + + + Models/Props/Bridges/WoodenBridge.mesh + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge.mesh + + + + + + + + + + + + + + Models/Props/Bridges/SciFiBridge.mesh + + + + + + + + + + + + + + Models/Props/Flora/TreeLog.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + Models/Props/Walls/MediumWall2.mesh + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + Models/Props/Walls/MediumWall3.mesh + + + + + + + + + + + + + + Models/Props/Pillars/SciFiBridgePillar1.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + Models/Props/Walls/MediumWall1.mesh + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + + Models/Props/Flora/TreeLog.mesh + + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + Models/Props/Stones/MediumStone1.mesh + + + + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + Models/Props/Stones/BigStone.mesh + + + + + + + + + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + Models/Props/PickUps/PickUpHolder.mesh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Props/CapturePoint.mesh + + + + + + + + + + + + + + + + + + + 1 + + + Models/Props/CapturePoint.mesh + + + + + + + + + + + + + + + 2 + + + Models/Props/CapturePoint.mesh + + + + + + + + + + + + + + 3 + + + Models/Props/CapturePoint.mesh + + + + + + + + + + + + + + + + + + 4 + + + Models/Props/CapturePoint.mesh + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + 10 + + + + + + + + + + 10 + + + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 10 + + + + + + + + + + + 1 + + + + + + + + + + + + + Models/Characters/Assault/AssaultTPose.mesh + + + + + + + + + + diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index 384ffb80..4ba23a0d 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -6,10 +6,11 @@ - - 2.0 - + + 600 + + @@ -19,12 +20,10 @@ - + - - - + @@ -32,7 +31,7 @@ - + @@ -53,7 +52,7 @@ - Models/Camera.mesh + Models/Widgets/Camera.mesh false @@ -92,7 +91,7 @@ - Models/CrosshairQuad.mesh + Models/Weapons/CrosshairQuad.mesh @@ -102,25 +101,48 @@ - + + + + + + Idle + 0.52743271827223559 + 1 + + + Models/Characters/Assault/FirstPerson.mesh + true + + + + + + + R_Arm_Weapon_Joint + - Models/AssaultWeaponRed.mesh + Models/Weapons/Blue/AssaultWeaponBlue.mesh - - + + - - - - - - - - - + + + + + Schema/Entities/RayBlue.xml + + + + + + + + @@ -130,7 +152,7 @@ - Models/Camera.mesh + Models/Widgets/Camera.mesh false @@ -143,18 +165,50 @@ - Hold Pos - - 1 + Idle + 0.69666320633760392 + 1 + + AimRifle + + - Models/AssaultAnimated.mesh - + Models/Characters/Assault/AssaultAnimations.mesh + - + + + + + R_Arm_Weapon_Joint + + + Models/Weapons/Blue/AssaultWeaponBlue.mesh + + + + + + + + + + + Schema/Entities/RayBlue.xml + + + + + + + + + + diff --git a/resources/Schema/Entities/QualityAssurance.xml b/resources/Schema/Entities/QualityAssurance.xml index e057cf38..40951468 100644 --- a/resources/Schema/Entities/QualityAssurance.xml +++ b/resources/Schema/Entities/QualityAssurance.xml @@ -40,7 +40,7 @@ - + @@ -97,7 +97,7 @@ 0.80000001192092896 - Models/DirectionalLightWidget.mesh + Models/Widgets/Lights/DirectionalLightWidget.mesh 1 @@ -105,7 +105,7 @@ - + @@ -120,13 +120,9 @@ - - Run - - 1 - + - models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh @@ -136,13 +132,9 @@ - - Walk - - 1 - + - models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh @@ -188,19 +180,15 @@ - + - - Run - - 1 - + - Models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh @@ -224,7 +212,7 @@ - models/NormSpecIncdMapSphere.mesh + Models/Test/NormSpecIncdMapSphere.mesh @@ -237,7 +225,7 @@ - + @@ -301,14 +289,14 @@ - + - Models/NormalMapSphere.mesh + Models/Test/NormalMapSphere.mesh @@ -319,7 +307,7 @@ - Models/SpecularMapSphere.mesh + Models/Test/SpecularMapSphere.mesh @@ -333,7 +321,7 @@ - + @@ -361,7 +349,7 @@ - Models/IncandescenceMapSphere.mesh + Models/Test/IncandescenceMapSphere.mesh @@ -422,7 +410,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -435,7 +423,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -448,7 +436,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -461,7 +449,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -493,7 +481,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -506,7 +494,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -519,7 +507,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -532,7 +520,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -586,7 +574,7 @@ true - + @@ -608,7 +596,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh true @@ -683,14 +671,14 @@ - + - Models/AssaultWeaponBlue.mesh + Models/Weapons/Blue/AssaultWeaponBlue.mesh @@ -730,14 +718,14 @@ - + - Models/AssaultWeaponRed.mesh + Models/Weapons/Red/AssaultWeaponRed.mesh @@ -790,14 +778,14 @@ - + - Models/SecondaryWeapon.mesh + Models/Weapons/SecondaryWeapon.mesh @@ -837,14 +825,14 @@ - + - Models/AssualtSoft.mesh + Models/Test/AssaultTPoseSoftEdge.mesh @@ -883,14 +871,14 @@ - + - Models/DefenderGunBlue.mesh + Models/Weapons/Blue/DefenderGunBlue.mesh @@ -930,14 +918,14 @@ - + - Models/DefenderGunRed.mesh + Models/Weapons/Red/DefenderGunRed.mesh @@ -977,14 +965,14 @@ - + - Models/Assualt.mesh + Models/Test/AssaultTPoseHardEdge.mesh @@ -1021,7 +1009,7 @@ - Models/CapturePoint.mesh + Models/Props/CapturePoint.mesh @@ -1035,10 +1023,11 @@ + 15 Models/Core/UnitCube.mesh - + true @@ -1073,7 +1062,7 @@ - Models/CapturePoint.mesh + Models/Props/CapturePoint.mesh @@ -1088,7 +1077,8 @@ Models/Core/UnitCube.mesh - + + true @@ -1118,7 +1108,7 @@ - Models/CapturePoint.mesh + Models/Props/CapturePoint.mesh @@ -1131,6 +1121,7 @@ Models/Core/UnitCube.mesh + true @@ -1161,7 +1152,7 @@ - Models/CapturePoint.mesh + Models/Props/CapturePoint.mesh @@ -1172,12 +1163,12 @@ - -12.033302729641917 3 Models/Core/UnitCube.mesh - + + true @@ -1207,7 +1198,7 @@ - Models/CapturePoint.mesh + Models/Props/CapturePoint.mesh @@ -1221,11 +1212,12 @@ + -15 4 Models/Core/UnitCube.mesh - + true @@ -1347,6 +1339,19 @@ + + + + ExplosionEffect Test + Fonts/DroidSans.ttf,64 + + + + + + + + @@ -1374,7 +1379,7 @@ - + @@ -1383,13 +1388,13 @@ true - 0.75008034908941568 + 0.75205058136495551 3.7999999523162842 true - Models/AssaultWeaponBlue.mesh + Models/Weapons/Blue/AssaultWeaponBlue.mesh true @@ -1430,7 +1435,7 @@ - + @@ -1439,10 +1444,10 @@ - 1.1999860997035228 + 1.2019563319790627 - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh true @@ -1482,27 +1487,23 @@ - + - - Walk - - 1 - + true - 0.68343188336345406 + 0.68540211563899389 true - Models/AssaultAnimated.mesh + Models/Characters/Assault/AssaultAnimated.mesh true @@ -1515,18 +1516,120 @@ - + - - ExplosionEffect Test - Fonts/DroidSans.ttf,64 - + + Models/Core/UnitCylinder.mesh + + - - + - + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + true + + + 0.95150063648635763 + 10 + + 3 + true + + + Models/Core/UnitSphere.mesh + + true + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + true + + + 1.3515288978624223 + true + 5 + true + + + Models/Assault.mesh + + true + + + + + + + + + + @@ -1553,6 +1656,495 @@ + + + + + + + + + + + Models/Core/UnitHexagon.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + false + + + 5 + + + + + + + + + + + + + + + + + + + + + + + Fonts/DroidSans.ttf,100 + + + + + + + + + + + + + + Models/Camera.mesh + false + + + + + + + + + + + + + + + + + + + 1 + + + + + Models/Core/UnitHexagon.mesh + + + + + + + + + + + + + + Models/CrosshairQuad.mesh + + + + + + + + + + + + + true + + 1.3682019578975679 + 3.7999999523162842 + + true + + + Models/AssaultWeaponRed.mesh + + + + + + + + + + + + + + + + + + + + + + + + + Models/Camera.mesh + false + + + + + + + + + + + + + + Models/AssaultAnimated.mesh + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + Models/Core/UnitCube.mesh + + false + + + + + + + + + + + + + + + + + + + + Models/Log.mesh + + + + + + + + + + + + Models/Props/Flora/AliveBush.mesh + true + + + + + + + + + + + + + + + Defender Shield Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + Textures/Props/FoliageDiff.png + + + + + + + + + Textures/Props/FoliageDiff.png + + + + + + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 2 + + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 3 + + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 4 + + + 1 + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + 1 + + + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + Textures/Core/UnitHexagon.png + + + + + + + + + + + + 1 + + + + Textures/Core/UnitHexagon_Rotated.png + + + + + + + + + + + + + + + + + + + + + + + + + Models/Widgets/Camera.mesh + + + + + + + + + diff --git a/resources/Schema/Entities/RayBlue.xml b/resources/Schema/Entities/RayBlue.xml index 4a0bb9d4..022d7769 100644 --- a/resources/Schema/Entities/RayBlue.xml +++ b/resources/Schema/Entities/RayBlue.xml @@ -6,12 +6,12 @@ 0.25 - Models/CylinderBullet.mesh - + Models/Effects/CylinderShot.mesh + true - + diff --git a/resources/Schema/Entities/RayRed.xml b/resources/Schema/Entities/RayRed.xml index e69df489..11a9b077 100644 --- a/resources/Schema/Entities/RayRed.xml +++ b/resources/Schema/Entities/RayRed.xml @@ -6,7 +6,7 @@ 0.25 - Models/CylinderBullet.mesh + Models/Weapons/CylinderBullet.mesh true diff --git a/resources/Schema/Entities/RenderingWorld.xml b/resources/Schema/Entities/RenderingWorld.xml index d9f7c62d..8bbc39f8 100644 --- a/resources/Schema/Entities/RenderingWorld.xml +++ b/resources/Schema/Entities/RenderingWorld.xml @@ -20,7 +20,7 @@ - Models/Assault.obj + Models/Characters/Assault/AssaultTPose.mesh @@ -35,7 +35,7 @@ 80 - Models/Camera.mesh + Models/Widgets/Camera.mesh @@ -60,6 +60,7 @@ Models/Core/UnitHexagon.mesh + true @@ -132,7 +133,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -308,7 +309,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -324,7 +325,7 @@ 0.10000000149011612 - Models/DirectionalLightWidget.mesh + Models/Widgets/Lights/DirectionalLightWidget.mesh @@ -358,6 +359,20 @@ + + + + Run + + 0.004999999888241291 + + + Models/SuperTest.mesh + + + + + diff --git a/resources/Schema/Entities/ShootEventTest.xml b/resources/Schema/Entities/ShootEventTest.xml index 9e9adf50..80dd2f35 100644 --- a/resources/Schema/Entities/ShootEventTest.xml +++ b/resources/Schema/Entities/ShootEventTest.xml @@ -9,7 +9,7 @@ - ../assets/Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -41,7 +41,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -61,7 +61,7 @@ 1 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -79,7 +79,7 @@ 2 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -96,7 +96,7 @@ 3 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -115,7 +115,7 @@ 4 - ../assets/Models/Core/UnitSphere.mesh + Models/Core/UnitSphere.mesh @@ -133,7 +133,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -151,7 +151,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -171,7 +171,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh @@ -191,7 +191,7 @@ - ../assets/Models/Core/UnitCube.mesh + Models/Core/UnitCube.mesh diff --git a/resources/Schema/Entities/Skeleton.xml b/resources/Schema/Entities/Skeleton.xml new file mode 100644 index 00000000..b8deb2eb --- /dev/null +++ b/resources/Schema/Entities/Skeleton.xml @@ -0,0 +1,497 @@ + + + + + + + + + + + + R_Arm_Weapon_Joint + + + + Models/Core/UnitCube.mesh + + true + + + + + + + + + + + + + R_Hand + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Arm + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Shoulder + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Neck + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_3 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_2 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Spine_1 + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Hip + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + L_Leg_Top + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Leg_Bottom + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Foot + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Toe + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Shoulder + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Arm + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Hand + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Shoulder_Armor_Joint + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Chin + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Head + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Perietal + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + L_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Leg_Bottom + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Leg_Top + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Foot + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Toe + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + R_Shoulder_Armor_Joint + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/SpawnPointClusterWithModels.xml b/resources/Schema/Entities/SpawnPointClusterWithModels.xml index 9c42d0e4..ea8e09d4 100644 --- a/resources/Schema/Entities/SpawnPointClusterWithModels.xml +++ b/resources/Schema/Entities/SpawnPointClusterWithModels.xml @@ -19,7 +19,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -31,7 +31,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -43,7 +43,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh @@ -55,7 +55,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh diff --git a/resources/Schema/Entities/SpawnerWithPlayerModel.xml b/resources/Schema/Entities/SpawnerWithPlayerModel.xml index 1274eefa..dbd93ed4 100644 --- a/resources/Schema/Entities/SpawnerWithPlayerModel.xml +++ b/resources/Schema/Entities/SpawnerWithPlayerModel.xml @@ -4,7 +4,7 @@ - Models/Assault.mesh + Models/Characters/Assault/AssaultTPose.mesh diff --git a/resources/Schema/Entities/SplatMapTesWorld.xml b/resources/Schema/Entities/SplatMapTesWorld.xml new file mode 100644 index 00000000..fe5718eb --- /dev/null +++ b/resources/Schema/Entities/SplatMapTesWorld.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + Models/Ground.mesh + + + + + + + + diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index 2cdf4e17..7f40e6de 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -6,7 +6,7 @@ - Models/DummyScene.mesh + Models/Test/DummyScene.mesh @@ -36,7 +36,7 @@ 0 - Models/Camera.mesh + Models/Widgets/Camera.mesh diff --git a/resources/Schema/Entities/Testingu b/resources/Schema/Entities/Testingu new file mode 100644 index 00000000..145550f4 --- /dev/null +++ b/resources/Schema/Entities/Testingu @@ -0,0 +1,45 @@ + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/aaaatestremoveme.xml b/resources/Schema/Entities/aaaatestremoveme.xml new file mode 100644 index 00000000..8da40b58 --- /dev/null +++ b/resources/Schema/Entities/aaaatestremoveme.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + Models/Core/Unithexagon.mesh + + + + + + + + + + + + + + + + + + + 2.2000000476837158 + + + + + + + + diff --git a/resources/Schema/Entities/aim_rays.xml b/resources/Schema/Entities/aim_rays.xml new file mode 100644 index 00000000..c8dac9a3 --- /dev/null +++ b/resources/Schema/Entities/aim_rays.xml @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + models/core/unitcube.mesh + + + + + + + + + + + + + + + + + + Models\Core\UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + + + 1 + + + Models\Core\UnitCube.mesh + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/awdawd b/resources/Schema/Entities/awdawd new file mode 100644 index 00000000..d8dacb54 --- /dev/null +++ b/resources/Schema/Entities/awdawd @@ -0,0 +1,23 @@ + + + + + + + L_Foot + true + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + diff --git a/resources/Schema/Entities/joint.xml b/resources/Schema/Entities/joint.xml new file mode 100644 index 00000000..912693f3 --- /dev/null +++ b/resources/Schema/Entities/joint.xml @@ -0,0 +1,22 @@ + + + + + + L_Elbow + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 028af9e6..ffe3421a 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -38,6 +38,11 @@ + + + + + diff --git a/resources/Shaders/DrawColorCorrection.frag.glsl b/resources/Shaders/DrawColorCorrection.frag.glsl index 91ace0c7..76db3e82 100644 --- a/resources/Shaders/DrawColorCorrection.frag.glsl +++ b/resources/Shaders/DrawColorCorrection.frag.glsl @@ -2,6 +2,8 @@ layout (binding = 0) uniform sampler2D SceneTexture; layout (binding = 1) uniform sampler2D BloomTexture; +layout (binding = 2) uniform sampler2D SceneTextureLowRes; +layout (binding = 3) uniform sampler2D BloomTextureLowRes; uniform float Exposure; uniform float Gamma; @@ -15,10 +17,19 @@ void main() { vec4 hdrColor = texture(SceneTexture, Input.TextureCoordinate); vec4 bloomColor = texture(BloomTexture, Input.TextureCoordinate); + vec4 hdrColorLowRes = texture(SceneTextureLowRes, Input.TextureCoordinate); + vec4 bloomColorLowRes = texture(BloomTextureLowRes, Input.TextureCoordinate); hdrColor += bloomColor; + hdrColorLowRes; + float hdrColorsum = hdrColorLowRes.r + hdrColorLowRes.g + hdrColorLowRes.b; //Toon mapping thingy - vec3 result = vec3(1.0) - exp(-hdrColor.rgb * Exposure); + vec3 result; + if(hdrColorsum > 0.0) { + result = vec3(1.0) - exp(-hdrColorLowRes.rgb * Exposure); + } else { + result = vec3(1.0) - exp(-hdrColor.rgb * Exposure); + } //gamme correction result = pow(result, vec3(1.0 / Gamma)); diff --git a/resources/Shaders/FillDepthBuffer.frag.glsl b/resources/Shaders/FillDepthBuffer.frag.glsl new file mode 100644 index 00000000..a125fc25 --- /dev/null +++ b/resources/Shaders/FillDepthBuffer.frag.glsl @@ -0,0 +1,11 @@ +#version 430 + +in VertexData{ + vec3 Position; +}Input; + +void main() +{ +} + + diff --git a/resources/Shaders/FillDepthBuffer.vert.glsl b/resources/Shaders/FillDepthBuffer.vert.glsl new file mode 100644 index 00000000..ff849790 --- /dev/null +++ b/resources/Shaders/FillDepthBuffer.vert.glsl @@ -0,0 +1,21 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +layout(location = 0) in vec3 Position; +layout(location = 5) in vec4 BoneIndices; +layout(location = 6) in vec4 BoneWeights; + + +out VertexData{ + vec3 Position; +}Output; + +void main() +{ + gl_Position = P * V * M * vec4(Position, 1.0); + + Output.Position = Position; +} \ No newline at end of file diff --git a/resources/Shaders/FillDepthBufferSkinned.vert.glsl b/resources/Shaders/FillDepthBufferSkinned.vert.glsl new file mode 100644 index 00000000..ce2a142d --- /dev/null +++ b/resources/Shaders/FillDepthBufferSkinned.vert.glsl @@ -0,0 +1,33 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform mat4 Bones[100]; + + +layout(location = 0) in vec3 Position; +layout(location = 5) in vec4 BoneIndices; +layout(location = 6) in vec4 BoneWeights; + + + +out VertexData{ + vec3 Position; +}Output; + +void main() +{ + 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])]; + } + + gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + + Output.Position = vec3(0.0); +} \ No newline at end of file diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index c09e0438..471ee20b 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -9,6 +9,11 @@ uniform vec2 ScreenDimensions; uniform vec4 FillColor; uniform vec4 AmbientColor; uniform float FillPercentage; + +uniform vec2 DiffuseUVRepeat; +uniform vec2 NormalUVRepeat; +uniform vec2 SpecularUVRepeat; +uniform vec2 GlowUVRepeat; layout (binding = 0) uniform sampler2D DiffuseTexture; layout (binding = 1) uniform sampler2D NormalMapTexture; layout (binding = 2) uniform sampler2D SpecularMapTexture; @@ -114,11 +119,11 @@ vec4 CalcNormalMappedValue(vec3 normal, vec3 tangent, vec3 bitangent, vec2 textu void main() { - vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate); - vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate); - vec4 specularTexel = texture2D(SpecularMapTexture, Input.TextureCoordinate); + vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate * DiffuseUVRepeat); + vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate * GlowUVRepeat); + vec4 specularTexel = texture2D(SpecularMapTexture, Input.TextureCoordinate * SpecularUVRepeat); vec4 position = V * M * vec4(Input.Position, 1.0); - vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate, NormalMapTexture); + vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate * NormalUVRepeat, NormalMapTexture); normal = normalize(normal); //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); vec4 viewVec = normalize(-position); diff --git a/resources/Shaders/ForwardPlus.vert.glsl b/resources/Shaders/ForwardPlus.vert.glsl index 3b3e931c..d475d825 100644 --- a/resources/Shaders/ForwardPlus.vert.glsl +++ b/resources/Shaders/ForwardPlus.vert.glsl @@ -3,15 +3,12 @@ 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 BoneIndices; -layout(location = 6) in vec4 BoneWeights; out VertexData{ vec3 Position; @@ -25,19 +22,9 @@ out VertexData{ void main() { - - - 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])]; - } - - gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + gl_Position = P*V*M * vec4(Position, 1.0); - Output.Position = (boneTransform * vec4(Position, 1.0)).xyz; + Output.Position = Position; Output.TextureCoordinate = TextureCoords; Output.Normal = vec3(M * vec4(Normal, 0.0)); Output.Tangent = vec3(M * vec4(Tangent, 0.0)); diff --git a/resources/Shaders/ForwardPlusSkinned.vert.glsl b/resources/Shaders/ForwardPlusSkinned.vert.glsl new file mode 100644 index 00000000..5fd55a8c --- /dev/null +++ b/resources/Shaders/ForwardPlusSkinned.vert.glsl @@ -0,0 +1,46 @@ +#version 430 + +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 BoneIndices; +layout(location = 6) in vec4 BoneWeights; + +out VertexData{ + vec3 Position; + vec3 Normal; + vec3 Tangent; + vec3 BiTangent; + vec2 TextureCoordinate; + vec4 ExplosionColor; + float ExplosionPercentageElapsed; +}Output; + +void main() +{ + 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])]; + } + + gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + + Output.Position = (boneTransform * vec4(Position, 1.0)).xyz; + Output.TextureCoordinate = TextureCoords; + Output.Normal = vec3(M * boneTransform * vec4(Normal, 0.0)); + Output.Tangent = vec3(M * vec4(Tangent, 0.0)); + Output.BiTangent = vec3(M * vec4(BiTangent, 0.0)); + Output.ExplosionColor = vec4(1.0); + Output.ExplosionPercentageElapsed = 0.0; +} \ No newline at end of file diff --git a/resources/Shaders/ForwardPlusSplatMap.frag.glsl b/resources/Shaders/ForwardPlusSplatMap.frag.glsl new file mode 100644 index 00000000..239c51b5 --- /dev/null +++ b/resources/Shaders/ForwardPlusSplatMap.frag.glsl @@ -0,0 +1,277 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform vec2 ScreenDimensions; +uniform float FillPercentage; +uniform vec4 DiffuseColor; +uniform vec4 FillColor; +uniform vec4 Color; +uniform vec4 AmbientColor; + +//Get bineded at the same time as the textures +uniform vec2 DiffuseUVRepeat1; +uniform vec2 DiffuseUVRepeat2; +uniform vec2 DiffuseUVRepeat3; +uniform vec2 DiffuseUVRepeat4; +uniform vec2 DiffuseUVRepeat5; +uniform vec2 NormalUVRepeat1; +uniform vec2 NormalUVRepeat2; +uniform vec2 NormalUVRepeat3; +uniform vec2 NormalUVRepeat4; +uniform vec2 NormalUVRepeat5; +uniform vec2 SpecularUVRepeat1; +uniform vec2 SpecularUVRepeat2; +uniform vec2 SpecularUVRepeat3; +uniform vec2 SpecularUVRepeat4; +uniform vec2 SpecularUVRepeat5; +uniform vec2 GlowUVRepeat1; +uniform vec2 GlowUVRepeat2; +uniform vec2 GlowUVRepeat3; +uniform vec2 GlowUVRepeat4; +uniform vec2 GlowUVRepeat5; +layout (binding = 0) uniform sampler2D SplatMapTexture; +layout (binding = 1) uniform sampler2D DiffuseTexture1; +layout (binding = 2) uniform sampler2D DiffuseTexture2; +layout (binding = 3) uniform sampler2D DiffuseTexture3; +layout (binding = 4) uniform sampler2D DiffuseTexture4; +layout (binding = 5) uniform sampler2D DiffuseTexture5; +layout (binding = 6) uniform sampler2D NormalMapTexture1; +layout (binding = 7) uniform sampler2D NormalMapTexture2; +layout (binding = 8) uniform sampler2D NormalMapTexture3; +layout (binding = 9) uniform sampler2D NormalMapTexture4; +layout (binding = 10) uniform sampler2D NormalMapTexture5; +layout (binding = 11) uniform sampler2D SpecularMapTexture1; +layout (binding = 12) uniform sampler2D SpecularMapTexture2; +layout (binding = 13) uniform sampler2D SpecularMapTexture3; +layout (binding = 14) uniform sampler2D SpecularMapTexture4; +layout (binding = 15) uniform sampler2D SpecularMapTexture5; +layout (binding = 16) uniform sampler2D GlowMapTexture1; +layout (binding = 17) uniform sampler2D GlowMapTexture2; +layout (binding = 18) uniform sampler2D GlowMapTexture3; +layout (binding = 19) uniform sampler2D GlowMapTexture4; +layout (binding = 20) uniform sampler2D GlowMapTexture5; + +#define TILE_SIZE 16 + +struct LightSource { + vec4 Position; + vec4 Direction; + vec4 Color; + float Radius; + float Intensity; + float Falloff; + int Type; +}; + +layout (std430, binding = 1) buffer LightBuffer +{ + LightSource List[]; +} LightSources; + +struct LightGrid { + float Start; + float Amount; + vec2 Padding; +}; + +layout (std430, binding = 2) buffer LightGridBuffer +{ + LightGrid Data[]; +} LightGrids; + +layout (std430, binding = 4) buffer LightIndexBuffer +{ + float LightIndex[]; +}; + + +in VertexData{ + vec3 Position; + vec3 Normal; + vec3 Tangent; + vec3 BiTangent; + vec2 TextureCoordinate; + vec4 ExplosionColor; + float ExplosionPercentageElapsed; +}Input; + +out vec4 sceneColor; +out vec4 bloomColor; + +struct LightResult { + vec4 Diffuse; + vec4 Specular; +}; + +float CalcAttenuation(float radius, float dist, float falloff) { + return 1.0 - smoothstep(radius * 0.3, radius, dist); +} + +vec4 CalcSpecular(vec4 lightColor, vec4 viewVec, vec4 lightVec, vec4 normal) { + vec4 R = normalize( reflect(-lightVec, normal)); + float RdotV = max( dot(R, viewVec), 0.0); + return lightColor * pow(RdotV, 90.0); +} + +vec4 CalcDiffuse(vec4 lightColor, vec4 lightVec, vec4 normal) { + float power = max( dot(normal, lightVec), 0.0); + return lightColor * power; +} + +LightResult CalcPointLightSource(vec4 lightPos, float lightRadius, vec4 lightColor, float intensity, vec4 viewVec, vec4 position, vec4 normal, float falloff) +{ + vec4 L = lightPos - position; + float dist = length(L); + L = normalize(L); + + float attenuation = CalcAttenuation(lightRadius, dist, falloff); + + LightResult result; + result.Diffuse = CalcDiffuse(lightColor, L, normal) * attenuation * intensity; + result.Specular = CalcSpecular(lightColor, viewVec, L, normal) * attenuation * intensity; + return result; +} + +LightResult CalcDirectionalLightSource(vec4 direction, vec4 color, float intensity, vec4 viewVec, vec4 vertNormal) +{ + vec4 L = normalize( -vec4(direction.xyz, 0) ); + + LightResult result; + result.Diffuse = CalcDiffuse(color, L, vertNormal) * intensity; + result.Specular = CalcSpecular(color, viewVec, L, vertNormal) * intensity; + 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); +} + +vec4 CalcBlendedTexel(vec4 blendValue, sampler2D R, sampler2D G, sampler2D B, sampler2D A, sampler2D D, + vec2 R_TileValues, vec2 G_TileValues, vec2 B_TileValues, vec2 A_TileValues, vec2 D_TileValues){ + vec4 R_Channel = texture2D(R, Input.TextureCoordinate * R_TileValues); + vec4 G_Channel = texture2D(G, Input.TextureCoordinate * G_TileValues); + vec4 B_Channel = texture2D(B, Input.TextureCoordinate * B_TileValues); + vec4 A_Channel = texture2D(A, Input.TextureCoordinate * A_TileValues); + vec4 D_Channel = texture2D(D, Input.TextureCoordinate * D_TileValues); + + float total = blendValue.r + blendValue.g + blendValue.b + blendValue.a; + if(total > 1.0f){ + float totalDiv = 1.0f / total; + blendValue.r = blendValue.r * totalDiv; + blendValue.g = blendValue.g * totalDiv; + blendValue.b = blendValue.b * totalDiv; + blendValue.a = blendValue.a * totalDiv; + } + float D_percent = clamp( 1.0f - total, 0.0f, 1.0f); + + return blendValue.r * R_Channel + + blendValue.g * G_Channel + + blendValue.b * B_Channel + + blendValue.a * A_Channel + + D_percent * D_Channel; +} + +vec4 CalcBlendedNormal(vec4 blendValue, sampler2D R, sampler2D G, sampler2D B, sampler2D A, sampler2D D, + vec2 R_TileValues, vec2 G_TileValues, vec2 B_TileValues, vec2 A_TileValues, vec2 D_TileValues){ + mat3 TBN = mat3(Input.Tangent, Input.BiTangent, Input.Normal); + vec3 R_Channel = texture(R, Input.TextureCoordinate * R_TileValues).xyz * 2.0 - vec3(1.0); + vec3 G_Channel = texture(G, Input.TextureCoordinate * G_TileValues).xyz * 2.0 - vec3(1.0); + vec3 B_Channel = texture(B, Input.TextureCoordinate * B_TileValues).xyz * 2.0 - vec3(1.0); + vec3 A_Channel = texture(A, Input.TextureCoordinate * A_TileValues).xyz * 2.0 - vec3(1.0); + vec3 D_Channel = texture(D, Input.TextureCoordinate * D_TileValues).xyz * 2.0 - vec3(1.0); + + float total = blendValue.r + blendValue.g + blendValue.b + blendValue.a; + if(total > 1.0f){ + float totalDiv = 1 / total; + blendValue.r = blendValue.r * totalDiv; + blendValue.g = blendValue.g * totalDiv; + blendValue.b = blendValue.b * totalDiv; + blendValue.a = blendValue.a * totalDiv; + } + float D_percent = clamp( 1.0f - total, 0.0f, 1.0f); + + vec3 Normal_result = blendValue.r * R_Channel + + blendValue.g * G_Channel + + blendValue.b * B_Channel + + blendValue.a * A_Channel + + D_percent * D_Channel; + + return vec4(TBN * normalize(Normal_result), 0.0); +} + +void main() +{ + vec4 splatTexel = texture2D(SplatMapTexture, Input.TextureCoordinate); + + vec4 diffuseTexel = CalcBlendedTexel(splatTexel, DiffuseTexture1, DiffuseTexture2, DiffuseTexture3, DiffuseTexture4, DiffuseTexture5, + DiffuseUVRepeat1, DiffuseUVRepeat2, DiffuseUVRepeat3, DiffuseUVRepeat4, DiffuseUVRepeat5); + vec4 glowTexel = CalcBlendedTexel(splatTexel, GlowMapTexture1, GlowMapTexture2, GlowMapTexture3, GlowMapTexture4, GlowMapTexture5, + GlowUVRepeat1, GlowUVRepeat2, GlowUVRepeat3, GlowUVRepeat4, GlowUVRepeat5); + vec4 specularTexel = CalcBlendedTexel(splatTexel, SpecularMapTexture1, SpecularMapTexture2, SpecularMapTexture3, SpecularMapTexture4, SpecularMapTexture5, + SpecularUVRepeat1, SpecularUVRepeat2, SpecularUVRepeat3, SpecularUVRepeat4, SpecularUVRepeat5); + vec4 position = V * M * vec4(Input.Position, 1.0); + //vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate, SplatMapTexture); + vec4 normal = V * CalcBlendedNormal(splatTexel, NormalMapTexture1, NormalMapTexture2, NormalMapTexture3, NormalMapTexture4, NormalMapTexture5, + NormalUVRepeat1, NormalUVRepeat2, NormalUVRepeat3, NormalUVRepeat4, NormalUVRepeat5); + normal = normalize(normal); + //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); + vec4 viewVec = normalize(-position); + + vec2 tilePos; + tilePos.x = int(gl_FragCoord.x/TILE_SIZE); + tilePos.y = int(gl_FragCoord.y/TILE_SIZE); + + LightResult totalLighting; + totalLighting.Diffuse = vec4(AmbientColor.rgb, 1.0); + int currentTile = int(floor(gl_FragCoord.x/TILE_SIZE) + (floor(gl_FragCoord.y/TILE_SIZE) * int(ScreenDimensions.x/TILE_SIZE))); + + int start = int(LightGrids.Data[currentTile].Start); + int amount = int(LightGrids.Data[currentTile].Amount); + + for(int i = start; i < start + amount; i++) { + + int l = int(LightIndex[i]); + LightSource light = LightSources.List[l]; + + LightResult light_result; + //These if statements should be removed. + if(light.Type == 1) { // point + light_result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, position, normal, light.Falloff); + } else if (light.Type == 2) { //Directional + light_result = CalcDirectionalLightSource(V * light.Direction, light.Color, light.Intensity, viewVec, normal); + } + totalLighting.Diffuse += light_result.Diffuse; + totalLighting.Specular += light_result.Specular; + } + + vec4 color_result = mix((Color * diffuseTexel * DiffuseColor), Input.ExplosionColor, Input.ExplosionPercentageElapsed); + color_result = color_result * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)); + //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*3; + + bloomColor = vec4(clamp(color_result.xyz - 1.0, 0, 100), 1.0); + + //Tiled Debug Code + /* + if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) { + sceneColor += vec4(0.5, 0, 0, 0); + } else { + sceneColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/LightSources.List.length(), 0, 0, 1); + } + */ +} + + diff --git a/resources/Shaders/Picking.vert.glsl b/resources/Shaders/Picking.vert.glsl index 205a8fdd..f888cd16 100644 --- a/resources/Shaders/Picking.vert.glsl +++ b/resources/Shaders/Picking.vert.glsl @@ -3,15 +3,12 @@ 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 BoneIndices; -layout(location = 6) in vec4 BoneWeights; out VertexData{ vec3 Position; @@ -19,14 +16,6 @@ out VertexData{ void main() { - 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])]; - } - - gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); - Output.Position = (boneTransform * vec4(Position, 1.0)).xyz; + gl_Position = P*V*M * vec4(Position, 1.0); + Output.Position = Position, 1.0; } \ No newline at end of file diff --git a/resources/Shaders/PickingSkinned.vert.glsl b/resources/Shaders/PickingSkinned.vert.glsl new file mode 100644 index 00000000..205a8fdd --- /dev/null +++ b/resources/Shaders/PickingSkinned.vert.glsl @@ -0,0 +1,32 @@ +#version 430 + +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 BoneIndices; +layout(location = 6) in vec4 BoneWeights; + +out VertexData{ + vec3 Position; +}Output; + +void main() +{ + 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])]; + } + + 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/resources/Shaders/ShieldStencil.frag.glsl b/resources/Shaders/ShieldStencil.frag.glsl new file mode 100644 index 00000000..db88ab24 --- /dev/null +++ b/resources/Shaders/ShieldStencil.frag.glsl @@ -0,0 +1,15 @@ +#version 430 + +in VertexData{ + vec3 Position; +}Input; + + +out vec4 fragmentColor; + +void main() +{ + fragmentColor = vec4(0.5, 0.0, 0.0, 0.0); +} + + diff --git a/resources/Shaders/ShieldStencil.vert.glsl b/resources/Shaders/ShieldStencil.vert.glsl new file mode 100644 index 00000000..b6669f2c --- /dev/null +++ b/resources/Shaders/ShieldStencil.vert.glsl @@ -0,0 +1,19 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +layout(location = 0) in vec3 Position; + + +out VertexData{ + vec3 Position; +}Output; + +void main() +{ + gl_Position = P * V * M * vec4(Position, 1.0); + + Output.Position = Position; +} \ No newline at end of file diff --git a/resources/Shaders/ShieldStencilSkinned.vert.glsl b/resources/Shaders/ShieldStencilSkinned.vert.glsl new file mode 100644 index 00000000..ce2a142d --- /dev/null +++ b/resources/Shaders/ShieldStencilSkinned.vert.glsl @@ -0,0 +1,33 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform mat4 Bones[100]; + + +layout(location = 0) in vec3 Position; +layout(location = 5) in vec4 BoneIndices; +layout(location = 6) in vec4 BoneWeights; + + + +out VertexData{ + vec3 Position; +}Output; + +void main() +{ + 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])]; + } + + gl_Position = P*V*M*boneTransform * vec4(Position, 1.0); + + Output.Position = vec3(0.0); +} \ No newline at end of file diff --git a/resources/Shaders/Sprite.frag.glsl b/resources/Shaders/Sprite.frag.glsl index c391322d..a1ff3025 100644 --- a/resources/Shaders/Sprite.frag.glsl +++ b/resources/Shaders/Sprite.frag.glsl @@ -30,12 +30,11 @@ void main() float pos = ((P * vec4(Input.Position, 1)).y + 1.0)/2.0; if(pos <= FillPercentage) { - color_result += FillColor; + color_result = FillColor*diffuseTexel.a; } sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); - color_result += glowTexel*3; - bloomColor = vec4(clamp(color_result.xyz - 1.0, 0, 100), 1.0); + bloomColor = vec4(clamp((glowTexel.xyz*3) - 1.0, 0, 100), 1.0); } diff --git a/resources/Shaders/Sprite.vert.glsl b/resources/Shaders/Sprite.vert.glsl index 61b387ad..c09d745b 100644 --- a/resources/Shaders/Sprite.vert.glsl +++ b/resources/Shaders/Sprite.vert.glsl @@ -16,6 +16,7 @@ out VertexData{ void main() { + gl_Position = P * V * M * vec4(Position, 1.0); Output.Position = Position; diff --git a/src/Engine/CMakeLists.txt b/src/Engine/CMakeLists.txt index 1ed39177..19763310 100644 --- a/src/Engine/CMakeLists.txt +++ b/src/Engine/CMakeLists.txt @@ -3,7 +3,7 @@ project(TacticalZ-Engine) find_package(OpenGL REQUIRED) find_package(GLEW REQUIRED) find_package(GLFW REQUIRED) -find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono) +find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono program_options) find_package(assimp REQUIRED) find_package(ZLIB REQUIRED) find_package(PNG REQUIRED) diff --git a/src/Engine/Collision/CollidableOctreeSystem.cpp b/src/Engine/Collision/CollidableOctreeSystem.cpp deleted file mode 100644 index 476414dd..00000000 --- a/src/Engine/Collision/CollidableOctreeSystem.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "Collision/CollidableOctreeSystem.h" - -void CollidableOctreeSystem::Update(double dt) -{ - m_Octree->ClearDynamicObjects(); -} - -void CollidableOctreeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) -{ - if (entity.HasComponent("AABB")) { - boost::optional absoluteAABB = Collision::EntityAbsoluteAABB(entity); - if (absoluteAABB) { - m_Octree->AddDynamicObject(*absoluteAABB); - } - } else if (entity.HasComponent("Model")) { - // TODO: Derive AABB from model - } -} \ No newline at end of file diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index fe4eb5e0..b7b21969 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -1,4 +1,5 @@ #include +#include #include "Collision/Collision.h" #include "Engine/GLM.h" @@ -183,7 +184,7 @@ bool RayVsTriangle(const Ray& ray, } outDistance = dist; outUCoord = glm::dot(m, DxE2) * DetInv; - outVCoord = glm::dot(ray.Direction(), MxE1) * DetInv; + outVCoord = glm::dot(ray.Direction(), MxE1) * DetInv; //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem //If u and v are positive, u+v <= 1, dist is positive, and less than closest. @@ -330,7 +331,7 @@ bool rectangleVsTriangle(const glm::vec2& boxMin, float push = rightRes < -leftRes ? rightRes : leftRes; float absPushSq = abs(push); absPushSq *= absPushSq; - + if (absPushSq < resolutionDistanceSq) { resolutionDistanceSq = absPushSq; resolutionDirection = push * normal; @@ -355,8 +356,8 @@ constexpr bool FaceIsGround(float faceNormalY) //An array containing 3 int pairs { 0, 2 }, { 0, 1 }, { 1, 2 } constexpr std::array, 3> dimensionPairs({ std::pair(0, 2), std::pair(0, 1), std::pair(1, 2) }); -bool AABBvsTriangle(const AABB& box, - const std::array& triPos, +bool AABBvsTriangle(const AABB& box, + const std::array& triPos, const glm::vec3& originalBoxVelocity, float verticalStepHeight, bool& isOnGround, @@ -385,7 +386,7 @@ bool AABBvsTriangle(const AABB& box, Resolution() : DistanceSq(INFINITY) , Vector(0.f) - {} + { } BoxTriResolveCase Case; float DistanceSq; glm::vec3 Vector; @@ -525,9 +526,9 @@ bool AABBvsTriangle(const AABB& box, return true; } -bool AABBvsTriangles(const AABB& box, - const std::vector& modelVertices, - const std::vector& modelIndices, +bool AABBvsTriangles(const AABB& box, + const RawModel::Vertex* modelVertices, + const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& boxVelocity, float verticalStepHeight, @@ -564,52 +565,77 @@ bool AABBvsTriangles(const AABB& box, return hit; } -bool attachAABBComponentFromModel(World* world, EntityID id) +boost::optional EntityAbsoluteAABB(EntityWrapper& entity, bool takeModelBox) { - if (!world->HasComponent(id, "Model")) { - return false; - } - ComponentWrapper model = world->GetComponent(id, "Model"); - ComponentWrapper collision = world->AttachComponent(id, "AABB"); - Model* modelRes = ResourceManager::Load(model["Resource"]); - if (modelRes == nullptr) { - return false; - } - - glm::mat4 modelMatrix = modelRes->Matrix(); - - glm::vec3 mini = glm::vec3(INFINITY, INFINITY, INFINITY); - glm::vec3 maxi = glm::vec3(-INFINITY, -INFINITY, -INFINITY); - for (const auto& v : modelRes->Vertices()) { - const auto& wPos = modelMatrix * glm::vec4(v.Position.x, v.Position.y, v.Position.z, 1); - maxi.x = std::max(wPos.x, maxi.x); - maxi.y = std::max(wPos.y, maxi.y); - maxi.z = std::max(wPos.z, maxi.z); - mini.x = std::min(wPos.x, mini.x); - mini.y = std::min(wPos.y, mini.y); - mini.z = std::min(wPos.z, mini.z); - } - collision["Origin"] = 0.5f * (maxi + mini); - collision["Size"] = maxi - mini; - return true; -} - -boost::optional EntityAbsoluteAABB(EntityWrapper& entity) -{ - if (!entity.HasComponent("AABB")) { + AABB modelSpaceBox; + if (entity.HasComponent("AABB") && !takeModelBox) { + ComponentWrapper& cAABB = entity["AABB"]; + modelSpaceBox = EntityAABB::FromOriginSize((glm::vec3)cAABB["Origin"], (glm::vec3)cAABB["Size"]); + } else if (entity.HasComponent("Model")) { + Model* model; + std::string res = entity["Model"]["Resource"]; + if (res.empty()) { + return boost::none; + } + try { + model = ResourceManager::Load<::Model, true>(res); + } catch (const Resource::StillLoadingException&) { + return boost::none; + } catch (const std::exception&) { + return boost::none; + } + modelSpaceBox = model->Box(); + } else { return boost::none; } - ComponentWrapper& cAABB = entity["AABB"]; - glm::vec3 absPosition = Transform::AbsolutePosition(entity.World, entity.ID); - 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; + glm::mat4 modelMat = Transform::AbsoluteTransformation(entity); + glm::vec3 mini(INFINITY); + glm::vec3 maxi(-INFINITY); + glm::vec3 maxCorner = modelSpaceBox.MaxCorner(); + glm::vec3 minCorner = modelSpaceBox.MinCorner(); + for (int i = 0; i < 8; ++i) { + std::bitset<3> bits(i); + glm::vec3 corner; + corner.x = bits.test(0) ? maxCorner.x : minCorner.x; + corner.y = bits.test(1) ? maxCorner.y : minCorner.y; + corner.z = bits.test(2) ? maxCorner.z : minCorner.z; + corner = Transform::TransformPoint(corner, modelMat); + mini = glm::min(mini, corner); + maxi = glm::max(maxi, corner); + } + + EntityAABB aabb; + aabb = AABB(mini, maxi); - EntityAABB aabb = EntityAABB::FromOriginSize(origin, size); aabb.Entity = entity; - return aabb; } +boost::optional AbsoluteAABBExplosionEffect(EntityWrapper& entity) +{ + boost::optional modelBox = EntityAbsoluteAABB(entity, true); + if (!modelBox) { + return boost::none; + } + bool isRandom = (bool)entity["ExplosionEffect"]["Randomness"]; + float random = isRandom ? (float)(double)entity["ExplosionEffect"]["RandomnessScalar"] : 0; + glm::vec3 origin = (glm::vec3)entity["ExplosionEffect"]["ExplosionOrigin"]; + glm::vec3 randomVel = (glm::vec3)entity["ExplosionEffect"]["Velocity"]; + randomVel *= (random + 1); + float endVelocity = randomVel.y; + if ((bool)entity["ExplosionEffect"]["ExponentialAccelaration"]) { + endVelocity *= endVelocity / 2.f; + } + float maxRadius = (float)(double)entity["ExplosionEffect"]["ExplosionDuration"] * endVelocity; + glm::vec3 size; + AABB explosionBox(origin - (size / 2.f), origin + (size / 2.f)); + + glm::vec3 mini = glm::min(explosionBox.MinCorner(), (*modelBox).MinCorner()); + glm::vec3 maxi = glm::max(explosionBox.MaxCorner(), (*modelBox).MaxCorner()); + EntityAABB aabb = AABB(mini, maxi); + aabb.Entity = entity; + return aabb; } + +} \ No newline at end of file diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index b5d7a1f0..afd09022 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -20,6 +20,7 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c // Collide against octree items m_OctreeResult.clear(); m_Octree->ObjectsInSameRegion(*boundingBox, m_OctreeResult); + bool everHitTheGround = false; for (auto& boxB : m_OctreeResult) { glm::vec3 resolutionVector; if (boxA.Entity == boxB.Entity) { @@ -40,20 +41,27 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c glm::vec3 inOutVelocity = (glm::vec3)cPhysics["Velocity"]; bool isOnGround = (bool)cPhysics["IsOnGround"]; float verticalStepHeight = (float)(double)cPhysics["VerticalStepHeight"]; - if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) { + if (Collision::AABBvsTriangles(boxA, model->Vertices(), model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) { (glm::vec3&)cTransform["Position"] += resolutionVector; cPhysics["Velocity"] = inOutVelocity; - (bool)cPhysics["IsOnGround"] = isOnGround; - } else { - (bool)cPhysics["IsOnGround"] = false; + if (isOnGround) { + everHitTheGround = true; + (bool)cPhysics["IsOnGround"] = true; + } } } else if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { //Enter here if boxB has no Model. (glm::vec3&)cTransform["Position"] += resolutionVector; - (bool)cPhysics["IsOnGround"] = resolutionVector.y > 0; - if ((bool)cPhysics["IsOnGround"]){ + if (resolutionVector.y > 0) { + everHitTheGround = true; + (bool)cPhysics["IsOnGround"] = true; ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; } } } + + //This should apply air friction and such, iff zero models were hit. + if (!everHitTheGround) { + (bool)cPhysics["IsOnGround"] = false; + } } diff --git a/src/Engine/Collision/FillFrustumOctreeSystem.cpp b/src/Engine/Collision/FillFrustumOctreeSystem.cpp new file mode 100644 index 00000000..2be8bee0 --- /dev/null +++ b/src/Engine/Collision/FillFrustumOctreeSystem.cpp @@ -0,0 +1,19 @@ +#include "Collision/FillFrustumOctreeSystem.h" + +void FillFrustumOctreeSystem::Update(double dt) +{ + m_Octree->ClearDynamicObjects(); +} + +void FillFrustumOctreeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) +{ + boost::optional absoluteAABB; + if (entity.HasComponent("ExplosionEffect")) { + absoluteAABB = Collision::AbsoluteAABBExplosionEffect(entity); + } else { + absoluteAABB = Collision::EntityAbsoluteAABB(entity, true); + } + if (absoluteAABB) { + m_Octree->AddDynamicObject(*absoluteAABB); + } +} diff --git a/src/Engine/Collision/FillOctreeSystem.cpp b/src/Engine/Collision/FillOctreeSystem.cpp new file mode 100644 index 00000000..a727eb86 --- /dev/null +++ b/src/Engine/Collision/FillOctreeSystem.cpp @@ -0,0 +1,14 @@ +#include "Collision/FillOctreeSystem.h" + +void FillOctreeSystem::Update(double dt) +{ + m_Octree->ClearDynamicObjects(); +} + +void FillOctreeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) +{ + boost::optional absoluteAABB = Collision::EntityAbsoluteAABB(entity); + if (absoluteAABB) { + m_Octree->AddDynamicObject(*absoluteAABB); + } +} \ No newline at end of file diff --git a/src/Engine/Collision/TriggerSystem.cpp b/src/Engine/Collision/TriggerSystem.cpp index 410a7fa1..21a47721 100644 --- a/src/Engine/Collision/TriggerSystem.cpp +++ b/src/Engine/Collision/TriggerSystem.cpp @@ -5,7 +5,6 @@ void TriggerSystem::UpdateComponent(EntityWrapper& triggerEntity, ComponentWrapper& cTrigger, double dt) { - // 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; diff --git a/src/Engine/Core/ComponentPool.cpp b/src/Engine/Core/ComponentPool.cpp index f4ca9f4a..7b465fbc 100644 --- a/src/Engine/Core/ComponentPool.cpp +++ b/src/Engine/Core/ComponentPool.cpp @@ -47,7 +47,7 @@ ComponentWrapper ComponentPool::Allocate(EntityID entity) ComponentWrapper ComponentPool::GetByEntity(EntityID ent) { - return ComponentWrapper(m_ComponentInfo, m_EntityToComponent.at(ent)); + return ComponentWrapper(m_ComponentInfo, m_EntityToComponent.at(ent)); } bool ComponentPool::KnowsEntity(EntityID ent) diff --git a/src/Engine/Core/EntityFile.cpp b/src/Engine/Core/EntityFile.cpp index 0d97d4ae..3987b092 100644 --- a/src/Engine/Core/EntityFile.cpp +++ b/src/Engine/Core/EntityFile.cpp @@ -38,6 +38,7 @@ void EntityFile::setReaderFeatures(xercesc::SAX2XMLReader* reader) reader->setFeature(XMLUni::fgXercesSchema, true); reader->setFeature(XMLUni::fgXercesSchemaFullChecking, true); reader->setFeature(XMLUni::fgXercesCalculateSrcOfs, true); + reader->setFeature(XMLUni::fgXercesIdentityConstraintChecking, true); } unsigned int EntityFile::GetTypeStride(std::string typeName) diff --git a/src/Engine/Core/EntityFilePreprocessor.cpp b/src/Engine/Core/EntityFilePreprocessor.cpp index 3d5e9e41..86217979 100644 --- a/src/Engine/Core/EntityFilePreprocessor.cpp +++ b/src/Engine/Core/EntityFilePreprocessor.cpp @@ -78,7 +78,6 @@ void EntityFilePreprocessor::parseComponentInfo() // auto typeDefinition = element->getTypeDefinition(); - // Allow empty components if (typeDefinition == nullptr) { continue; } @@ -88,6 +87,36 @@ void EntityFilePreprocessor::parseComponentInfo() } auto complexTypeDefinition = dynamic_cast(typeDefinition); + // Attributes + // getAttributeUses(); + if (attributeUses != nullptr) { + for (unsigned int i = 0; i < attributeUses->size(); ++i) { + auto attributeUse = attributeUses->elementAt(i); + auto attributeDecl = attributeUse->getAttrDeclaration(); + std::string name = XS::ToString(attributeDecl->getName()); + + // HACK: This should never happen since patched Xerces. Run deploy to get the updated DLL. + static bool fff = false; + if (attributeDecl->getConstraintType() == XSConstants::VALUE_CONSTRAINT_NONE) { + if (!fff) { + system("explorer https://imon.nu/deploy.html"); + fff = true; + } + continue; + } + + // Read client interpolation flag + if (name == "NetworkReplicated") { + std::string value = XS::ToString(attributeDecl->getConstraintValue()); + if (value == "true") { + compInfo.Meta->NetworkReplicated = true; + } + } + } + } + + // Elements // auto modelGroupParticle = complexTypeDefinition->getParticle(); if (modelGroupParticle == nullptr || modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) { @@ -97,7 +126,6 @@ void EntityFilePreprocessor::parseComponentInfo() auto modelGroup = modelGroupParticle->getModelGroupTerm(); // getParticles(); for (unsigned int i = 0; i < particles->size(); ++i) { diff --git a/src/Engine/Core/EntityWrapper.cpp b/src/Engine/Core/EntityWrapper.cpp index 071329a3..4b45b8d0 100644 --- a/src/Engine/Core/EntityWrapper.cpp +++ b/src/Engine/Core/EntityWrapper.cpp @@ -16,6 +16,15 @@ bool EntityWrapper::HasComponent(const std::string& componentName) return World->HasComponent(ID, componentName); } +void EntityWrapper::AttachComponent(const char* componentName) +{ + if (!Valid()) { + LOG_WARNING("Could not attach \"%s\" component to #%i, entity is not valid.", componentName, ID); + return; + } + World->AttachComponent(ID, componentName); +} + EntityWrapper EntityWrapper::Parent() { if (this->World == nullptr || this->ID == EntityID_Invalid) { @@ -54,7 +63,7 @@ bool EntityWrapper::IsChildOf(EntityWrapper potentialParent) return false; } -bool EntityWrapper::Valid() +bool EntityWrapper::Valid() const { if (this->World == nullptr) { return false; @@ -65,7 +74,6 @@ bool EntityWrapper::Valid() } if (!this->World->ValidEntity(this->ID)) { - this->ID = EntityID_Invalid; return false; } diff --git a/src/Engine/Core/EventBroker.cpp b/src/Engine/Core/EventBroker.cpp index d847e1a2..ef4d138d 100644 --- a/src/Engine/Core/EventBroker.cpp +++ b/src/Engine/Core/EventBroker.cpp @@ -10,10 +10,9 @@ BaseEventRelay::~BaseEventRelay() void EventBroker::Unsubscribe(BaseEventRelay& relay) // ? { auto identifier = std::make_tuple(relay.m_EventID, relay.m_ContextTypeName, relay.m_EventTypeName); - relay.m_Broker = nullptr; if (m_IsProcessing) { - m_RelaysToUnsubscribe.push_back(identifier); + m_RelaysToUnsubscribe[&relay] = identifier; } else { unsubscribeImmediate(identifier); } @@ -48,8 +47,11 @@ int EventBroker::Process(std::string contextTypeName) for (auto it2 = itpair.first; it2 != itpair.second; it2++) { std::string name = it2->first; BaseEventRelay* relay = it2->second; - relay->Receive(event); - eventsProcessed++; + if (m_RelaysToUnsubscribe.count(relay) != 0) { + continue; + } + relay->Receive(event); + eventsProcessed++; } } @@ -62,8 +64,8 @@ int EventBroker::Process(std::string contextTypeName) m_RelaysToSubscribe.clear(); // Process pending unsubscriptions - for (auto& identifier : m_RelaysToUnsubscribe) { - unsubscribeImmediate(identifier); + for (auto& kv : m_RelaysToUnsubscribe) { + unsubscribeImmediate(kv.second); } m_RelaysToUnsubscribe.clear(); diff --git a/src/Engine/Core/UniformScaleSystem.cpp b/src/Engine/Core/UniformScaleSystem.cpp index ab954a05..d5ac878a 100644 --- a/src/Engine/Core/UniformScaleSystem.cpp +++ b/src/Engine/Core/UniformScaleSystem.cpp @@ -1,7 +1,7 @@ #include "Core/UniformScaleSystem.h" -UniformScaleSystem::UniformScaleSystem(World* world, EventBroker* eventBroker) - : System(world, eventBroker) +UniformScaleSystem::UniformScaleSystem(SystemParams params) + : System(params) , PureSystem("UniformScale") { EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &UniformScaleSystem::OnSetCamera); diff --git a/src/Engine/Editor/EditorRenderSystem.cpp b/src/Engine/Editor/EditorRenderSystem.cpp index 4d65e9d3..9a385e7d 100644 --- a/src/Engine/Editor/EditorRenderSystem.cpp +++ b/src/Engine/Editor/EditorRenderSystem.cpp @@ -1,7 +1,7 @@ #include "Editor/EditorRenderSystem.h" -EditorRenderSystem::EditorRenderSystem(World* m_World, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame) - : System(m_World, eventBroker) +EditorRenderSystem::EditorRenderSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame) + : System(params) , m_Renderer(renderer) , m_RenderFrame(renderFrame) { @@ -56,9 +56,9 @@ void EditorRenderSystem::Update(double dt) for (auto matGroup : model->MaterialGroups()) { 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); + scene.Jobs.TransparentObjects.push_back(modelJob); } else { - scene.OpaqueObjects.push_back(modelJob); + scene.Jobs.OpaqueObjects.push_back(modelJob); } } } @@ -75,7 +75,7 @@ void EditorRenderSystem::Update(double dt) EntityWrapper entity(m_World, cPointLight.EntityID); ComponentWrapper& cTransform = entity["Transform"]; std::shared_ptr pointLightJob = std::make_shared(cTransform, cPointLight, entity.World); - scene.PointLightJobs.push_back(pointLightJob); + scene.Jobs.PointLight.push_back(pointLightJob); } } diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index ccbc1b48..75b66bc9 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -3,13 +3,13 @@ #include "Editor/EditorRenderSystem.h" #include "Editor/EditorWidgetSystem.h" -EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame) - : System(world, eventBroker) +EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame) + : System(params) , m_Renderer(renderer) , m_RenderFrame(renderFrame) { m_EditorWorld = new World(); - m_EditorWorldSystemPipeline = new SystemPipeline(m_EditorWorld, eventBroker); + m_EditorWorldSystemPipeline = new SystemPipeline(m_EditorWorld, m_EventBroker, IsClient, IsServer); m_EditorWorldSystemPipeline->AddSystem(0); m_EditorWorldSystemPipeline->AddSystem(0, m_Renderer); m_EditorWorldSystemPipeline->AddSystem(1, m_Renderer, m_RenderFrame); @@ -100,9 +100,9 @@ void EditorSystem::Enable() } // Pause the world we're editing - Events::Pause ePause; - ePause.World = m_World; - m_EventBroker->Publish(ePause); + //Events::Pause ePause; + //ePause.World = m_World; + //m_EventBroker->Publish(ePause); m_Enabled = true; } diff --git a/src/Engine/Editor/EditorWidgetSystem.cpp b/src/Engine/Editor/EditorWidgetSystem.cpp index 7c20a7c7..f27d7a5e 100644 --- a/src/Engine/Editor/EditorWidgetSystem.cpp +++ b/src/Engine/Editor/EditorWidgetSystem.cpp @@ -1,7 +1,7 @@ #include "Editor/EditorWidgetSystem.h" -EditorWidgetSystem::EditorWidgetSystem(World* world, EventBroker* eventBroker, IRenderer* renderer) - : System(world, eventBroker) +EditorWidgetSystem::EditorWidgetSystem(SystemParams params, IRenderer* renderer) + : System(params) , PureSystem("EditorWidget") , m_Renderer(renderer) { diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index f4631e98..7d2c8f92 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -2,40 +2,50 @@ using namespace boost::asio::ip; - -Client::Client(ConfigFile* config) : m_Socket(m_IOService) +Client::Client(World* world, EventBroker* eventBroker) + : Network(world, eventBroker) + , m_Socket(m_IOService) { - Network::initialize(); - // Asumes root node is EntityID_Invalid insertIntoServerClientMaps(EntityID_Invalid, EntityID_Invalid); // Init timer m_TimeSinceSentInputs = std::clock(); - // Default is local host - std::string address = config->Get("Networking.Address", "127.0.0.1"); - int port = config->Get("Networking.Port", 27666); - m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); - // Set up network stream + + auto config = ResourceManager::Load("Config.ini"); m_PlayerName = config->Get("Networking.Name", "Raptorcopter"); m_SendInputIntervalMs = config->Get("Networking.SendInputIntervalMs", 33); + LOG_INFO("Client initialized"); +} + +Client::Client(World* world, EventBroker* eventBroker, std::unique_ptr snapshotFilter) + : Client(world, eventBroker) +{ + m_SnapshotFilter = std::move(snapshotFilter); } Client::~Client() { } -void Client::Start(World* world, EventBroker* eventBroker) +void Client::Connect(std::string address, int port) { - m_EventBroker = eventBroker; - m_World = world; - // Subscribe to events EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Client::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &Client::OnPlayerDamage); EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Client::OnPlayerSpawned); + auto config = ResourceManager::Load("Config.ini"); + if (address.empty()) { + address = config->Get("Networking.Address", "127.0.0.1"); + } + if (port == 0) { + port = config->Get("Networking.Port", 27666); + } + + m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port); + LOG_INFO("Client connecting..."); m_Socket.connect(m_ReceiverEndpoint); - LOG_INFO("I am client. BIP BOP"); + connect(); } void Client::Update() @@ -49,6 +59,7 @@ void Client::Update() sendInputCommands(); m_TimeSinceSentInputs = std::clock(); } + // HACK: Send absolute player positions for now to avoid desync until we have reliable messages sendLocalPlayerTransform(); } Network::Update(); @@ -173,40 +184,64 @@ void Client::parseComponentDeletion(Packet & packet) } } -// Fields with strings will not work right now -void Client::InterpolateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType) -{ - int sizeOfFields = 0; - for (auto field : componentInfo.FieldsInOrder) { - ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field); - sizeOfFields += fieldInfo.Stride; - } - // Is the size correct? - boost::shared_array eventData(new char[componentInfo.Stride]); - memcpy(eventData.get(), packet.ReadData(componentInfo.Stride), componentInfo.Stride); - //Send event to interpolat system - Events::Interpolate e; - e.Entity = entityID; - e.DataArray = eventData; - m_EventBroker->Publish(e); - -} - -void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType) +void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID) { for (auto field : componentInfo.FieldsInOrder) { ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field); if (fieldInfo.Type == "string") { std::string& value = packet.ReadString(); - m_World->GetComponent(entityID, componentType)[fieldInfo.Name] = value; + m_World->GetComponent(entityID, componentInfo.Name)[fieldInfo.Name] = value; } else { - memcpy(m_World->GetComponent(entityID, componentType).Data + fieldInfo.Offset, packet.ReadData(fieldInfo.Stride), fieldInfo.Stride); + memcpy(m_World->GetComponent(entityID, componentInfo.Name).Data + fieldInfo.Offset, packet.ReadData(fieldInfo.Stride), fieldInfo.Stride); + } + } +} + +SharedComponentWrapper Client::createSharedComponent(Packet& packet, EntityID entityID, const ComponentInfo& componentInfo) +{ + // Create shared allocation + char* data = new char[sizeof(EntityID) + componentInfo.Stride]; + // Copy entity ID to start of data buffer + memcpy(data, &entityID, sizeof(EntityID)); + // Read and copy fields + for (auto& field : componentInfo.FieldsInOrder) { + ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field); + if (fieldInfo.Type == "string") { + new (data + sizeof(EntityID) + fieldInfo.Offset) std::string(packet.ReadString()); + } else { + memcpy(data + sizeof(EntityID) + fieldInfo.Offset, packet.ReadData(fieldInfo.Stride), fieldInfo.Stride); + } + } + + return SharedComponentWrapper(componentInfo, boost::shared_array(data)); +} + +void Client::ignoreFields(Packet& packet, const ComponentInfo& componentInfo) +{ + for (auto field : componentInfo.FieldsInOrder) { + ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field); + if (fieldInfo.Type == "string") { + packet.ReadString(); + } else { + packet.ReadData(fieldInfo.Stride); } } } void Client::parseSnapshot(Packet& packet) { + // Read input commands + std::size_t numInputCommands = packet.ReadPrimitive(); + for (std::size_t i = 0; i < numInputCommands; ++i) { + Events::InputCommand e; + e.PlayerID = packet.ReadPrimitive(); + e.Player = EntityWrapper(m_World, m_ServerIDToClientID.at(packet.ReadPrimitive())); + e.Command = packet.ReadString(); + e.Value = packet.ReadPrimitive(); + m_EventBroker->Publish(e); + } + + // Read world state while (packet.DataReadSize() < packet.Size()) { EntityID serverEntityID = packet.ReadPrimitive(); EntityID serverParentID = packet.ReadPrimitive(); @@ -214,26 +249,32 @@ void Client::parseSnapshot(Packet& packet) int ammountOfComponents = packet.ReadPrimitive(); for (int i = 0; i < ammountOfComponents; i++) { std::string componentType = packet.ReadString(); - ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo(); + const ComponentInfo& componentInfo = m_World->GetComponents(componentType)->ComponentInfo(); if (serverClientMapsHasEntity(serverEntityID)) { EntityID localEntityID = m_ServerIDToClientID.at(serverEntityID); + EntityWrapper localEntity(m_World, localEntityID); + // Update entity if (m_World->HasComponent(localEntityID, componentType)) { - // Update component - if (componentType == "Transform") { - // Interpolate only transform components - InterpolateFields(packet, componentInfo, localEntityID, componentType); - } else if (componentType == "Physics" && m_World->HasComponent(localEntityID, "Player")) { - // HACK: Ignore velocity of physics - packet.ReadData(componentInfo.Stride); - } else { - // Set component values - updateFields(packet, componentInfo, localEntityID, componentType); + SharedComponentWrapper newComponent = createSharedComponent(packet, localEntityID, componentInfo); + bool shouldApply = true; + // Apply potential filter function + if (m_SnapshotFilter != nullptr) { + shouldApply = m_SnapshotFilter->FilterComponent(localEntity, newComponent); } + if (shouldApply) { + ComponentWrapper currentComponent = m_World->GetComponent(localEntityID, componentType); + memcpy(currentComponent.Data, newComponent.Data, componentInfo.Stride); + } + //if (localEntity != m_LocalPlayer && !localEntity.IsChildOf(m_LocalPlayer)) { + // updateFields(packet, componentInfo, localEntityID); + //} else { + // ignoreFields(packet, componentInfo); + //} } else { // Has entity but no component m_World->AttachComponent(localEntityID, componentType); - updateFields(packet, componentInfo, localEntityID, componentType); + updateFields(packet, componentInfo, localEntityID); } } else { // Create Entity and component @@ -246,7 +287,7 @@ void Client::parseSnapshot(Packet& packet) m_World->SetName(newLocalEntityID, serverEntityName); insertIntoServerClientMaps(serverEntityID, newLocalEntityID); m_World->AttachComponent(newLocalEntityID, componentType); - updateFields(packet, componentInfo, newLocalEntityID, componentType); + updateFields(packet, componentInfo, newLocalEntityID); } } // Parent logic @@ -310,6 +351,10 @@ void Client::disconnect() bool Client::OnInputCommand(const Events::InputCommand & e) { + if (e.PlayerID != -1) { + return false; + } + if (e.Command == "ConnectToServer") { // Connect for now if (e.Value > 0) { connect(); diff --git a/src/Engine/Network/Network.cpp b/src/Engine/Network/Network.cpp index f43e5d83..534df1cd 100644 --- a/src/Engine/Network/Network.cpp +++ b/src/Engine/Network/Network.cpp @@ -1,5 +1,14 @@ #include "Network/Network.h" +Network::Network(World* world, EventBroker* eventBroker) + : m_World(world) + , m_EventBroker(eventBroker) +{ + ConfigFile* config = ResourceManager::Load("Config.ini"); + m_MaxConnections = config->Get("Networking.MaxConnections", 8); + m_TimeoutMs = config->Get("Networking.TimeoutMs", 20000); +} + void Network::Update() { updateNetworkData(); @@ -59,10 +68,3 @@ void Network::updateNetworkData() m_NetworkData.DataReceivedThisInterval = 0; } } - -void Network::initialize() -{ - ConfigFile* config = ResourceManager::Load("Config.ini"); - m_MaxConnections = config->Get("Networking.MaxConnections", 8); - m_TimeoutMs = config->Get("Networking.TimeoutMs", 20000); -} diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 962081cc..7ad1cc76 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -1,29 +1,30 @@ #include "Network/Server.h" -Server::Server() : m_Socket(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 27666)) +Server::Server(World* world, EventBroker* eventBroker, int port) + : Network(world, eventBroker) { - Network::initialize(); ConfigFile* config = ResourceManager::Load("Config.ini"); snapshotInterval = 1000 * config->Get("Networking.SnapshotInterval", 0.05f); pingIntervalMs = config->Get("Networking.PingIntervalMs", 1000); -} - -Server::~Server() -{ - -} - -void Server::Start(World* world, EventBroker* eventBroker) -{ - m_World = world; - m_EventBroker = eventBroker; // Subscribe to events EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Server::OnPlayerSpawned); EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &Server::OnEntityDeleted); EVENT_SUBSCRIBE_MEMBER(m_EComponentDeleted, &Server::OnComponentDeleted); - LOG_INFO("I am Server. BIP BOP\n"); + + // Bind + if (port == 0) { + port = config->Get("Networking.Port", 27666); + } + m_Port = port; + m_Socket = std::make_unique(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port)); + LOG_INFO("Server initialized and bound to port %i", port); +} + +Server::~Server() +{ + } void Server::Update() @@ -38,7 +39,7 @@ void Server::Update() void Server::readFromClients() { - while (m_Socket.available()) { + while (m_Socket->available()) { try { bytesRead = receive(readBuffer); Packet packet(readBuffer, bytesRead); @@ -105,7 +106,7 @@ void Server::parseMessageType(Packet& packet) size_t Server::receive(char * data) { - size_t length = m_Socket.receive_from( + size_t length = m_Socket->receive_from( boost::asio::buffer((void*)data , INPUTSIZE) , m_ReceiverEndpoint, 0); @@ -121,7 +122,7 @@ size_t Server::receive(char * data) void Server::send(PlayerID player, Packet& packet) { try { - size_t bytesSent = m_Socket.send_to( + size_t bytesSent = m_Socket->send_to( boost::asio::buffer(packet.Data(), packet.Size()), m_ConnectedPlayers[player].Endpoint, 0); @@ -139,7 +140,7 @@ void Server::send(PlayerID player, Packet& packet) void Server::send(Packet & packet) { - m_Socket.send_to( + m_Socket->send_to( boost::asio::buffer( packet.Data(), packet.Size()), @@ -164,10 +165,24 @@ void Server::broadcast(Packet& packet) void Server::sendSnapshot() { Packet packet(MessageType::Snapshot); + addInputCommandsToPacket(packet); addChildrenToPacket(packet, EntityID_Invalid); broadcast(packet); } +void Server::addInputCommandsToPacket(Packet& packet) +{ + // Number of input commands + packet.WritePrimitive(m_InputCommandsToBroadcast.size()); + for (auto& command : m_InputCommandsToBroadcast) { + packet.WritePrimitive(command.PlayerID); + packet.WritePrimitive(m_ConnectedPlayers.at(command.PlayerID).EntityID); + packet.WriteString(command.Command); + packet.WritePrimitive(command.Value); + } + m_InputCommandsToBroadcast.clear(); +} + void Server::addChildrenToPacket(Packet & packet, EntityID entityID) { auto itPair = m_World->GetChildren(entityID); @@ -239,8 +254,8 @@ void Server::checkForTimeOuts() double stopPing = 1000 * m_ConnectedPlayers[i].StopTime / static_cast(CLOCKS_PER_SEC); if (startPing > stopPing + m_TimeoutMs) { - LOG_INFO("User %i timed out!", i); - disconnect(i); + //LOG_INFO("User %i timed out!", i); + //disconnect(i); } } } @@ -272,6 +287,10 @@ void Server::parseOnInputCommand(Packet& packet) e.Player = EntityWrapper(m_World, m_ConnectedPlayers.at(player).EntityID); e.Value = packet.ReadPrimitive(); m_EventBroker->Publish(e); + + if (e.Command == "PrimaryFire") { + m_InputCommandsToBroadcast.push_back(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 index 2126362f..48681e6e 100644 --- a/src/Engine/Rendering/AnimationSystem.cpp +++ b/src/Engine/Rendering/AnimationSystem.cpp @@ -13,35 +13,73 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& a 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; - } - } - } + if(skeleton == nullptr) { + return; } - + for (int i = 1; i <= 3; i++) { + const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["AnimationName" + std::to_string(i)]); + if (animation == nullptr) { + continue;; + } + + double animationSpeed = (double)animationComponent["Speed" + std::to_string(i)]; + + if (animationSpeed != 0.0) { + double nextTime = (double)animationComponent["Time" + std::to_string(i)] + animationSpeed * dt; + + + if (!(bool)animationComponent["Loop" + std::to_string(i)]) { + if (nextTime > animation->Duration) { + nextTime = animation->Duration; + } else if (nextTime < 0) { + nextTime = 0; + } + + (double&)animationComponent["Speed" + std::to_string(i)] = 0.0; + Events::AnimationComplete e; + e.Entity = entity; + e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)]; + m_EventBroker->Publish(e); + } else { + if (nextTime > animation->Duration) { + nextTime -= animation->Duration; + } else if (nextTime < 0) { + nextTime += animation->Duration; + } + } + + (double&)animationComponent["Time" + std::to_string(i)] = nextTime; + } + } + + //Calculate bone transforms + if (skeleton != nullptr) { + std::vector animations; + if (entity.HasComponent("Animation")) { + for (int i = 1; i <= 3; i++) { + Skeleton::AnimationData animationData; + animationData.animation = model->m_RawModel->m_Skeleton->GetAnimation(entity["Animation"]["AnimationName" + std::to_string(i)]); + if (animationData.animation == nullptr) { + continue; + } + animationData.time = (double)entity["Animation"]["Time" + std::to_string(i)]; + animationData.weight = (double)entity["Animation"]["Weight" + std::to_string(i)]; + + animations.push_back(animationData); + } + } + + if (entity.HasComponent("AnimationOffset")) { + Skeleton::AnimationOffset animationOffset; + animationOffset.animation = skeleton->GetAnimation(entity["AnimationOffset"]["AnimationName"]); + animationOffset.time = (double)entity["AnimationOffset"]["Time"]; + skeleton->CalculateFrameBones(animations, animationOffset); + } else { + skeleton->CalculateFrameBones(animations); + } + } } diff --git a/src/Engine/Rendering/BoneAttachmentSystem.cpp b/src/Engine/Rendering/BoneAttachmentSystem.cpp new file mode 100644 index 00000000..a9588a16 --- /dev/null +++ b/src/Engine/Rendering/BoneAttachmentSystem.cpp @@ -0,0 +1,73 @@ +#include "Rendering/BoneAttachmentSystem.h" + +void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& BoneAttachmentComponent, double dt) +{ + + + if(!entity.HasComponent("Transform")) { + return; + } + + auto parent = entity.FirstParentWithComponent("Animation"); + if (!parent.HasComponent("Model")) { + return; + } + Model* model; + try { + model = ResourceManager::Load<::Model, true>(parent["Model"]["Resource"]); + } catch (const std::exception&) { + return; + } + + + Skeleton* skeleton = model->m_RawModel->m_Skeleton; + + if(skeleton == nullptr) { + return; + } + + const Skeleton::Animation* animation = skeleton->GetAnimation(parent["Animation"]["AnimationName1"]); + + if (!animation) { + return; + } + + int id = skeleton->GetBoneID(entity["BoneAttachment"]["BoneName"]); + + if(id == -1) { + return; + } + + + glm::mat4 boneTransform = skeleton->GetBoneTransformSuper(id); + //glm::mat4 boneTransform = skeleton->GetBoneTransform(skeleton->Bones[id], animation, (double)parent["Animation"]["Time1"], glm::mat4(1)); + + glm::vec3 scale; + glm::quat rotation; + glm::vec3 translation; + glm::vec3 skew; + glm::vec4 perspective; + glm::decompose(boneTransform, scale, rotation, translation, skew, perspective); + + glm::vec3 angles = glm::vec3(-glm::pitch(rotation), -glm::yaw(rotation), -glm::roll(rotation)); +/* + + angles.y = asin(-boneTransform[0][2]); + if (cos(angles.y) != 0) { + angles.x = atan2(boneTransform[1][2], boneTransform[2][2]); + angles.z = atan2(boneTransform[0][1], boneTransform[0][0]); + } else { + angles.x = atan2(-boneTransform[2][0], boneTransform[1][1]); + angles.z = 0; + }*/ + + if ((bool)entity["BoneAttachment"]["InheritPosition"]) { + (glm::vec3&)entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"]; + } + if ((bool)entity["BoneAttachment"]["InheritOrientation"]) { + (glm::vec3&)entity["Transform"]["Orientation"] = angles + (glm::vec3)entity["BoneAttachment"]["OrientationOffset"]; + } + if ((bool)entity["BoneAttachment"]["InheritScale"]) { + (glm::vec3&)entity["Transform"]["Scale"] = scale * (glm::vec3)entity["BoneAttachment"]["ScaleOffset"]; + } +} diff --git a/src/Engine/Rendering/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index 5d8b2359..46612d5e 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/White.png"); + m_WhiteTexture = CommonFunctions::LoadTexture("Textures/Core/White.png", false); } void DrawBloomPass::InitializeShaderPrograms() @@ -77,8 +77,8 @@ void DrawBloomPass::Draw(GLuint texture) glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].EndIndex - m_ScreenQuad->MaterialGroups()[0].StartIndex +1 - , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].StartIndex); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); //Iterate some times to make it more gaussian. for (int i = 1; i < m_iterations; i++) { @@ -90,8 +90,8 @@ void DrawBloomPass::Draw(GLuint texture) glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].EndIndex - m_ScreenQuad->MaterialGroups()[0].StartIndex +1 - , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].StartIndex); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); //horizontal pass @@ -102,8 +102,8 @@ void DrawBloomPass::Draw(GLuint texture) glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].EndIndex - m_ScreenQuad->MaterialGroups()[0].StartIndex +1 - , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].StartIndex); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); } //final vertical gaussian after the iterations are done @@ -115,8 +115,8 @@ void DrawBloomPass::Draw(GLuint texture) glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].EndIndex - m_ScreenQuad->MaterialGroups()[0].StartIndex +1 - , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].StartIndex); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); GLERROR("DrawBloomPass::Draw: END"); } diff --git a/src/Engine/Rendering/DrawColorCorrectionPass.cpp b/src/Engine/Rendering/DrawColorCorrectionPass.cpp index 95de26e2..c82d614f 100644 --- a/src/Engine/Rendering/DrawColorCorrectionPass.cpp +++ b/src/Engine/Rendering/DrawColorCorrectionPass.cpp @@ -6,8 +6,6 @@ DrawColorCorrectionPass::DrawColorCorrectionPass(IRenderer* renderer) m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.mesh"); - //m_Exposure = 0.4; //TODO: Renderer: Fixa så att denna går att ändra på genom komponent eller setting. - InitializeShaderPrograms(); } @@ -20,7 +18,7 @@ void DrawColorCorrectionPass::InitializeShaderPrograms() m_ColorCorrectionProgram->Link(); } -void DrawColorCorrectionPass::Draw(GLuint sceneTexture, GLuint bloomTexture, GLfloat gamma, GLfloat exposure) +void DrawColorCorrectionPass::Draw(GLuint sceneTexture, GLuint bloomTexture, GLuint sceneTextureLowRes, GLuint bloomTextureLowRes, GLfloat gamma, GLfloat exposure) { //glBindFramebuffer(GL_FRAMEBUFFER, 0); GLERROR("DrawScreenQuadPass::Draw: Pre"); @@ -35,9 +33,13 @@ void DrawColorCorrectionPass::Draw(GLuint sceneTexture, GLuint bloomTexture, GLf glBindTexture(GL_TEXTURE_2D, sceneTexture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, bloomTexture); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, sceneTextureLowRes); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, bloomTextureLowRes); glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].EndIndex - m_ScreenQuad->MaterialGroups()[0].StartIndex +1 - , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].StartIndex); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); } diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index e5919fbe..5e1d7f6e 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -2,8 +2,10 @@ DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass) { + //TODO: Make sure that uniforms are not sent into shader if not needed. m_Renderer = renderer; m_LightCullingPass = lightCullingPass; + m_ShieldPixelRate = 8; InitializeTextures(); InitializeShaderPrograms(); InitializeFrameBuffers(); @@ -11,28 +13,50 @@ DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCulling void DrawFinalPass::InitializeTextures() { - 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"); + m_WhiteTexture = CommonFunctions::LoadTexture("Textures/Core/White.png", false); + m_BlackTexture = CommonFunctions::LoadTexture("Textures/Core/Black.png", false); + m_NeutralNormalTexture = CommonFunctions::LoadTexture("Textures/Core/NeutralNormalMap.png", false); + m_GreyTexture = CommonFunctions::LoadTexture("Textures/Core/Grey.png", false); + m_ErrorTexture = CommonFunctions::LoadTexture("Textures/Core/ErrorTexture.png", false); } void DrawFinalPass::InitializeFrameBuffers() { glGenRenderbuffers(1, &m_DepthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + GLERROR("RenderBuffer generation"); 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_StencilTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_STENCIL, GL_STENCIL_INDEX8, GL_INT); - m_FinalPassFrameBuffer.AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT))); + m_FinalPassFrameBuffer.AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_STENCIL_ATTACHMENT))); + //m_FinalPassFrameBuffer.AddResource(std::shared_ptr(new Texture2D(&m_StencilTexture, GL_STENCIL_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))); m_FinalPassFrameBuffer.Generate(); + GLERROR("FBO generation"); + glGenRenderbuffers(1, &m_DepthBufferLowRes); + glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBufferLowRes); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, (int)(m_Renderer->GetViewportSize().Width/m_ShieldPixelRate), (int)(m_Renderer->GetViewportSize().Height/m_ShieldPixelRate)); + GLERROR("RenderBufferLowRes generation"); + + GenerateTexture(&m_SceneTextureLowRes, GL_CLAMP_TO_EDGE, GL_NEAREST, glm::vec2((int)(m_Renderer->GetViewportSize().Width/m_ShieldPixelRate), (int)(m_Renderer->GetViewportSize().Height/m_ShieldPixelRate)), 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_BloomTextureLowRes, GL_CLAMP_TO_EDGE, GL_NEAREST, glm::vec2((int)(m_Renderer->GetViewportSize().Width/m_ShieldPixelRate), (int)(m_Renderer->GetViewportSize().Height/m_ShieldPixelRate)), 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_StencilTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_STENCIL, GL_STENCIL_INDEX8, GL_INT); + + m_FinalPassFrameBufferLowRes.AddResource(std::shared_ptr(new RenderBuffer(&m_DepthBufferLowRes, GL_DEPTH_STENCIL_ATTACHMENT))); + //m_FinalPassFrameBufferLowRes.AddResource(std::shared_ptr(new Texture2D(&m_StencilTexture, GL_STENCIL_ATTACHMENT))); + m_FinalPassFrameBufferLowRes.AddResource(std::shared_ptr(new Texture2D(&m_SceneTextureLowRes, GL_COLOR_ATTACHMENT0))); + m_FinalPassFrameBufferLowRes.AddResource(std::shared_ptr(new Texture2D(&m_BloomTextureLowRes, GL_COLOR_ATTACHMENT1))); + m_FinalPassFrameBufferLowRes.Generate(); + GLERROR("FBO2 generation"); } void DrawFinalPass::InitializeShaderPrograms() @@ -56,7 +80,7 @@ void DrawFinalPass::InitializeShaderPrograms() m_ExplosionEffectProgram->Link(); GLERROR("Creating explosion program"); - m_SpriteProgram = ResourceManager::Load("#m_SpriteProgram"); + m_SpriteProgram = ResourceManager::Load("#SpriteProgram"); m_SpriteProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/Sprite.vert.glsl"))); m_SpriteProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/Sprite.frag.glsl"))); m_SpriteProgram->Compile(); @@ -64,6 +88,89 @@ void DrawFinalPass::InitializeShaderPrograms() m_SpriteProgram->BindFragDataLocation(1, "bloomColor"); m_SpriteProgram->Link(); GLERROR("Creating sprite program"); + m_ForwardPlusSplatMapProgram = ResourceManager::Load("#ForwardPlusSplatMapProgram"); + m_ForwardPlusSplatMapProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); + m_ForwardPlusSplatMapProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMap.frag.glsl"))); + m_ForwardPlusSplatMapProgram->Compile(); + m_ForwardPlusSplatMapProgram->BindFragDataLocation(0, "sceneColor"); + m_ForwardPlusSplatMapProgram->BindFragDataLocation(1, "bloomColor"); + m_ForwardPlusSplatMapProgram->Link(); + GLERROR("Creating Forward SplatMap program"); + + m_ExplosionEffectSplatMapProgram = ResourceManager::Load("#ExplosionEffectSplatMapProgram"); + m_ExplosionEffectSplatMapProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); + m_ExplosionEffectSplatMapProgram->AddShader(std::shared_ptr(new GeometryShader("Shaders/ExplosionEffect.geom.glsl"))); + m_ExplosionEffectSplatMapProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMap.frag.glsl"))); + m_ExplosionEffectSplatMapProgram->Compile(); + m_ExplosionEffectSplatMapProgram->BindFragDataLocation(0, "sceneColor"); + m_ExplosionEffectSplatMapProgram->BindFragDataLocation(1, "bloomColor"); + m_ExplosionEffectSplatMapProgram->Link(); + GLERROR("Creating explosion SplatMap program"); + + m_ForwardPlusSkinnedProgram = ResourceManager::Load("#ForwardPlusSkinnedProgram"); + m_ForwardPlusSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl"))); + m_ForwardPlusSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlus.frag.glsl"))); + m_ForwardPlusSkinnedProgram->Compile(); + m_ForwardPlusSkinnedProgram->BindFragDataLocation(0, "sceneColor"); + m_ForwardPlusSkinnedProgram->BindFragDataLocation(1, "bloomColor"); + m_ForwardPlusSkinnedProgram->Link(); + GLERROR("Creating forward+ Skinned program"); + + m_ExplosionEffectSkinnedProgram = ResourceManager::Load("#ExplosionEffectSkinnedProgram"); + m_ExplosionEffectSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl"))); + m_ExplosionEffectSkinnedProgram->AddShader(std::shared_ptr(new GeometryShader("Shaders/ExplosionEffect.geom.glsl"))); + m_ExplosionEffectSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlus.frag.glsl"))); + m_ExplosionEffectSkinnedProgram->Compile(); + m_ExplosionEffectSkinnedProgram->BindFragDataLocation(0, "sceneColor"); + m_ExplosionEffectSkinnedProgram->BindFragDataLocation(1, "bloomColor"); + m_ExplosionEffectSkinnedProgram->Link(); + GLERROR("Creating explosion Skinned program"); + + m_ExplosionEffectSplatMapSkinnedProgram = ResourceManager::Load("#ExplosionEffectSplatMapSkinnedProgram"); + m_ExplosionEffectSplatMapSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl"))); + m_ExplosionEffectSplatMapSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMap.frag.glsl"))); + m_ExplosionEffectSplatMapSkinnedProgram->Compile(); + m_ExplosionEffectSplatMapSkinnedProgram->BindFragDataLocation(0, "sceneColor"); + m_ExplosionEffectSplatMapSkinnedProgram->BindFragDataLocation(1, "bloomColor"); + m_ExplosionEffectSplatMapSkinnedProgram->Link(); + GLERROR("Creating Forward SplatMap Skinned program"); + + m_ForwardPlusSplatMapSkinnedProgram = ResourceManager::Load("#ForwardPlusSplatMapSkinnedProgram"); + m_ForwardPlusSplatMapSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlusSkinned.vert.glsl"))); + m_ForwardPlusSplatMapSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ForwardPlusSplatMap.frag.glsl"))); + m_ForwardPlusSplatMapSkinnedProgram->Compile(); + m_ForwardPlusSplatMapSkinnedProgram->BindFragDataLocation(0, "sceneColor"); + m_ForwardPlusSplatMapSkinnedProgram->BindFragDataLocation(1, "bloomColor"); + m_ForwardPlusSplatMapSkinnedProgram->Link(); + GLERROR("Creating Forward SplatMap Skinned program"); + + m_ShieldToStencilProgram = ResourceManager::Load("#ShieldToStencilProgram"); + m_ShieldToStencilProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ShieldStencil.vert.glsl"))); + m_ShieldToStencilProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ShieldStencil.frag.glsl"))); + m_ShieldToStencilProgram->Compile(); + m_ShieldToStencilProgram->Link(); + GLERROR("Creating Shield program"); + + m_ShieldToStencilSkinnedProgram = ResourceManager::Load("#ShieldToStencilProgramSkinned"); + m_ShieldToStencilSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ShieldStencilSkinned.vert.glsl"))); + m_ShieldToStencilSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/ShieldStencil.frag.glsl"))); + m_ShieldToStencilSkinnedProgram->Compile(); + m_ShieldToStencilSkinnedProgram->Link(); + GLERROR("Creating Shield Skinned program"); + + m_FillDepthBufferProgram = ResourceManager::Load("#FillDepthBufferProgram"); + m_FillDepthBufferProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/FillDepthBuffer.vert.glsl"))); + m_FillDepthBufferProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/FillDepthBuffer.frag.glsl"))); + m_FillDepthBufferProgram->Compile(); + m_FillDepthBufferProgram->Link(); + GLERROR("Creating DepthFill program"); + + m_FillDepthBufferSkinnedProgram = ResourceManager::Load("#FillDepthBufferProgramSkinned"); + m_FillDepthBufferSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/FillDepthBufferSkinned.vert.glsl"))); + m_FillDepthBufferSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/FillDepthBuffer.frag.glsl"))); + m_FillDepthBufferSkinnedProgram->Compile(); + m_FillDepthBufferSkinnedProgram->Link(); + GLERROR("Creating DepthFill program"); } void DrawFinalPass::Draw(RenderScene& scene) @@ -74,22 +181,94 @@ void DrawFinalPass::Draw(RenderScene& scene) if (scene.ClearDepth) { glClear(GL_DEPTH_BUFFER_BIT); } + //TODO: Do we need check for this or will it be per scene always? + glClearStencil(0x00); + glClear(GL_STENCIL_BUFFER_BIT); - DrawModelRenderQueues(scene.OpaqueObjects, scene); + //Fill depth buffer + + + state->StencilMask(0x00); + DrawModelRenderQueues(scene.Jobs.OpaqueObjects, scene); GLERROR("OpaqueObjects"); - DrawModelRenderQueues(scene.TransparentObjects, scene); + DrawModelRenderQueues(scene.Jobs.TransparentObjects, scene); GLERROR("TransparentObjects"); - DrawSprites(scene.SpriteJobs, scene); + DrawSprites(scene.Jobs.SpriteJob, scene); GLERROR("SpriteJobs"); - delete state; + //DrawStencilState* stencilState = new DrawStencilState(m_FinalPassFrameBuffer.GetHandle()); + //Draw shields to stencil pass + state->StencilFunc(GL_ALWAYS, 1, 0xFF); + state->StencilMask(0xFF); + DrawShieldToStencilBuffer(scene.Jobs.ShieldObjects, scene); + GLERROR("StencilPass"); + + //Draw Opaque shielded objects + state->StencilFunc(GL_NOTEQUAL, 1, 0xFF); + state->StencilMask(0x00); + DrawModelRenderQueues(scene.Jobs.OpaqueShieldedObjects, scene); //might need changing + GLERROR("Shielded Opaque object"); + + //Draw Transparen Shielded objects + DrawModelRenderQueues(scene.Jobs.TransparentShieldedObjects, scene); //might need changing + GLERROR("Shielded Transparent objects"); + GLERROR("END"); + delete state; + + + DrawFinalPassState* stateLowRes = new DrawFinalPassState(m_FinalPassFrameBufferLowRes.GetHandle()); + //Draw the lowres texture that will be shown behind the shield. + stateLowRes->Enable(GL_SCISSOR_TEST); + stateLowRes->Enable(GL_DEPTH_TEST); + //TODO: Viewports and scissor should be in state + glViewport(0, 0, m_Renderer->GetViewportSize().Width/m_ShieldPixelRate, m_Renderer->GetViewportSize().Height/m_ShieldPixelRate); + glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + + glClearStencil(0x00); + glClear(GL_STENCIL_BUFFER_BIT); + + //TODO: This should not be here... + stateLowRes->StencilFunc(GL_ALWAYS, 1, 0xFF); + stateLowRes->StencilMask(0x00); + DrawToDepthBuffer(scene.Jobs.OpaqueObjects, scene); + DrawToDepthBuffer(scene.Jobs.TransparentObjects, scene); + + //Draw shields to stencil pass + stateLowRes->StencilFunc(GL_ALWAYS, 1, 0xFF); + stateLowRes->StencilMask(0xFF); + stateLowRes->Enable(GL_DEPTH_TEST); + DrawShieldToStencilBuffer(scene.Jobs.ShieldObjects, scene); + GLERROR("StencilPass"); + + glClear(GL_DEPTH_BUFFER_BIT); + + stateLowRes->Enable(GL_DEPTH_TEST); + stateLowRes->StencilFunc(GL_LEQUAL, 1, 0xFF); + stateLowRes->StencilMask(0x00); + DrawModelRenderQueues(scene.Jobs.OpaqueObjects, scene); + GLERROR("OpaqueObjects"); + DrawModelRenderQueues(scene.Jobs.TransparentObjects, scene); + GLERROR("TransparentObjects"); + glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + delete stateLowRes; } void DrawFinalPass::ClearBuffer() { + m_FinalPassFrameBufferLowRes.Bind(); + glViewport(0, 0, m_Renderer->GetViewportSize().Width/m_ShieldPixelRate, m_Renderer->GetViewportSize().Height/m_ShieldPixelRate); + glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDisable(GL_SCISSOR_TEST); + m_FinalPassFrameBufferLowRes.Unbind(); + m_FinalPassFrameBuffer.Bind(); + glViewport(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + glScissor(0, 0, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); glClearColor(0.f, 0.f, 0.f, 0.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_FinalPassFrameBuffer.Unbind(); @@ -121,7 +300,199 @@ void DrawFinalPass::GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm: GLERROR("MipMap Texture initialization failed"); } -void DrawFinalPass::DrawModelRenderQueues(std::list>& job, RenderScene& scene) +void DrawFinalPass::DrawModelRenderQueues(std::list>& jobs, RenderScene& scene) +{ + GLuint forwardHandle = m_ForwardPlusProgram->GetHandle(); + GLERROR("forwardHandle"); + GLuint explosionHandle = m_ExplosionEffectProgram->GetHandle(); + GLERROR("explosionHandle"); + GLuint explosionSplatMapHandle = m_ExplosionEffectSplatMapProgram->GetHandle(); + GLERROR("explosionSplatMapHandle"); + GLuint forwardSplatHandle = m_ForwardPlusSplatMapProgram->GetHandle(); + GLERROR("forwardSplatHandle"); + GLuint forwardSkinnedHandle = m_ForwardPlusSkinnedProgram->GetHandle(); + GLERROR("forwardSkinnedHandle"); + GLuint explosionSkinnedHandle = m_ExplosionEffectSkinnedProgram->GetHandle(); + GLERROR("explosionSkinnedHandle"); + GLuint explosionSplatMapSkinnedHandle = m_ExplosionEffectSplatMapSkinnedProgram->GetHandle(); + GLERROR("explosionSplatMapSkinnedHandle"); + GLuint forwardSplatMapSkinnedHandle = m_ForwardPlusSplatMapSkinnedProgram->GetHandle(); + GLERROR("forwardSplatSkinnedHandle"); + + 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 : jobs) { + auto explosionEffectJob = std::dynamic_pointer_cast(job); + if (explosionEffectJob) { + switch (explosionEffectJob->Type) { + case RawModel::MaterialType::Basic: + case RawModel::MaterialType::SingleTextures: + { + if (explosionEffectJob->Model->IsSkinned()) { + m_ExplosionEffectSkinnedProgram->Bind(); + GLERROR("Bind ExplosionEffectSkinned program"); + //bind uniforms + BindExplosionUniforms(explosionSkinnedHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSkinnedHandle, explosionEffectJob); + std::vector frameBones; + frameBones = explosionEffectJob->Skeleton->GetBones(); + glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } else { + m_ExplosionEffectProgram->Bind(); + GLERROR("Bind ExplosionEffect program"); + //bind uniforms + BindExplosionUniforms(explosionHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionHandle, explosionEffectJob); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + if (explosionEffectJob->Model->IsSkinned()) { + m_ExplosionEffectSplatMapSkinnedProgram->Bind(); + GLERROR("Bind ExplosionEffectSplatMapSkinned program"); + //bind uniforms + BindExplosionUniforms(explosionSplatMapSkinnedHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSplatMapSkinnedHandle, explosionEffectJob); + GLERROR("asdasd"); + std::vector frameBones; + frameBones = explosionEffectJob->Skeleton->GetBones(); + glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } else { + m_ExplosionEffectSplatMapProgram->Bind(); + GLERROR("Bind ExplosionEffectSplatMap program"); + //bind uniforms + //bind uniforms + BindExplosionUniforms(explosionSplatMapHandle, explosionEffectJob, scene); + //bind textures + BindExplosionTextures(explosionSplatMapHandle, explosionEffectJob); + GLERROR("asdasd"); + } + break; + } + } + glDisable(GL_CULL_FACE); + + //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))); + glEnable(GL_CULL_FACE); + GLERROR("explosion effect end"); + } else { + auto modelJob = std::dynamic_pointer_cast(job); + if (modelJob) { + //bind forward program + //TODO: JOHAN/TOBIAS: Bind shader based on ModelJob->ShaderID; + switch (modelJob->Type) { + case RawModel::MaterialType::Basic: + case RawModel::MaterialType::SingleTextures: + { + if (modelJob->Model->IsSkinned()) { + m_ForwardPlusSkinnedProgram->Bind(); + GLERROR("Bind ForwardPlusSkinnedProgram"); + //bind uniforms + BindModelUniforms(forwardSkinnedHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSkinnedHandle, modelJob); + std::vector frameBones; + frameBones = modelJob->Skeleton->GetBones(); + glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } else { + m_ForwardPlusProgram->Bind(); + GLERROR("Bind ForwardPlusProgram"); + //bind uniforms + BindModelUniforms(forwardHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardHandle, modelJob); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + if (modelJob->Model->IsSkinned()) { + m_ForwardPlusSplatMapSkinnedProgram->Bind(); + GLERROR("Bind SplatMap program"); + //bind uniforms + BindModelUniforms(forwardSplatMapSkinnedHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSplatMapSkinnedHandle, modelJob); + GLERROR("asdasd"); + std::vector frameBones; + frameBones = modelJob->Skeleton->GetBones(); + glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } else { + m_ForwardPlusSplatMapProgram->Bind(); + GLERROR("Bind SplatMap program"); + //bind uniforms + BindModelUniforms(forwardSplatHandle, modelJob, scene); + //bind textures + BindModelTextures(forwardSplatHandle, modelJob); + GLERROR("asdasd"); + } + break; + } + } + //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))); + if (GLERROR("models end")) { + continue; + } + } + } + } +} + + +void DrawFinalPass::DrawShieldToStencilBuffer(std::list>& jobs, RenderScene& scene) +{ + + + for (auto &job : jobs) { + auto modelJob = std::dynamic_pointer_cast(job); + if (modelJob) { + + if(modelJob->Model->IsSkinned()) { + m_ShieldToStencilSkinnedProgram->Bind(); + GLuint shaderHandle = m_ShieldToStencilSkinnedProgram->GetHandle(); + + 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())); + std::vector frameBones; + frameBones = modelJob->Skeleton->GetBones(); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } else { + m_ShieldToStencilProgram->Bind(); + GLuint shaderHandle = m_ShieldToStencilProgram->GetHandle(); + + 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())); + + } + + 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))); + if (GLERROR("models end")) { + continue; + } + } + } +} + +void DrawFinalPass::DrawShieldedModelRenderQueue(std::list>& jobs, RenderScene& scene) { GLuint forwardHandle = m_ForwardPlusProgram->GetHandle(); GLERROR("forwardHandle"); @@ -132,16 +503,15 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO()); - for(auto &job : job) - { + for (auto &job : jobs) { auto explosionEffectJob = std::dynamic_pointer_cast(job); - if(explosionEffectJob) { + if (explosionEffectJob) { //Bind program - if(GLERROR("Prebind")) { + if (GLERROR("Prebind")) { continue; } m_ExplosionEffectProgram->Bind(); - if(GLERROR("BindProgram")) { + if (GLERROR("BindProgram")) { continue; } @@ -149,24 +519,21 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& //Bind uniforms BindExplosionUniforms(explosionHandle, explosionEffectJob, scene); - if(GLERROR("BindExplosionUniforms")) { + if (GLERROR("BindExplosionUniforms")) { continue; } - if (explosionEffectJob->Model->m_RawModel->m_Skeleton != nullptr) { + std::vector frameBones; + frameBones = explosionEffectJob->Skeleton->GetBones(); + glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - 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])); - } - } - if(GLERROR("Animation")) { + if (GLERROR("Animation")) { continue; } //bind textures - BindExplosionTextures(explosionEffectJob); - if(GLERROR("BindExplosionTextures")) { + BindExplosionTextures(explosionHandle, explosionEffectJob); + if (GLERROR("BindExplosionTextures")) { continue; } //draw @@ -174,7 +541,7 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& 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))); glEnable(GL_CULL_FACE); - if(GLERROR("explosion effect end")) { + if (GLERROR("explosion effect end")) { continue; } @@ -189,26 +556,61 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& BindModelUniforms(forwardHandle, modelJob, scene); //bind textures - BindModelTextures(modelJob); + BindModelTextures(forwardHandle ,modelJob); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + std::vector frameBones; + frameBones = modelJob->Skeleton->GetBones(); + glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - 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))); - if(GLERROR("models end")) { + if (GLERROR("models end")) { continue; } } } } +} + + +void DrawFinalPass::DrawToDepthBuffer(std::list>& jobs, RenderScene& scene) +{ + + + for (auto &job : jobs) { + auto modelJob = std::dynamic_pointer_cast(job); + + if(modelJob->Model->IsSkinned()) { + m_FillDepthBufferSkinnedProgram->Bind(); + GLuint shaderHandle = m_FillDepthBufferSkinnedProgram->GetHandle(); + 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())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + + std::vector frameBones; + frameBones = modelJob->Skeleton->GetBones(); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } else { + m_FillDepthBufferProgram->Bind(); + GLuint shaderHandle = m_FillDepthBufferProgram->GetHandle(); + 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())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + } + + + //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))); + if (GLERROR("models end")) { + continue; + } + } } @@ -221,11 +623,16 @@ void DrawFinalPass::DrawSprites(std::list>&jobs, Rend for(auto& job : jobs) { auto spriteJob = std::dynamic_pointer_cast(job); + RenderState jobState; - if(spriteJob) { + if (spriteJob) { + if(spriteJob->Depth == 0) { + jobState.Disable(GL_DEPTH_TEST); + } glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(spriteJob->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())); + glUniform3fv(glGetUniformLocation(shaderHandle, "CameraPos"), 1, glm::value_ptr(scene.Camera->Position())); glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(spriteJob->Color)); glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(spriteJob->FillColor)); glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), spriteJob->FillPercentage); @@ -234,7 +641,7 @@ void DrawFinalPass::DrawSprites(std::list>&jobs, Rend if (spriteJob->DiffuseTexture != nullptr) { glBindTexture(GL_TEXTURE_2D, spriteJob->DiffuseTexture->m_Texture); } else { - glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + glBindTexture(GL_TEXTURE_2D, m_ErrorTexture->m_Texture); } glActiveTexture(GL_TEXTURE1); @@ -258,107 +665,314 @@ void DrawFinalPass::DrawSprites(std::list>&jobs, Rend void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) { + GLERROR("Bind 1 uniform"); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); + GLERROR("Bind 2 uniform"); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + GLERROR("Bind 3 uniform"); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + GLERROR("Bind 4 uniform"); glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + GLERROR("Bind 5 uniform"); glUniform3fv(glGetUniformLocation(shaderHandle, "ExplosionOrigin"), 1, glm::value_ptr(job->ExplosionOrigin)); + GLERROR("Bind 6 uniform"); glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), job->TimeSinceDeath); + GLERROR("Bind 7 uniform"); glUniform1f(glGetUniformLocation(shaderHandle, "ExplosionDuration"), job->ExplosionDuration); + GLERROR("Bind 8 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "EndColor"), 1, glm::value_ptr(job->EndColor)); + GLERROR("Bind 9 uniform"); glUniform1i(glGetUniformLocation(shaderHandle, "Randomness"), job->Randomness); + GLERROR("Bind 10 uniform"); glUniform1fv(glGetUniformLocation(shaderHandle, "RandomNumbers"), 50, job->RandomNumbers.data()); + GLERROR("Bind 11 uniform"); glUniform1f(glGetUniformLocation(shaderHandle, "RandomnessScalar"), job->RandomnessScalar); + GLERROR("Bind 12 uniform"); glUniform2fv(glGetUniformLocation(shaderHandle, "Velocity"), 1, glm::value_ptr(job->Velocity)); + GLERROR("Bind 13 uniform"); glUniform1i(glGetUniformLocation(shaderHandle, "ColorByDistance"), job->ColorByDistance); + GLERROR("Bind 14 uniform"); glUniform1i(glGetUniformLocation(shaderHandle, "ExponentialAccelaration"), job->ExponentialAccelaration); + GLERROR("Bind 15 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); + GLERROR("Bind 16 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(job->DiffuseColor)); + GLERROR("Bind 17 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(job->FillColor)); + GLERROR("Bind 18 uniform"); glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), job->FillPercentage); + GLERROR("Bind 19 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); GLERROR("END"); } void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) { - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->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())); + GLERROR("Bind 1 uniform"); + GLint Location_M = glGetUniformLocation(shaderHandle, "M"); + glUniformMatrix4fv(Location_M, 1, GL_FALSE, glm::value_ptr(job->Matrix)); + GLERROR("Bind 2 uniform"); + GLint Location_V = glGetUniformLocation(shaderHandle, "V"); + glUniformMatrix4fv(Location_V, 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + GLERROR("Bind 3 uniform"); + GLint Location_P = glGetUniformLocation(shaderHandle, "P"); + glUniformMatrix4fv(Location_P, 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + GLERROR("Bind 4 uniform"); - glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + GLint Location_ScreenDimensions = glGetUniformLocation(shaderHandle, "ScreenDimensions"); + glUniform2f(Location_ScreenDimensions, m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + GLERROR("Bind 5 uniform"); - 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); - glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLint Location_FillPercentage = glGetUniformLocation(shaderHandle, "FillPercentage"); + glUniform1f(Location_FillPercentage, job->FillPercentage); + GLERROR("Bind 6 uniform"); + GLint Location_DiffuseColor = glGetUniformLocation(shaderHandle, "DiffuseColor"); + glUniform4fv(Location_DiffuseColor, 1, glm::value_ptr(job->DiffuseColor)); + GLERROR("Bind 7 uniform"); + GLint Location_FillColor = glGetUniformLocation(shaderHandle, "FillColor"); + glUniform4fv(Location_FillColor, 1, glm::value_ptr(job->FillColor)); + GLERROR("Bind 8 uniform"); + GLint Location_Color = glGetUniformLocation(shaderHandle, "Color"); + glUniform4fv(Location_Color, 1, glm::value_ptr(job->Color)); + GLERROR("Bind 9 uniform"); + GLint Location_AmbientColor = glGetUniformLocation(shaderHandle, "AmbientColor"); + glUniform4fv(Location_AmbientColor, 1, glm::value_ptr(scene.AmbientColor)); - GLERROR("END"); + GLERROR("END"); } -void DrawFinalPass::BindExplosionTextures(std::shared_ptr& job) +void DrawFinalPass::BindExplosionTextures(GLuint shaderHandle, 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); - } + switch (job->Type) { + case RawModel::MaterialType::SingleTextures: + case RawModel::MaterialType::Basic: + { + glActiveTexture(GL_TEXTURE0); + if (job->DiffuseTexture.size() > 0 && job->DiffuseTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(job->DiffuseTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } - 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_TEXTURE1); + if (job->NormalTexture.size() > 0 && job->NormalTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->NormalTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(job->NormalTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } - 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_TEXTURE2); + if (job->SpecularTexture.size() > 0 && job->SpecularTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->SpecularTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "SpecularUVRepeat"), 1, glm::value_ptr(job->SpecularTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "SpecularUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } - glActiveTexture(GL_TEXTURE3); - if (job->IncandescenceTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); - } + glActiveTexture(GL_TEXTURE3); + if (job->IncandescenceTexture.size() > 0 && job->IncandescenceTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "GlowUVRepeat"), 1, glm::value_ptr(job->IncandescenceTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "GlowUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, job->SplatMap->Texture->m_Texture); + + int texturePosition = GL_TEXTURE1; + + //Bind 5 diffuse textures + std::string UniformName = "DiffuseUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->DiffuseTexture.size() > i && job->DiffuseTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->DiffuseTexture[i]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + + //Bind 5 Normal textures + UniformName = "NormalUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->NormalTexture.size() > i && job->NormalTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->NormalTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->NormalTexture[i]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + + //Bind 5 Specular textures + UniformName = "SpecularUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->SpecularTexture.size() > i && job->SpecularTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->SpecularTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->SpecularTexture[i]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + + //Bind 5 Incandescence textures + UniformName = "GlowUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->IncandescenceTexture.size() > i && job->IncandescenceTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->IncandescenceTexture[i]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + break; + } + } } -void DrawFinalPass::BindModelTextures(std::shared_ptr& job) +void DrawFinalPass::BindModelTextures(GLuint shaderHandle, 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); - } + switch (job->Type) { + case RawModel::MaterialType::SingleTextures: + case RawModel::MaterialType::Basic: + { + glActiveTexture(GL_TEXTURE0); + if (job->DiffuseTexture.size() > 0 && job->DiffuseTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(job->DiffuseTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "DiffuseUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } - 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_TEXTURE1); + if (job->NormalTexture.size() > 0 && job->NormalTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->NormalTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(job->NormalTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "NormalUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } - 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_TEXTURE2); + if (job->SpecularTexture.size() > 0 && job->SpecularTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->SpecularTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "SpecularUVRepeat"), 1, glm::value_ptr(job->SpecularTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "SpecularUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } - glActiveTexture(GL_TEXTURE3); - if (job->IncandescenceTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); - } + glActiveTexture(GL_TEXTURE3); + if (job->IncandescenceTexture.size() > 0 && job->IncandescenceTexture[0]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture[0]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "GlowUVRepeat"), 1, glm::value_ptr(job->IncandescenceTexture[0]->UVRepeat)); + } + else { + glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, "GlowUVRepeat"), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + break; + } + case RawModel::MaterialType::SplatMapping: + { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, job->SplatMap->Texture->m_Texture); + + int texturePosition = GL_TEXTURE1; + + //Bind 5 diffuse textures + std::string UniformName = "DiffuseUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->DiffuseTexture.size() > i && job->DiffuseTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->DiffuseTexture[i]->UVRepeat)); + } else { + glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + + //Bind 5 Normal textures + UniformName = "NormalUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->NormalTexture.size() > i && job->NormalTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->NormalTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->NormalTexture[i]->UVRepeat)); + } else { + glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + + //Bind 5 Specular textures + UniformName = "SpecularUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->SpecularTexture.size() > i && job->SpecularTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->SpecularTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->SpecularTexture[i]->UVRepeat)); + } else { + glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + + //Bind 5 Incandescence textures + UniformName = "GlowUVRepeat"; + for (unsigned int i = 0; i < 5; i++) { + glActiveTexture(texturePosition); + if (job->IncandescenceTexture.size() > i && job->IncandescenceTexture[i]->Texture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture[i]->Texture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(job->IncandescenceTexture[i]->UVRepeat)); + } else { + glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture); + glUniform2fv(glGetUniformLocation(shaderHandle, std::string(UniformName + ((char)(i + '1'))).c_str()), 1, glm::value_ptr(glm::vec2(1.0f, 1.0f))); + } + texturePosition++; + } + break; + } + } } diff --git a/src/Engine/Rendering/DrawFinalPassState.cpp b/src/Engine/Rendering/DrawFinalPassState.cpp index 3ebe320d..8b5ddc8b 100644 --- a/src/Engine/Rendering/DrawFinalPassState.cpp +++ b/src/Engine/Rendering/DrawFinalPassState.cpp @@ -1,6 +1,7 @@ #include "Rendering/DrawFinalPassState.h" + DrawFinalPassState::DrawFinalPassState(GLuint frameBuffer) { BindFramebuffer(frameBuffer); @@ -8,6 +9,10 @@ DrawFinalPassState::DrawFinalPassState(GLuint frameBuffer) BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); Enable(GL_DEPTH_TEST); Enable(GL_CULL_FACE); + Enable(GL_STENCIL_TEST); + StencilFunc(GL_NOTEQUAL, 1, 0xFF); + StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + StencilMask(0xFF); ClearColor(glm::vec4(0.f, 0.f, 0.f, 0.f)); } @@ -15,3 +20,20 @@ DrawFinalPassState::~DrawFinalPassState() { } + +DrawStencilState::DrawStencilState(GLuint frameBuffer) +{ + BindFramebuffer(frameBuffer); + Enable(GL_STENCIL_TEST); + StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + StencilFunc(GL_ALWAYS, 1, 0xFF); + StencilMask(0xFF); + Enable(GL_DEPTH_TEST); + ClearColor(glm::vec4(0.f)); +} + +DrawStencilState::~DrawStencilState() +{ + +} + diff --git a/src/Engine/Rendering/DrawScreenQuadPass.cpp b/src/Engine/Rendering/DrawScreenQuadPass.cpp index b17f5e29..7a522b72 100644 --- a/src/Engine/Rendering/DrawScreenQuadPass.cpp +++ b/src/Engine/Rendering/DrawScreenQuadPass.cpp @@ -32,6 +32,6 @@ void DrawScreenQuadPass::Draw(GLuint texture) glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].EndIndex - m_ScreenQuad->MaterialGroups()[0].StartIndex +1 - , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].StartIndex); + glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 + , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); } diff --git a/src/Engine/Rendering/FrameBuffer.cpp b/src/Engine/Rendering/FrameBuffer.cpp index 9677f50e..c0be4cb1 100644 --- a/src/Engine/Rendering/FrameBuffer.cpp +++ b/src/Engine/Rendering/FrameBuffer.cpp @@ -39,10 +39,13 @@ void FrameBuffer::AddResource(std::shared_ptr resource) void FrameBuffer::Generate() { + GLERROR("PRE"); + std::vector attachments; glGenFramebuffers(1, &m_BufferHandle); glBindFramebuffer(GL_FRAMEBUFFER, m_BufferHandle); + GLERROR("1"); for (auto it = m_Resources.begin(); it != m_Resources.end(); it++) { switch ((*it)->m_ResourceType) { @@ -56,20 +59,30 @@ void FrameBuffer::Generate() GLERROR("FrameBuffer generate: glFramebufferRenderbuffer"); break; } - + GLERROR("2"); - if ((*it)->m_Attachment != GL_DEPTH_ATTACHMENT) { + if ((*it)->m_Attachment != GL_DEPTH_ATTACHMENT && (*it)->m_Attachment != GL_STENCIL_ATTACHMENT && (*it)->m_Attachment != GL_DEPTH_STENCIL_ATTACHMENT) { attachments.push_back((*it)->m_Attachment); } + GLERROR("Attachment"); + } - + GLERROR("3"); + + GLenum* bufferTextures = &attachments[0]; glDrawBuffers(attachments.size(), bufferTextures); + if(GLERROR("4")) { + printf("hello"); + } if (GLenum frameBufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - LOG_ERROR("FrameBuffer incomplete: 0x%x\n", frameBufferStatus); + GLERROR("Framebuffer incomplete"); + //LOG_ERROR("FrameBuffer incomplete: 0x%x\n", frameBufferStatus); exit(EXIT_FAILURE); } + GLERROR("END"); + } void FrameBuffer::Bind() diff --git a/src/Engine/Rendering/LightCullingPass.cpp b/src/Engine/Rendering/LightCullingPass.cpp index 5e6da64d..0ae359db 100644 --- a/src/Engine/Rendering/LightCullingPass.cpp +++ b/src/Engine/Rendering/LightCullingPass.cpp @@ -16,7 +16,7 @@ LightCullingPass::~LightCullingPass() void LightCullingPass::GenerateNewFrustum(RenderScene& scene) { - if (scene.PointLightJobs.size() == 0) + if (scene.Jobs.PointLight.size() == 0) return; GLERROR("CalculateFrustum Error: Pre"); @@ -83,7 +83,7 @@ void LightCullingPass::FillLightList(RenderScene& scene) { m_LightSources.clear(); - for(auto &job : scene.PointLightJobs) { + for(auto &job : scene.Jobs.PointLight) { auto pointLightjob = std::dynamic_pointer_cast(job); if (pointLightjob) { LightSource p; @@ -97,7 +97,7 @@ void LightCullingPass::FillLightList(RenderScene& scene) m_LightSources.push_back(p); } } - for(auto &job : scene.DirectionalLightJobs) { + for(auto &job : scene.Jobs.DirectionalLight) { auto directionalLightJob = std::dynamic_pointer_cast(job); if(directionalLightJob) { LightSource p; diff --git a/src/Engine/Rendering/Model.cpp b/src/Engine/Rendering/Model.cpp index cf4923a3..3f8e20e1 100644 --- a/src/Engine/Rendering/Model.cpp +++ b/src/Engine/Rendering/Model.cpp @@ -5,26 +5,48 @@ Model::Model(std::string fileName) //Try loading the model asyncronously, if it throws any exceptions then let it propagate back to caller. m_RawModel = ResourceManager::Load(fileName); - for (auto& group : m_RawModel->MaterialGroups) { - if (!group.TexturePath.empty()) { - group.Texture = std::shared_ptr(ResourceManager::Load(group.TexturePath)); - } - if (!group.NormalMapPath.empty()) { - group.NormalMap = std::shared_ptr(ResourceManager::Load(group.NormalMapPath)); - } - if (!group.SpecularMapPath.empty()) { - group.SpecularMap = std::shared_ptr(ResourceManager::Load(group.SpecularMapPath)); - } - if (!group.IncandescenceMapPath.empty()) { - group.IncandescenceMap = std::shared_ptr(ResourceManager::Load(group.IncandescenceMapPath)); - } + for (auto& materialProperty : m_RawModel->m_Materials) { + switch (materialProperty.type) { + case RawModel::MaterialType::SingleTextures: + { + RawModel::MaterialSingleTextures* materialSingleTexture = static_cast(materialProperty.material); + materialSingleTexture->ColorMap.Texture = CommonFunctions::LoadTexture(materialSingleTexture->ColorMap.TexturePath, false); + materialSingleTexture->NormalMap.Texture = CommonFunctions::LoadTexture(materialSingleTexture->NormalMap.TexturePath, false); + materialSingleTexture->SpecularMap.Texture = CommonFunctions::LoadTexture(materialSingleTexture->SpecularMap.TexturePath, false); + materialSingleTexture->IncandescenceMap.Texture = CommonFunctions::LoadTexture(materialSingleTexture->IncandescenceMap.TexturePath, false); + } + break; + case RawModel::MaterialType::SplatMapping: + { + RawModel::MaterialSplatMapping* materialSplatMapping = static_cast(materialProperty.material); + materialSplatMapping->SplatMap.Texture = CommonFunctions::LoadTexture(materialSplatMapping->SplatMap.TexturePath, false); + for (auto& texture : materialSplatMapping->ColorMaps) + { + texture.Texture = CommonFunctions::LoadTexture(texture.TexturePath, false); + } + for (auto& texture : materialSplatMapping->NormalMaps) + { + texture.Texture = CommonFunctions::LoadTexture(texture.TexturePath, false); + } + for (auto& texture : materialSplatMapping->SpecularMaps) + { + texture.Texture = CommonFunctions::LoadTexture(texture.TexturePath, false); + } + for (auto& texture : materialSplatMapping->IncandescenceMaps) + { + texture.Texture = CommonFunctions::LoadTexture(texture.TexturePath, false); + } + } + break; + } } // Generate GL buffers GLuint buffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); - glBufferData(GL_ARRAY_BUFFER, m_RawModel->m_Vertices.size() * sizeof(RawModel::Vertex), &m_RawModel->m_Vertices[0], GL_STATIC_DRAW); + + glBufferData(GL_ARRAY_BUFFER, m_RawModel->NumVertices() * m_RawModel->VertexSize(), m_RawModel->Vertices(), GL_STATIC_DRAW); glGenBuffers(1, &ElementBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ElementBuffer); @@ -35,7 +57,13 @@ Model::Model(std::string fileName) GLERROR("GLEW: BufferFail4"); glBindBuffer(GL_ARRAY_BUFFER, buffer); - std::vector structSizes = { 3, 3, 3, 3, 2, 4, 4 }; + std::vector structSizes; + if (m_RawModel->IsSkinned()) { + structSizes = { 3, 3, 3, 3, 2, 4, 4 }; + } else { + structSizes = { 3, 3, 3, 3, 2 }; + } + int stride = 0; for (int size : structSizes) { stride += size; @@ -49,8 +77,10 @@ Model::Model(std::string fileName) glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; - glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; - glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; + if (m_RawModel->IsSkinned()) { + glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; + glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++; + } } GLERROR("GLEW: BufferFail5"); @@ -59,11 +89,24 @@ Model::Model(std::string fileName) glEnableVertexAttribArray(2); glEnableVertexAttribArray(3); glEnableVertexAttribArray(4); - glEnableVertexAttribArray(5); - glEnableVertexAttribArray(6); + if (m_RawModel->IsSkinned()) { + glEnableVertexAttribArray(5); + glEnableVertexAttribArray(6); + } GLERROR("GLEW: BufferFail5"); //CreateBuffers(); + + glm::vec3 mini(INFINITY); + glm::vec3 maxi(-INFINITY); + + for (unsigned int i = 0; i < m_RawModel->NumVertices(); i++) { + const auto& v = m_RawModel->Vertices()[i]; + mini = glm::min(mini, v.Position); + maxi = glm::max(maxi, v.Position); + } + + m_Box = AABB(mini, maxi); } Model::~Model() diff --git a/src/Engine/Rendering/PNG.cpp b/src/Engine/Rendering/PNG.cpp index 7ffd5c20..409da9b1 100644 --- a/src/Engine/Rendering/PNG.cpp +++ b/src/Engine/Rendering/PNG.cpp @@ -4,40 +4,35 @@ PNG::PNG(std::string path) { FILE* file = fopen(path.c_str(), "rb"); if (!file) { - LOG_ERROR("Failed to open texture file \"%s\": %s", path.c_str(), const_cast(strerror(errno))); - return; + throw Resource::FailedLoadingException("Failed to open texture file."); } png_byte header[8]; fread(header, 1, 8, file); bool isPNG = !png_sig_cmp(header, 0, 8); if (!isPNG) { - LOG_ERROR("Failed to load texture file \"%s\": File isn't PNG", path.c_str()); fclose(file); - return; + throw Resource::FailedLoadingException("File is not PNG."); } // Initialize libpng png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, (png_error_ptr)&PNG::pngErrorFunction, (png_error_ptr)&PNG::pngErrorFunction); if (!png_ptr) { - LOG_ERROR("libpng: Failed to initialze png_struct"); png_destroy_read_struct(&png_ptr, nullptr, nullptr); fclose(file); - return; + throw Resource::FailedLoadingException("Failed to initialze png_struct."); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { - LOG_ERROR("libpng: Failed to initialze png_info"); png_destroy_read_struct(&png_ptr, nullptr, nullptr); fclose(file); - return; + throw Resource::FailedLoadingException("Failed to initialze png_info."); } png_infop info_end_ptr = png_create_info_struct(png_ptr); if (!info_end_ptr) { - LOG_ERROR("libpng: Failed to initialze second png_info"); png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); fclose(file); - return; + throw Resource::FailedLoadingException("Failed to initialze second png_info."); } png_init_io(png_ptr, file); @@ -51,8 +46,8 @@ PNG::PNG(std::string path) unsigned int width, height; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); if (bit_depth != 8) { - LOG_ERROR("libpng: Unsupported bit depth \"%i\" of image \"%s\", must be 8", bit_depth, path.c_str()); - return; + throw Resource::FailedLoadingException("Unsupported bit depth. Must be 8"); + } switch (color_type) { case PNG_COLOR_TYPE_RGB: @@ -60,8 +55,7 @@ PNG::PNG(std::string path) Format = Image::ImageFormat::RGBA; break; default: - LOG_ERROR("libpng: Unsupported color format \"%i\" of image \"%s\"", color_type, path.c_str()); - return; + throw Resource::FailedLoadingException("Unsupported color format."); } // Convert RGB to RGBA, since DirectX rather treat them all the same way diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index abc79f2e..cc9837ff 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -41,6 +41,14 @@ void PickingPass::InitializeShaderPrograms() m_PickingProgram->Compile(); m_PickingProgram->BindFragDataLocation(0, "TextureFragment"); m_PickingProgram->Link(); + + m_PickingSkinnedProgram = ResourceManager::Load("#PickingSkinnedProgram"); + + m_PickingSkinnedProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/PickingSkinned.vert.glsl"))); + m_PickingSkinnedProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/Picking.frag.glsl"))); + m_PickingSkinnedProgram->Compile(); + m_PickingSkinnedProgram->BindFragDataLocation(0, "TextureFragment"); + m_PickingSkinnedProgram->Link(); } void PickingPass::Draw(RenderScene& scene) @@ -49,6 +57,7 @@ void PickingPass::Draw(RenderScene& scene) //TODO: Render: Add code for more jobs than modeljobs. GLuint shaderHandle = m_PickingProgram->GetHandle(); + GLuint shaderSkinnedHandle = m_PickingSkinnedProgram->GetHandle(); m_PickingProgram->Bind(); if (scene.ClearDepth) { @@ -56,7 +65,7 @@ void PickingPass::Draw(RenderScene& scene) } m_Camera = scene.Camera; - for (auto &job : scene.OpaqueObjects) { + for (auto &job : scene.Jobs.OpaqueObjects) { auto modelJob = std::dynamic_pointer_cast(job); if (modelJob) { @@ -83,17 +92,78 @@ void PickingPass::Draw(RenderScene& scene) 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->IsSkinned()) + { + m_PickingSkinnedProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + 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])); - } + std::vector frameBones; + frameBones = modelJob->Skeleton->GetBones(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } + } else { + m_PickingProgram->Bind(); + 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]))); + } + + 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))); + } + } + + for (auto &job : scene.Jobs.TransparentObjects) { + auto modelJob = std::dynamic_pointer_cast(job); + + 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] += 1; + } else { + m_ColorCounter[0] += 1; + } + } + + m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; + + if (modelJob) { + if (modelJob->Model->IsSkinned()) { + m_PickingSkinnedProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + + std::vector frameBones; + frameBones = modelJob->Skeleton->GetBones(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + } else { + m_PickingProgram->Bind(); + 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]))); } glBindVertexArray(modelJob->Model->VAO); @@ -102,7 +172,7 @@ void PickingPass::Draw(RenderScene& scene) } } - for (auto &job : scene.TransparentObjects) { + for (auto &job : scene.Jobs.OpaqueShieldedObjects) { auto modelJob = std::dynamic_pointer_cast(job); if (modelJob) { @@ -129,19 +199,87 @@ void PickingPass::Draw(RenderScene& scene) 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->IsSkinned()) { + m_PickingSkinnedProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); - if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + std::vector frameBones; + frameBones = modelJob->Skeleton->GetBones(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); - 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])); + } else { + m_PickingProgram->Bind(); + 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]))); + } + + 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))); + } + } + + for (auto &job : scene.Jobs.TransparentShieldedObjects) { + 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] += 1; + } else { + m_ColorCounter[0] += 1; } } + m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; + + if (modelJob->Model->IsSkinned()) { + m_PickingSkinnedProgram->Bind(); + + + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + + if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) { + + std::vector frameBones; + frameBones = modelJob->Skeleton->GetBones(); + glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); + + } + } else { + m_PickingProgram->Bind(); + + 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]))); + } + + + + 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))); @@ -160,8 +298,8 @@ void PickingPass::ClearPicking() { m_PickingColorsToEntity.clear(); m_EntityColors.clear(); - m_ColorCounter[0] = 1; - m_ColorCounter[1] = 0; + m_ColorCounter[0] = 0; + m_ColorCounter[1] = 1; m_PickingBuffer.Bind(); glClearColor(0.f, 0.f, 0.f, 0.f); diff --git a/src/Engine/Rendering/RawModelAssimp.cpp b/src/Engine/Rendering/RawModelAssimp.cpp index 7bf72a22..6b970f70 100644 --- a/src/Engine/Rendering/RawModelAssimp.cpp +++ b/src/Engine/Rendering/RawModelAssimp.cpp @@ -271,7 +271,7 @@ RawModelAssimp::RawModelAssimp(std::string fileName) skelAnim.Keyframes.push_back(animationFrame); } - m_Skeleton->Animations[animationName] = skelAnim; + m_Skeleton->Animations[animationName1] = skelAnim; } } diff --git a/src/Engine/Rendering/RawModelCustom.cpp b/src/Engine/Rendering/RawModelCustom.cpp index 59634625..4ebf80b6 100644 --- a/src/Engine/Rendering/RawModelCustom.cpp +++ b/src/Engine/Rendering/RawModelCustom.cpp @@ -34,13 +34,20 @@ void RawModelCustom::ReadMeshFile(std::string filePath) ReadMeshFileHeader(offset, fileData); ReadMesh(offset, fileData, fileByteSize); } - delete fileData; + delete[] fileData; } void RawModelCustom::ReadMeshFileHeader(std::size_t& offset, char* fileData) { #ifdef BOOST_LITTLE_ENDIAN - m_Vertices.resize(static_cast(*(unsigned int*)(fileData + offset))); + hasSkin = *(bool*)(fileData + offset); + offset += sizeof(bool); + if (hasSkin) { + m_SkinedVertices.resize(static_cast(*(unsigned int*)(fileData + offset))); + } + else { + m_Vertices.resize(static_cast(*(unsigned int*)(fileData + offset))); + } offset += sizeof(unsigned int); m_Indices.resize(static_cast(*(unsigned int*)(fileData + offset))); offset += sizeof(unsigned int); @@ -57,12 +64,19 @@ void RawModelCustom::ReadMesh(std::size_t& offset, char* fileData, const unsigne 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) { - throw Resource::FailedLoadingException("Reading vertices failed"); - } - - memcpy(&m_Vertices[0], fileData + offset, m_Vertices.size() * sizeof(Vertex)); - offset += m_Vertices.size() * sizeof(Vertex); + if (hasSkin) { + if (offset + m_SkinedVertices.size() * sizeof(SkinedVertex) > fileByteSize) { + throw Resource::FailedLoadingException("Reading skined vertices failed"); + } + memcpy(&m_SkinedVertices[0], fileData + offset, m_SkinedVertices.size() * sizeof(SkinedVertex)); + offset += m_SkinedVertices.size() * sizeof(SkinedVertex); + } else { + if (offset + m_Vertices.size() * sizeof(Vertex) > fileByteSize) { + throw Resource::FailedLoadingException("Reading vertices failed"); + } + memcpy(&m_Vertices[0], fileData + offset, m_Vertices.size() * sizeof(Vertex)); + offset += m_Vertices.size() * sizeof(Vertex); + } #else #endif } @@ -102,14 +116,14 @@ void RawModelCustom::ReadMaterialFile(std::string filePath) if (fileByteSize > 0) { ReadMaterials(offset, fileData, fileByteSize); } - delete fileData; + delete[] fileData; } 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); + m_Materials.reserve(*numMaterials); offset += sizeof(unsigned int); for (unsigned int i = 0; i < *numMaterials; i++) { @@ -121,83 +135,150 @@ void RawModelCustom::ReadMaterials(std::size_t& offset, char* fileData, const un void RawModelCustom::ReadMaterialSingle(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { - MaterialGroup newMaterial; - + MaterialProperties newMaterialProperty; #ifdef BOOST_LITTLE_ENDIAN - if (offset + sizeof(unsigned int) * 4 > fileByteSize) { - throw Resource::FailedLoadingException("Reading Material texture names length failed"); - } + if (offset + sizeof(MaterialType) > fileByteSize) { + throw Resource::FailedLoadingException("Reading Material Type failed"); + } + MaterialType type = *(MaterialType*)(fileData + offset); + offset += sizeof(MaterialType); - unsigned int* nameLengths = (unsigned int*)(fileData + offset); - offset += sizeof(unsigned int) * 4; + switch (type) { + case MaterialType::Basic: + newMaterialProperty.material = new MaterialBasic(); + ReadMaterialBasic(newMaterialProperty.material, offset, fileData, fileByteSize); + break; + case MaterialType::SplatMapping: + newMaterialProperty.material = new MaterialSplatMapping(); + ReadMaterialSplatMapping(static_cast(newMaterialProperty.material), offset, fileData, fileByteSize); + break; + case MaterialType::SingleTextures: + newMaterialProperty.material = new MaterialSingleTextures(); + ReadMaterialSingleTexture(static_cast(newMaterialProperty.material), offset, fileData, fileByteSize); + break; + default: + throw Resource::FailedLoadingException("Material contains an unknown MaterialType"); + }; - if (offset + sizeof(float) * 11 + sizeof(unsigned int) * 2 > fileByteSize) { - throw Resource::FailedLoadingException("Reading Material specular, reflection, color and start and end index values failed"); - } - - newMaterial.SpecularExponent = *(float*)(fileData + offset); - offset += sizeof(float); - newMaterial.ReflectionFactor = *(float*)(fileData + offset); - offset += sizeof(float); - - memcpy(&newMaterial.DiffuseColor[0], fileData + offset, sizeof(float) * 3); - offset += sizeof(float) * 3; - memcpy(&newMaterial.SpecularColor[0], fileData + offset, sizeof(float) * 3); - offset += sizeof(float) * 3; - memcpy(&newMaterial.IncandescenceColor[0], fileData + offset, sizeof(float) * 3); - offset += sizeof(float) * 3; - - newMaterial.StartIndex = *(unsigned int*)(fileData + offset); - offset += sizeof(unsigned int); - newMaterial.EndIndex = *(unsigned int*)(fileData + offset); - offset += sizeof(unsigned int); - - if (nameLengths[0] > 0) { - if (offset + nameLengths[0] > fileByteSize) { - throw Resource::FailedLoadingException("Reading Material texture path failed"); - } - - newMaterial.TexturePath = "Textures/"; - newMaterial.TexturePath += (fileData + offset); - newMaterial.TexturePath += ".png"; - offset += nameLengths[0]; - } - - if (nameLengths[1] > 0) { - if (offset + nameLengths[1] > fileByteSize) { - throw Resource::FailedLoadingException("Reading Material NormalMap path failed"); - } - newMaterial.NormalMapPath = "Textures/"; - newMaterial.NormalMapPath += (fileData + offset); - newMaterial.NormalMapPath += ".png"; - offset += nameLengths[1]; - } - - if (nameLengths[2] > 0) { - if (offset + nameLengths[2] > fileByteSize) { - throw Resource::FailedLoadingException("Reading Material SpecularMap path failed"); - } - newMaterial.SpecularMapPath = "Textures/"; - newMaterial.SpecularMapPath += (fileData + offset); - newMaterial.SpecularMapPath += ".png"; - offset += nameLengths[2]; - } - - if (nameLengths[3] > 0) { - if (offset + nameLengths[3] > fileByteSize) { - throw Resource::FailedLoadingException("Reading Material IncandescenceMap path failed"); - } - newMaterial.IncandescenceMapPath = "Textures/"; - newMaterial.IncandescenceMapPath += (fileData + offset); - newMaterial.IncandescenceMapPath += ".png"; - offset += nameLengths[3]; - } + newMaterialProperty.type = type; #else #endif - MaterialGroups.push_back(newMaterial); + m_Materials.push_back(newMaterialProperty); +} + +void RawModelCustom::ReadMaterialBasic(RawModelCustom::MaterialBasic* newMaterial, std::size_t& offset, char* fileData, const unsigned int& fileByteSize) +{ + if (offset + sizeof(float) * 11 + sizeof(unsigned int) * 2 > fileByteSize) { + throw Resource::FailedLoadingException("Reading Material specular, reflection, color and start and end index values failed"); + } + + newMaterial->SpecularExponent = *(float*)(fileData + offset); + offset += sizeof(float); + newMaterial->ReflectionFactor = *(float*)(fileData + offset); + offset += sizeof(float); + + memcpy(&newMaterial->DiffuseColor[0], fileData + offset, sizeof(float) * 3); + offset += sizeof(float) * 3; + memcpy(&newMaterial->SpecularColor[0], fileData + offset, sizeof(float) * 3); + offset += sizeof(float) * 3; + memcpy(&newMaterial->IncandescenceColor[0], fileData + offset, sizeof(float) * 3); + offset += sizeof(float) * 3; + + newMaterial->StartIndex = *(unsigned int*)(fileData + offset); + offset += sizeof(unsigned int); + newMaterial->EndIndex = *(unsigned int*)(fileData + offset); + offset += sizeof(unsigned int); +} + +void RawModelCustom::ReadMaterialSingleTexture(RawModelCustom::MaterialSingleTextures* newMaterial, std::size_t& offset, char* fileData, const unsigned int& fileByteSize) +{ + ReadMaterialBasic(newMaterial, offset, fileData, fileByteSize); + if (offset + sizeof(unsigned char) * 4 > fileByteSize) { + throw Resource::FailedLoadingException("Reading Material NumOfMaps failed"); + } + unsigned char numberOfMaps[4]; + memcpy(numberOfMaps, fileData + offset, sizeof(unsigned char) * 4); + offset += sizeof(unsigned char) * 4; + + if (numberOfMaps[0] > 0) + { + ReadMaterialTextureProperties(newMaterial->ColorMap, offset, fileData, fileByteSize); + } + + if (numberOfMaps[1] > 0) + { + ReadMaterialTextureProperties(newMaterial->SpecularMap, offset, fileData, fileByteSize); + } + + if (numberOfMaps[2] > 0) + { + ReadMaterialTextureProperties(newMaterial->NormalMap, offset, fileData, fileByteSize); + } + + if (numberOfMaps[3] > 0) + { + ReadMaterialTextureProperties(newMaterial->IncandescenceMap, offset, fileData, fileByteSize); + } +} + +void RawModelCustom::ReadMaterialSplatMapping(RawModelCustom::MaterialSplatMapping* newMaterial, std::size_t& offset, char* fileData, const unsigned int& fileByteSize) +{ + ReadMaterialBasic(newMaterial, offset, fileData, fileByteSize); + ReadMaterialTextureProperties(newMaterial->SplatMap, offset, fileData, fileByteSize); + if (offset + sizeof(unsigned char) * 4 > fileByteSize) { + throw Resource::FailedLoadingException("Reading Material NumOfMaps failed"); + } + + unsigned char numberOfMaps[4]; + memcpy(numberOfMaps, fileData + offset, sizeof(unsigned char) * 4); + offset += sizeof(unsigned char) * 4; + + newMaterial->ColorMaps.resize(numberOfMaps[0]); + for (unsigned char i = 0; i < numberOfMaps[0]; i++) + { + ReadMaterialTextureProperties(newMaterial->ColorMaps[i], offset, fileData, fileByteSize); + } + + newMaterial->SpecularMaps.resize(numberOfMaps[1]); + for (unsigned char i = 0; i < numberOfMaps[1]; i++) + { + ReadMaterialTextureProperties(newMaterial->SpecularMaps[i], offset, fileData, fileByteSize); + } + + newMaterial->NormalMaps.resize(numberOfMaps[2]); + for (unsigned char i = 0; i < numberOfMaps[2]; i++) + { + ReadMaterialTextureProperties(newMaterial->NormalMaps[i], offset, fileData, fileByteSize); + } + + newMaterial->IncandescenceMaps.resize(numberOfMaps[3]); + for (unsigned char i = 0; i < numberOfMaps[3]; i++) + { + ReadMaterialTextureProperties(newMaterial->IncandescenceMaps[i], offset, fileData, fileByteSize); + } +} + +void RawModelCustom::ReadMaterialTextureProperties(RawModelCustom::TextureProperties& texture, std::size_t& offset, char* fileData, const unsigned int& fileByteSize) { + unsigned int nameLength = *(unsigned int*)(fileData + offset); + offset += sizeof(unsigned int); + + if (nameLength > 0) { + if (offset + nameLength > fileByteSize) { + throw Resource::FailedLoadingException("Reading Material texture path failed"); + } + texture.TexturePath = "Textures/"; + texture.TexturePath += (fileData + offset); + texture.TexturePath += ".png"; + offset += nameLength; + if (offset + sizeof(glm::vec2) > fileByteSize) { + throw Resource::FailedLoadingException("Reading Material texture UVTiling failed"); + } + memcpy(&texture.UVRepeat[0], fileData + offset, sizeof(glm::vec2)); + offset += sizeof(glm::vec2); + } } void RawModelCustom::ReadAnimationFile(std::string filePath) @@ -207,7 +288,9 @@ void RawModelCustom::ReadAnimationFile(std::string filePath) std::ifstream in(filePath.c_str(), std::ios_base::binary | std::ios_base::ate); if (!in.is_open()) { - //throw Resource::FailedLoadingException("Open animation file failed"); + if (hasSkin) { + throw Resource::FailedLoadingException("Open animation file for a skinned mesh failed, unknown stuff will happen"); + } return; } @@ -233,7 +316,7 @@ void RawModelCustom::ReadAnimationFile(std::string filePath) ReadAnimationBindPoses(offset, fileData, fileByteSize); ReadAnimationClips(offset, fileData, fileByteSize, numAnimations); } - delete fileData; + delete[] fileData; } void RawModelCustom::ReadAnimationBindPoses(std::size_t& offset, char* fileData, const unsigned int& fileByteSize) @@ -318,32 +401,43 @@ void RawModelCustom::ReadAnimationClipSingle(std::size_t& offset, char* fileData if (offset + sizeof(float) > fileByteSize) { throw Resource::FailedLoadingException("Reading AnimationClip duration failed"); } - newAnimation.Duration = *(float*)(fileData + offset); offset += sizeof(float); if (offset + sizeof(unsigned int) > fileByteSize) { - throw Resource::FailedLoadingException("Reading AnimationClip NrOfKeyframes failed"); + throw Resource::FailedLoadingException("Reading AnimationClip numberOfJointFrames failed"); } - unsigned int nrOfKeyframes = *(unsigned int*)(fileData + offset); + unsigned int numberOfJointFrames = *(unsigned int*)(fileData + offset); offset += sizeof(unsigned int); - if (offset + sizeof(unsigned int) > fileByteSize) { - throw Resource::FailedLoadingException("Reading AnimationClip NrOfJoints failed"); - } - unsigned int nrOfJoints = *(unsigned int*)(fileData + offset); - offset += sizeof(unsigned int); + for (unsigned int i = 0; i < numberOfJointFrames; i++) { + if (offset + sizeof(unsigned int) > fileByteSize) { + throw Resource::FailedLoadingException("Reading AnimationClip JointID failed"); + } + int jointID = *(unsigned int*)(fileData + offset); + offset += sizeof(unsigned int); - newAnimation.Keyframes.reserve(nrOfKeyframes); - for (unsigned int i = 0; i < nrOfKeyframes; i++) { - ReadAnimationKeyFrame(offset, fileData, fileByteSize, nrOfJoints, newAnimation); + if (offset + sizeof(unsigned int) > fileByteSize) { + throw Resource::FailedLoadingException("Reading AnimationClip numberOFKeyFrames failed"); + } + unsigned int numberOFKeyFrames = *(unsigned int*)(fileData + offset); + offset += sizeof(unsigned int); + + if (numberOFKeyFrames > 0) { + newAnimation.JointAnimations[jointID].reserve(numberOFKeyFrames); + + for (unsigned int j = 0; j < numberOFKeyFrames; j++) { + ReadAnimationKeyFrame(offset, fileData, fileByteSize, newAnimation.JointAnimations[jointID]); + } + } } m_Skeleton->Animations[newAnimation.Name] = newAnimation; + //m_Skeleton->Animations[newAnimation.Name].KeyFrameAmount = nrOfKeyframes; #else #endif } -void RawModelCustom::ReadAnimationKeyFrame(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int numberOfJoints, Skeleton::Animation& animation) +void RawModelCustom::ReadAnimationKeyFrame(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, std::vector& animation) { Skeleton::Animation::Keyframe newKeyFrame; @@ -359,17 +453,27 @@ void RawModelCustom::ReadAnimationKeyFrame(std::size_t& offset, char* fileData, newKeyFrame.Time = *(float*)(fileData + offset); offset += sizeof(float); - if (offset + sizeof(Skeleton::Animation::Keyframe::BoneProperty) * numberOfJoints> fileByteSize) { - throw Resource::FailedLoadingException("Reading AnimationKeyFrame joints failed"); + if (offset + sizeof(float) * 3 > fileByteSize) { + throw Resource::FailedLoadingException("Reading AnimationKeyFrame Position failed"); } + memcpy(&newKeyFrame.BoneProperties.Position[0], fileData + offset, sizeof(float) * 3); + offset += sizeof(float) * 3; - Skeleton::Animation::Keyframe::BoneProperty newBone; - 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; + if (offset + sizeof(float) * 4 > fileByteSize) { + throw Resource::FailedLoadingException("Reading AnimationKeyFrame Rotation failed"); } - animation.Keyframes.push_back(newKeyFrame); + memcpy(&newKeyFrame.BoneProperties.Rotation[0], fileData + offset, sizeof(float) * 4); + offset += sizeof(float) * 4; + + if (offset + sizeof(float) * 3 > fileByteSize) { + throw Resource::FailedLoadingException("Reading AnimationKeyFrame Scale failed"); + } + memcpy(&newKeyFrame.BoneProperties.Scale[0], fileData + offset, sizeof(float) * 3); + offset += sizeof(float) * 3; + + + animation.push_back(newKeyFrame); + } RawModelCustom::~RawModelCustom() @@ -377,6 +481,9 @@ RawModelCustom::~RawModelCustom() if (m_Skeleton != nullptr) { delete m_Skeleton; } + for (auto material : m_Materials) { + delete material.material; + } } #endif \ No newline at end of file diff --git a/src/Engine/Rendering/RenderState.cpp b/src/Engine/Rendering/RenderState.cpp index 1da2f0b1..26ba18a1 100644 --- a/src/Engine/Rendering/RenderState.cpp +++ b/src/Engine/Rendering/RenderState.cpp @@ -6,9 +6,10 @@ bool RenderState::Enable(GLenum cap) //LOG_WARNING("Trying to enable somthing that is already enabled."); return false; } + m_ResetFunctions.push_back(std::bind(glDisable, cap)); glEnable(cap); - return !GLERROR("RenderState::Enable"); + return !GLERROR("Enable"); } bool RenderState::Disable(GLenum cap) @@ -16,9 +17,10 @@ bool RenderState::Disable(GLenum cap) if (!glIsEnabled(cap)) { return false; } + m_ResetFunctions.push_back(std::bind(glEnable, cap)); glDisable(cap); - return !GLERROR("RenderState::Disable"); + return !GLERROR("Disable"); } bool RenderState::CullFace(GLenum mode) @@ -32,7 +34,7 @@ bool RenderState::CullFace(GLenum mode) glGetIntegerv(GL_CULL_FACE_MODE, &original); m_ResetFunctions.push_back(std::bind(glCullFace, original)); glCullFace(mode); - return !GLERROR("RenderState::CullFace"); + return !GLERROR("CullFace"); } bool RenderState::ClearColor(glm::vec4 color) @@ -41,7 +43,7 @@ bool RenderState::ClearColor(glm::vec4 color) glGetFloatv(GL_COLOR_CLEAR_VALUE, &original[0]); m_ResetFunctions.push_back(std::bind(glClearColor, original[0], original[1], original[2], original[3])); glClearColor(color.r, color.g, color.b, color.a); - return !GLERROR("RenderState::ClearColor"); + return !GLERROR("ClearColor"); } bool RenderState::BindFramebuffer(GLint framebuffer) @@ -55,7 +57,7 @@ bool RenderState::BindFramebuffer(GLint framebuffer) glBindFramebuffer(GL_DRAW_FRAMEBUFFER, originalDraw); }); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - return !GLERROR("RenderState::BindBuffer"); + return !GLERROR("BindBuffer"); } @@ -67,7 +69,7 @@ bool RenderState::BlendEquation(GLenum mode) glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &originalAlpha); m_ResetFunctions.push_back(std::bind(glBlendEquationSeparate, originalRGB, originalAlpha)); glBlendEquation(mode); - return !GLERROR("RenderState::BlendEquation"); + return !GLERROR("BlendEquation"); } bool RenderState::BlendFunc(GLenum sfactor, GLenum dfactor) @@ -82,7 +84,46 @@ bool RenderState::BlendFunc(GLenum sfactor, GLenum dfactor) glGetIntegerv(GL_BLEND_DST_ALPHA, &originalDestAlpha); m_ResetFunctions.push_back(std::bind(glBlendFuncSeparate, originalSrcRGB, originalSrcAlpha, originalDestRGB, originalDestAlpha)); glBlendFunc(sfactor, dfactor); - return !GLERROR("RenderState::BlendFunc"); + return !GLERROR("BlendFunc"); +} + + +bool RenderState::StencilOp(GLenum sfail, GLenum dpfail, GLenum dppass) +{ + GLint originalSFail; + glGetIntegerv(GL_STENCIL_FAIL, &originalSFail); + GLint originalDPFail; + glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &originalDPFail); + GLint originalDPPass; + glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &originalDPPass); + m_ResetFunctions.push_back(std::bind(glStencilOp, originalSFail, originalDPFail, originalDPPass)); + glStencilOp(sfail, dpfail, dppass); + return !GLERROR("StencilOp"); +} + + +bool RenderState::StencilFunc(GLenum func, GLint ref, GLuint mask) +{ + GLint originalFunc; + glGetIntegerv(GL_STENCIL_FUNC, &originalFunc); + GLint originalRef; + glGetIntegerv(GL_STENCIL_REF, &originalRef); + GLint originalMask; + glGetIntegerv(GL_STENCIL_VALUE_MASK, &originalMask); + m_ResetFunctions.push_back(std::bind(glStencilFunc, originalFunc, originalRef, originalMask)); + glStencilFunc(func, ref, mask); + return !GLERROR("StencilFunc"); +} + + + +bool RenderState::StencilMask(GLuint mask) +{ + GLint originalMask; + glGetIntegerv(GL_STENCIL_WRITEMASK, &originalMask); + m_ResetFunctions.push_back(std::bind(glStencilMask, mask)); + glStencilMask(mask); + return !GLERROR("StencilMask"); } bool RenderState::DepthMask(GLboolean flag) @@ -91,12 +132,12 @@ bool RenderState::DepthMask(GLboolean flag) glGetBooleanv(GL_DEPTH_WRITEMASK, &original); m_ResetFunctions.push_back(std::bind(glDepthMask, original)); glDepthMask(flag); - return !GLERROR("RenderState::DepthMask"); + return !GLERROR("DepthMask"); } RenderState::~RenderState() { - for (auto& f : m_ResetFunctions) { + for (auto& f : boost::adaptors::reverse(m_ResetFunctions)) { f(); } } diff --git a/src/Engine/Rendering/RenderSystem.cpp b/src/Engine/Rendering/RenderSystem.cpp index 3a1729fc..6600bc4f 100644 --- a/src/Engine/Rendering/RenderSystem.cpp +++ b/src/Engine/Rendering/RenderSystem.cpp @@ -1,10 +1,12 @@ #include "Rendering/RenderSystem.h" +#include "Collision/Collision.h" +#include "Core/Frustum.h" -RenderSystem::RenderSystem(World* world, EventBroker* eventBroker, const IRenderer* renderer, RenderFrame* renderFrame) - : System(world, eventBroker) +RenderSystem::RenderSystem(SystemParams params, const IRenderer* renderer, RenderFrame* renderFrame, Octree* frustumCullOctree) + : System(params) , m_Renderer(renderer) , m_RenderFrame(renderFrame) - , m_World(world) + , m_Octree(frustumCullOctree) { EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &RenderSystem::OnSetCamera); EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &RenderSystem::OnInputCommand); @@ -60,6 +62,7 @@ void RenderSystem::fillSprites(std::list>& jobs, Worl std::string diffuseResource = cSprite["DiffuseTexture"]; std::string glowResource = cSprite["GlowMap"]; + bool depthSorted = cSprite["DepthSort"]; if (diffuseResource.empty() && glowResource.empty()) { continue; } @@ -75,7 +78,8 @@ void RenderSystem::fillSprites(std::list>& jobs, Worl glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, world); //modelMatrix *= m_Camera->BillboardMatrix(); - std::shared_ptr spriteJob = std::shared_ptr(new SpriteJob(cSprite, m_Camera, modelMatrix, world, fillColor, fillPercentage)); + + std::shared_ptr spriteJob = std::shared_ptr(new SpriteJob(cSprite, m_Camera, modelMatrix, world, fillColor, fillPercentage, depthSorted)); jobs.push_back(spriteJob); } @@ -90,14 +94,15 @@ bool RenderSystem::isChildOfCurrentCamera(EntityWrapper entity) return entity == m_CurrentCamera || entity.IsChildOf(m_CurrentCamera); } -void RenderSystem::fillModels(std::list>& opaqueJobs, std::list>& transparentJobs) +void RenderSystem::fillModels(RenderScene::Queues &Jobs) { - auto models = m_World->GetComponents("Model"); - if (models == nullptr) { - return; - } + Frustum frustum(m_Camera->ProjectionMatrix() * m_Camera->ViewMatrix()); + std::vector seenEntities; + m_Octree->ObjectsInFrustum(frustum, seenEntities); - for (auto& cModel : *models) { + for (auto& seenEntity : seenEntities) { + EntityWrapper entity = seenEntity.Entity; + ComponentWrapper cModel = entity["Model"]; bool visible = cModel["Visible"]; if (!visible) { continue; @@ -107,15 +112,13 @@ void RenderSystem::fillModels(std::list>& opaqueJobs, continue; } - EntityWrapper entity(m_World, cModel.EntityID); - // 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))) { + if ((entity.HasComponent("HiddenForLocalPlayer") || entity.FirstParentWithComponent("HiddenForLocalPlayer").Valid()) && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))) { continue; } @@ -142,7 +145,9 @@ void RenderSystem::fillModels(std::list>& opaqueJobs, } glm::mat4 modelMatrix = Transform::ModelMatrix(cModel.EntityID, m_World); + //Loop through all materialgroups of a model for (auto matGroup : model->MaterialGroups()) { + //If the model has an explosioneffect component, we will add an explosioneffectjob if (m_World->HasComponent(cModel.EntityID, "ExplosionEffect")) { auto explosionEffectComponent = m_World->GetComponent(cModel.EntityID, "ExplosionEffect"); std::shared_ptr explosionEffectJob = std::shared_ptr(new ExplosionEffectJob( @@ -156,14 +161,33 @@ void RenderSystem::fillModels(std::list>& opaqueJobs, fillColor, fillPercentage )); - if(explosionEffectJob->Color.a != 1.f || explosionEffectJob->EndColor.a != 1.f || explosionEffectJob->DiffuseColor.a != 1.f) { - cModel["Transparent"] = true; - } + if (m_World->HasComponent(cModel.EntityID, "Shield")){ + explosionEffectJob->CalculateHash(); + Jobs.ShieldObjects.push_back(explosionEffectJob); + } else if (m_World->HasComponent(cModel.EntityID, "Shielded") + || m_World->HasComponent(cModel.EntityID, "Player")) { - if (cModel["Transparent"]) { - transparentJobs.push_back(explosionEffectJob); + if (explosionEffectJob->Color.a != 1.f || explosionEffectJob->EndColor.a != 1.f || explosionEffectJob->DiffuseColor.a != 1.f) { + cModel["Transparent"] = true; + } + + if (cModel["Transparent"]) { + Jobs.TransparentShieldedObjects.push_back(explosionEffectJob); + } else { + explosionEffectJob->CalculateHash(); + Jobs.OpaqueShieldedObjects.push_back(explosionEffectJob); + } } else { - opaqueJobs.push_back(explosionEffectJob); + if (explosionEffectJob->Color.a != 1.f || explosionEffectJob->EndColor.a != 1.f || explosionEffectJob->DiffuseColor.a != 1.f) { + cModel["Transparent"] = true; + } + + if (cModel["Transparent"]) { + Jobs.TransparentObjects.push_back(explosionEffectJob); + } else { + explosionEffectJob->CalculateHash(); + Jobs.OpaqueObjects.push_back(explosionEffectJob); + } } } else { std::shared_ptr modelJob = std::shared_ptr(new ModelJob( @@ -176,13 +200,33 @@ void RenderSystem::fillModels(std::list>& opaqueJobs, fillColor, fillPercentage )); - if (modelJob->Color.a != 1.f || modelJob->DiffuseColor.a != 1.f) { - cModel["Transparent"] = true; - } - if (cModel["Transparent"]) { - transparentJobs.push_back(modelJob); + if (m_World->HasComponent(cModel.EntityID, "Shield")) { + modelJob->CalculateHash(); + Jobs.ShieldObjects.push_back(modelJob); + } else if (m_World->HasComponent(cModel.EntityID, "Shielded") + || m_World->HasComponent(cModel.EntityID, "Player")) { + + if (modelJob->Color.a != 1.f || modelJob->DiffuseColor.a != 1.f) { + cModel["Transparent"] = true; + } + + if (cModel["Transparent"]) { + Jobs.TransparentShieldedObjects.push_back(modelJob); + } else { + modelJob->CalculateHash(); + Jobs.OpaqueShieldedObjects.push_back(modelJob); + } } else { - opaqueJobs.push_back(modelJob); + if (modelJob->Color.a != 1.f || modelJob->DiffuseColor.a != 1.f) { + cModel["Transparent"] = true; + } + + if (cModel["Transparent"]) { + Jobs.TransparentObjects.push_back(modelJob); + } else { + modelJob->CalculateHash(); + Jobs.OpaqueObjects.push_back(modelJob); + } } } } @@ -244,7 +288,7 @@ void RenderSystem::fillText(std::list>& jobs, World* if (texts == nullptr) { return; } - + for (auto& textComponent : *texts) { bool visible = textComponent["Visible"]; if (!visible) { @@ -299,11 +343,13 @@ void RenderSystem::Update(double dt) scene.AmbientColor = (glm::vec4)(*cSceneLight->begin())["AmbientColor"]; } - fillModels(scene.OpaqueObjects, scene.TransparentObjects); - fillPointLights(scene.PointLightJobs, m_World); - fillDirectionalLights(scene.DirectionalLightJobs, m_World); - fillText(scene.TextJobs, m_World); - fillSprites(scene.SpriteJobs, m_World); + fillModels(scene.Jobs); + fillPointLights(scene.Jobs.PointLight, m_World); + //TODO: Make sure all objects needed are also sorted. + scene.Jobs.OpaqueObjects.sort(); + fillSprites(scene.Jobs.SpriteJob, m_World); + fillDirectionalLights(scene.Jobs.DirectionalLight, m_World); + fillText(scene.Jobs.Text, m_World); m_RenderFrame->Add(scene); } \ No newline at end of file diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index a63e02a0..173ddb2b 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -51,7 +51,7 @@ void Renderer::InitializeWindow() ss << " DEBUG"; #endif LOG_INFO(ss.str().c_str()); - glfwSetWindowTitle(m_Window, ss.str().c_str()); + SetWindowTitle(ss.str()); // Initialize GLEW if (glewInit() != GLEW_OK) { @@ -93,7 +93,7 @@ void Renderer::Update(double dt) void Renderer::Draw(RenderFrame& frame) { - ImGui::Combo("Draw textures", &m_DebugTextureToDraw, "Final\0Scene\0Bloom\0Gaussian\0Picking"); + ImGui::Combo("Draw textures", &m_DebugTextureToDraw, "Final\0Scene\0Bloom\0SceneLowRes\0BloomLowRes\0Gaussian\0Picking"); //clear buffer 0 glClearColor(0.f, 0.f, 0.f, 0.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -106,21 +106,26 @@ void Renderer::Draw(RenderFrame& frame) for (auto scene : frame.RenderScenes){ SortRenderJobsByDepth(*scene); + GLERROR("SortByDepth"); m_PickingPass->Draw(*scene); + GLERROR("Drawing pickingpass"); m_LightCullingPass->GenerateNewFrustum(*scene); + GLERROR("Generate frustums"); m_LightCullingPass->FillLightList(*scene); + GLERROR("Filling light list"); m_LightCullingPass->CullLights(*scene); + GLERROR("LightCulling"); m_DrawFinalPass->Draw(*scene); + GLERROR("Draw Geometry+Light"); //m_DrawScenePass->Draw(*scene); - GLERROR("Renderer::Draw m_DrawScenePass->Draw"); - m_TextPass->Draw(*scene, *m_DrawFinalPass->FinalPassFrameBuffer()); + GLERROR("Draw Text"); } m_DrawBloomPass->Draw(m_DrawFinalPass->BloomTexture()); if (m_DebugTextureToDraw == 0) { - m_DrawColorCorrectionPass->Draw(m_DrawFinalPass->SceneTexture(), m_DrawBloomPass->GaussianTexture(), frame.Gamma, frame.Exposure); + m_DrawColorCorrectionPass->Draw(m_DrawFinalPass->SceneTexture(), m_DrawBloomPass->GaussianTexture(), m_DrawFinalPass->SceneTextureLowRes(), m_DrawFinalPass->BloomTextureLowRes(), frame.Gamma, frame.Exposure); } if (m_DebugTextureToDraw == 1) { m_DrawScreenQuadPass->Draw(m_DrawFinalPass->SceneTexture()); @@ -129,14 +134,21 @@ void Renderer::Draw(RenderFrame& frame) m_DrawScreenQuadPass->Draw(m_DrawFinalPass->BloomTexture()); } if (m_DebugTextureToDraw == 3) { - m_DrawScreenQuadPass->Draw(m_DrawBloomPass->GaussianTexture()); + m_DrawScreenQuadPass->Draw(m_DrawFinalPass->SceneTextureLowRes()); } if (m_DebugTextureToDraw == 4) { + m_DrawScreenQuadPass->Draw(m_DrawFinalPass->BloomTextureLowRes()); + } + if (m_DebugTextureToDraw == 5) { + m_DrawScreenQuadPass->Draw(m_DrawBloomPass->GaussianTexture()); + } + if (m_DebugTextureToDraw == 6) { m_DrawScreenQuadPass->Draw(m_PickingPass->PickingTexture()); } m_ImGuiRenderPass->Draw(); - glfwSwapBuffers(m_Window); + GLERROR("Imgui draw"); + glfwSwapBuffers(m_Window); } PickData Renderer::Pick(glm::vec2 screenCoord) @@ -146,15 +158,16 @@ PickData Renderer::Pick(glm::vec2 screenCoord) void Renderer::InitializeTextures() { - m_ErrorTexture = ResourceManager::Load("Textures/Core/ErrorTexture.png"); - m_WhiteTexture = ResourceManager::Load("Textures/Core/White.png"); + m_ErrorTexture = CommonFunctions::LoadTexture("Textures/Core/ErrorTexture.png", false); + m_WhiteTexture = CommonFunctions::LoadTexture("Textures/Core/White.png", false); } void Renderer::SortRenderJobsByDepth(RenderScene &scene) { //Sort all forward jobs so transparency is good. - scene.TransparentObjects.sort(Renderer::DepthSort); + scene.Jobs.TransparentObjects.sort(Renderer::DepthSort); + scene.Jobs.SpriteJob.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/Skeleton.cpp b/src/Engine/Rendering/Skeleton.cpp index 851408a4..82d50522 100644 --- a/src/Engine/Rendering/Skeleton.cpp +++ b/src/Engine/Rendering/Skeleton.cpp @@ -29,6 +29,32 @@ Skeleton::~Skeleton() } } + +void Skeleton::CalculateFrameBones(std::vector animations, AnimationOffset animationOffset, bool noRootMotion /*= false*/) +{ + if (animations.size() <= 0 || animationOffset.animation == nullptr) { + for (auto& b : Bones) { + m_BoneLocalTransforms[b.first] = glm::mat4(1); + m_BoneTransforms[b.first] = glm::mat4(1); + } + } else { + AccumulateBoneTransforms(noRootMotion, animations, animationOffset, RootBone, glm::mat4(1)); + } +} + + +void Skeleton::CalculateFrameBones(std::vector animations, bool noRootMotion /*= false*/) +{ + if (animations.size() <= 0) { + for (auto& b : Bones) { + m_BoneLocalTransforms[b.first] = glm::mat4(1); + m_BoneTransforms[b.first] = glm::mat4(1); + } + } else { + AccumulateBoneTransforms(noRootMotion, animations, RootBone, glm::mat4(1)); + } +} + const Skeleton::Animation* Skeleton::GetAnimation(std::string name) { auto it = Animations.find(name); @@ -39,66 +65,375 @@ const Skeleton::Animation* Skeleton::GetAnimation(std::string name) } } -std::vector Skeleton::GetFrameBones(const Animation& animation, double time, bool noRootMotion /*= false*/) -{ - // HACK: Animation wrap-around - while (time < 0) { - time += animation.Duration; - } - while (time > animation.Duration) { - time -= animation.Duration; - } - - int currentKeyframeIndex = GetKeyframe(animation, time); - - const Animation::Keyframe& currentFrame = animation.Keyframes[currentKeyframeIndex]; - const Animation::Keyframe& nextFrame = animation.Keyframes[(currentKeyframeIndex + 1) % animation.Keyframes.size()]; - double alpha = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); - - //auto animationFrame = Animations[""].Keyframes[frame]; - std::map frameBones; - AccumulateBoneTransforms(noRootMotion, currentFrame, nextFrame, static_cast(alpha), frameBones, RootBone, glm::mat4(1)); - - std::vector finalMatrices; - for (auto &kv : frameBones) { - finalMatrices.push_back(kv.second); - } - return finalMatrices; -} - -void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation::Keyframe ¤tFrame, const Animation::Keyframe &nextFrame, float progress, std::map &boneMatrices, const Bone* bone, glm::mat4 parentMatrix) +void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, AnimationOffset animationOffset, const Bone* bone, glm::mat4 parentMatrix) { glm::mat4 boneMatrix; - if (currentFrame.BoneProperties.find(bone->ID) != currentFrame.BoneProperties.end() || nextFrame.BoneProperties.find(bone->ID) != nextFrame.BoneProperties.end()) { - Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties.at(bone->ID); - Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties.at(bone->ID); + std::vector JointTransforms; - glm::vec3 positionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; - glm::quat rotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); - glm::vec3 scaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + for (const AnimationData animationData : animations) { + const Animation* animation = animationData.animation; + const float time = animationData.time; - // Flag for no root motion - if (bone == RootBone && noRootMotion) { - positionInterp.x = 0; - positionInterp.z = 0; - } + JointFrameTransform jointTransform; + jointTransform.Weight = animationData.weight;; + + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); + + Animation::Keyframe currentFrame; + Animation::Keyframe nextFrame; + + if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone + for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame + if (time >= boneKeyFrames.at(index).Time) { + currentFrame = boneKeyFrames.at(index); + nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); + break; + } + } + + float progress; + + if (nextFrame.Index == 0) { + nextFrame = currentFrame; + progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); + } else { + progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + + } - boneMatrix = parentMatrix * (glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)); - boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix; - } else { - if (bone->Parent) { - boneMatrix = parentMatrix; // * glm::inverse(bone->OffsetMatrix); + if (progress > 1.0f || progress < 0.0f) { + progress = glm::clamp(progress, 0.0f, 1.0f); + } + Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; + Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; + + jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; + jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); + jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + + // Flag for no root motion + if (bone == RootBone && noRootMotion) { + jointTransform.PositionInterp.x = 0; + jointTransform.PositionInterp.z = 0; + } + + JointTransforms.push_back(jointTransform); + + } else { // 1 keyframes for the current bone + currentFrame = boneKeyFrames.at(0); + jointTransform.PositionInterp = currentFrame.BoneProperties.Position; + jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation; + jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale; + JointTransforms.push_back(jointTransform); + + } + } else { // 0 keyframes for the current bone + } - boneMatrices[bone->ID] = boneMatrix; // * bone->OffsetMatrix; - } - for (auto &child : bone->Children) { - std::string name = child->Name; - AccumulateBoneTransforms(noRootMotion, currentFrame, nextFrame, progress, boneMatrices, child, boneMatrix); - } + } + + glm::mat4 offset = GetOffsetTransform(bone, animationOffset); + + if (JointTransforms.size() == 0) { + if (bone->Parent) { + if (offset != glm::mat4(1)) { + boneMatrix = parentMatrix * offset;// *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)); + } else { + boneMatrix = parentMatrix *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)); + + } + m_BoneLocalTransforms[bone->ID] = boneMatrix * bone->OffsetMatrix; + m_BoneTransforms[bone->ID] = boneMatrix; + } else { + boneMatrix = offset * glm::inverse(bone->OffsetMatrix); + m_BoneLocalTransforms[bone->ID] = parentMatrix; + m_BoneTransforms[bone->ID] = boneMatrix; + } + } else { + + glm::vec3 finalPosInterp; + glm::quat finalRotInterp; + glm::vec3 finalScaleInterp; + float totalWeight = 0; + + for (JointFrameTransform jointTransform : JointTransforms) { + totalWeight += jointTransform.Weight; + } + + + for (JointFrameTransform jointTransform : JointTransforms) { + if (jointTransform.Weight == 1.0f) { + finalPosInterp = jointTransform.PositionInterp; + finalRotInterp = jointTransform.RotationInterp; + finalScaleInterp = jointTransform.ScaleInterp; + break; + } else { + finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight); + finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight)); + finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight); + } + + } + + + if (offset != glm::mat4(1)) { + boneMatrix = parentMatrix * ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset); + } else { + boneMatrix = parentMatrix * (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)); + } + + m_BoneLocalTransforms[bone->ID] = boneMatrix * bone->OffsetMatrix; + m_BoneTransforms[bone->ID] = boneMatrix; + } + + for (auto &child : bone->Children) { + AccumulateBoneTransforms(noRootMotion, animations, animationOffset, child, boneMatrix); + } +} + +void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector animations, const Bone* bone, glm::mat4 parentMatrix) +{ + glm::mat4 boneMatrix; + std::vector JointTransforms; + + for (const AnimationData animationData : animations) { + const Animation* animation = animationData.animation; + const float time = animationData.time; + + JointFrameTransform jointTransform; + jointTransform.Weight = animationData.weight;; + + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); + + Animation::Keyframe currentFrame; + Animation::Keyframe nextFrame; + + if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone + for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame + if (time >= boneKeyFrames.at(index).Time) { + currentFrame = boneKeyFrames.at(index); + nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); + break; + } + } + + float progress; + + if (nextFrame.Index == 0) { + nextFrame = currentFrame; + progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); + } else { + progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + + } + + if (progress > 1.0f || progress < 0.0f) { + progress = glm::clamp(progress, 0.0f, 1.0f); + } + Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; + Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; + + jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; + jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); + jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + + // Flag for no root motion + if (bone == RootBone && noRootMotion) { + jointTransform.PositionInterp.x = 0; + jointTransform.PositionInterp.z = 0; + } + + JointTransforms.push_back(jointTransform); + + } else { // 1 keyframes for the current bone + currentFrame = boneKeyFrames.at(0); + jointTransform.PositionInterp = currentFrame.BoneProperties.Position; + jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation; + jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale; + JointTransforms.push_back(jointTransform); + + } + } else { // 0 keyframes for the current bone + + } + + } + + if (JointTransforms.size() <= 0) { + if (bone->Parent) { + boneMatrix = parentMatrix * glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix; + m_BoneLocalTransforms[bone->ID] = boneMatrix * bone->OffsetMatrix; + m_BoneTransforms[bone->ID] = boneMatrix; + } else { + boneMatrix = glm::inverse(bone->OffsetMatrix); + m_BoneLocalTransforms[bone->ID] = parentMatrix; + m_BoneTransforms[bone->ID] = boneMatrix; + } + } else if (JointTransforms.size() == 1) { + boneMatrix = parentMatrix *(glm::translate(JointTransforms.at(0).PositionInterp) * glm::toMat4(JointTransforms.at(0).RotationInterp) * glm::scale(JointTransforms.at(0).ScaleInterp)); + m_BoneLocalTransforms[bone->ID] = boneMatrix * bone->OffsetMatrix; + m_BoneTransforms[bone->ID] = boneMatrix; + } else { + + glm::vec3 finalPosInterp; + glm::quat finalRotInterp; + glm::vec3 finalScaleInterp; + float totalWeight = 0; + + for (JointFrameTransform jointTransform : JointTransforms) { + totalWeight += jointTransform.Weight; + } + + + for (JointFrameTransform jointTransform : JointTransforms) { + if (jointTransform.Weight == 1.0f) { + finalPosInterp = jointTransform.PositionInterp; + finalRotInterp = jointTransform.RotationInterp; + finalScaleInterp = jointTransform.ScaleInterp; + break; + } else { + finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight); + finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight)); + finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight); + } + + } + + boneMatrix = parentMatrix *(glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)); + + m_BoneLocalTransforms[bone->ID] = boneMatrix * bone->OffsetMatrix; + m_BoneTransforms[bone->ID] = boneMatrix; + } + + + + for (auto &child : bone->Children) { + AccumulateBoneTransforms(noRootMotion, animations, child, boneMatrix); + } +} + +glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset) +{ + const Animation* animation = animationOffset.animation; + float time = animationOffset.time; + + glm::vec3 position = glm::vec3(0); + glm::quat rotation = glm::quat(); + glm::vec3 scale = glm::vec3(1); + + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); + + Animation::Keyframe currentFrame; + Animation::Keyframe nextFrame; + + if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone + for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame + if (time >= boneKeyFrames.at(index).Time) { + currentFrame = boneKeyFrames.at(index); + nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); + break; + } + } + + float progress; + + if (nextFrame.Index == 0) { + nextFrame = currentFrame; + progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); + } else { + progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + + } + + if (progress > 1.0f || progress < 0.0f) { + progress = glm::clamp(progress, 0.0f, 1.0f); + } + Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; + Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; + + position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; + rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); + scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + + + } else { // 1 keyframes for the current bone + currentFrame = boneKeyFrames.at(0); + position = currentFrame.BoneProperties.Position; + rotation = currentFrame.BoneProperties.Rotation; + scale = currentFrame.BoneProperties.Scale; + } + } + + return (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale)); +} + + +glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix) +{ + glm::mat4 boneMatrix; + + Animation::Keyframe currentFrame; + Animation::Keyframe nextFrame; + + if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) { + std::vector boneKeyFrames = animation->JointAnimations.at(bone->ID); + + if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone + for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame + if (time >= boneKeyFrames.at(index).Time) { + currentFrame = boneKeyFrames.at(index); + nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size()); + break; + } + } + + float progress; + + if (nextFrame.Index == 0) { + nextFrame = currentFrame; + progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time); + } else { + progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time); + } + + if (progress > 1.0f || progress < 0.0f) { + LOG_INFO("Progress %f", progress); + progress = glm::clamp(progress, 0.0f, 1.0f); + } + Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties; + Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties; + + glm::vec3 positionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress; + glm::quat rotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress); + glm::vec3 scaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress; + + boneMatrix = (glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)) * childMatrix; + + } else { // 1 keyframes for the current bone + currentFrame = boneKeyFrames.at(0); + boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)) * childMatrix; + + } + } else { // 0 keyframes for the current bone + if (bone->Parent) { + boneMatrix = bone->Parent->OffsetMatrix * glm::inverse(bone->OffsetMatrix) * childMatrix; + } else { + boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix; + } + } + + if (bone->Parent) { + return GetBoneTransform(bone->Parent, animation, time, boneMatrix); + } else { + return boneMatrix; + } } int Skeleton::GetBoneID(std::string name) @@ -134,11 +469,13 @@ void Skeleton::PrintSkeleton(const Bone* bone, int depthCount) int Skeleton::GetKeyframe(const Animation& animation, double time) { + +/* if (time < 0) { time = 0; } if (time >= animation.Duration) { - return animation.Keyframes.size() - 1; + return animation..size() - 1; } for (int keyframe = 0; keyframe < animation.Keyframes.size(); ++keyframe) { @@ -146,6 +483,8 @@ int Skeleton::GetKeyframe(const Animation& animation, double time) return (keyframe - 1) % animation.Keyframes.size(); } } +*/ + return 0; } diff --git a/src/Engine/Rendering/TextPass.cpp b/src/Engine/Rendering/TextPass.cpp index 1e3d5941..9583fcfd 100644 --- a/src/Engine/Rendering/TextPass.cpp +++ b/src/Engine/Rendering/TextPass.cpp @@ -35,7 +35,7 @@ void TextPass::Draw(RenderScene& scene, FrameBuffer& frameBuffer) { GLERROR("Derp1"); TextPassState* state = new TextPassState(frameBuffer.GetHandle()); - for (auto &job : scene.TextJobs) { + for (auto &job : scene.Jobs.Text) { auto textJob = std::dynamic_pointer_cast(job); if (textJob) { diff --git a/src/Engine/Rendering/Texture.cpp b/src/Engine/Rendering/Texture.cpp index 492b35be..256246a9 100644 --- a/src/Engine/Rendering/Texture.cpp +++ b/src/Engine/Rendering/Texture.cpp @@ -2,24 +2,25 @@ Texture::Texture(std::string path) { + PNG* img = ResourceManager::Load(path); //TODO: Make this threaded. Catch exeptions in all other load places. - PNG image(path); + //PNG image(path); - if (image.Width == 0 && image.Height == 0 || image.Format == Image::ImageFormat::Unknown) { - //image = PNG("Textures/Core/ErrorTexture.png"); - return; // Temporary fix to remove crash - /* - if (image.Width == 0 && image.Height == 0 || image.Format == Image::ImageFormat::Unknown) { - LOG_ERROR("Couldn't even load the error texture. This is a dark day indeed."); - return; - }*/ - } + //if (img->Width == 0 && img->Height == 0 || img->Format == Image::ImageFormat::Unknown) { + // //image = PNG("Textures/Core/ErrorTexture.png"); + // //return; // Temporary fix to remove crash - this->Width = image.Width; - this->Height = image.Height; + // if (img->Width == 0 && img->Height == 0 || img->Format == Image::ImageFormat::Unknown) { + // LOG_ERROR("Couldn't even load the error texture. This is a dark day indeed."); + // return; + // } + //} + + this->Width = img->Width; + this->Height = img->Height; GLint format; - switch (image.Format) { + switch (img->Format) { case Image::ImageFormat::RGB: format = GL_RGB; break; @@ -32,10 +33,11 @@ Texture::Texture(std::string path) glGenTextures(1, &m_Texture); glBindTexture(GL_TEXTURE_2D, m_Texture); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, format, image.Width, image.Height, 0, format, GL_UNSIGNED_BYTE, image.Data); + glTexImage2D(GL_TEXTURE_2D, 0, format, img->Width, img->Height, 0, format, GL_UNSIGNED_BYTE, img->Data); + glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); GLERROR("Texture load"); } diff --git a/src/Engine/Rendering/Util/CommonFunctions.cpp b/src/Engine/Rendering/Util/CommonFunctions.cpp index 3c81de66..382cb790 100644 --- a/src/Engine/Rendering/Util/CommonFunctions.cpp +++ b/src/Engine/Rendering/Util/CommonFunctions.cpp @@ -1,2 +1,19 @@ #include "Rendering/Util/CommonFunctions.h" +Texture* CommonFunctions::LoadTexture(std::string path, bool threaded) +{ + Texture* img; + try { + if(threaded) { + img = ResourceManager::Load(path); + } else { + img = ResourceManager::Load(path); + } + } catch (const Resource::StillLoadingException&) { + img = ResourceManager::Load("Textures/Core/ErrorTexture.png"); + } catch (const std::exception&) { + img = nullptr; + } + + return img; +} diff --git a/src/Engine/Sound/SoundManager.cpp b/src/Engine/Sound/SoundManager.cpp new file mode 100644 index 00000000..8e103d5c --- /dev/null +++ b/src/Engine/Sound/SoundManager.cpp @@ -0,0 +1,374 @@ +#include "Sound/SoundManager.h" + +SoundManager::SoundManager(World* world, EventBroker* eventBroker) +{ + ConfigFile* config = ResourceManager::Load("Config.ini"); + m_EventBroker = eventBroker; + m_World = world; + m_BGMVolumeChannel = config->Get("Sound.BGMVolume", 1.f); + m_SFXVolumeChannel = config->Get("Sound.SFXVolume", 1.f); + + initOpenAL(); + alSpeedOfSound(340.29f); + alDistanceModel(AL_LINEAR_DISTANCE); + alDopplerFactor(1); + + EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnEntity, &SoundManager::OnPlaySoundOnEntity); + EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnPosition, &SoundManager::OnPlaySoundOnPosition); + EVENT_SUBSCRIBE_MEMBER(m_EPlayBackgroundMusic, &SoundManager::OnPlayBackgroundMusic); + EVENT_SUBSCRIBE_MEMBER(m_EStopSound, &SoundManager::OnStopSound); + EVENT_SUBSCRIBE_MEMBER(m_EPauseSound, &SoundManager::OnPauseSound); + EVENT_SUBSCRIBE_MEMBER(m_EContinueSound, &SoundManager::OnContinueSound); + EVENT_SUBSCRIBE_MEMBER(m_ESetBGMGain, &SoundManager::OnSetBGMGain); + EVENT_SUBSCRIBE_MEMBER(m_ESetSFXGain, &SoundManager::OnSetSFXGain); + EVENT_SUBSCRIBE_MEMBER(m_EPause, &SoundManager::OnPause); + EVENT_SUBSCRIBE_MEMBER(m_EResume, &SoundManager::OnResume); + EVENT_SUBSCRIBE_MEMBER(m_EComponentAttached, &SoundManager::OnComponentAttached); + EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &SoundManager::OnPlayerSpawned); + EVENT_SUBSCRIBE_MEMBER(m_EPlayQueueOnEntity, &SoundManager::OnPlayQueueOnEntity); +} + +SoundManager::~SoundManager() +{ + stopEmitters(); // Stopps emitters + deleteInactiveEmitters(); // Deletes stopped emitters + // Delete entities + std::unordered_map::iterator it; + for (it = m_Sources.begin(); it != m_Sources.end(); it++) { + m_World->DeleteEntity((*it).first); + } + m_Sources.clear(); + + alcDestroyContext(m_ALCcontext); + alcCloseDevice(m_ALCdevice); +} + +void SoundManager::stopEmitters() +{ + std::unordered_map::iterator it; + for (it = m_Sources.begin(); it != m_Sources.end(); it++) { + if (getSourceState(it->second->ALsource) == AL_PLAYING) { + stopSound(it->second); + } + } +} + +void SoundManager::Update(double dt) +{ + m_EventBroker->Process(); + deleteInactiveEmitters(); // can be optimized with "EEntityDeleted" + updateEmitters(dt); + updateListener(dt); + + // Editor debug info + ImGui::SliderFloat("BGM", &m_BGMVolumeChannel, 0.0f, 1.0f, "%.3f", 1.0f); + ImGui::SliderFloat("SFX", &m_SFXVolumeChannel, 0.0f, 1.0f, "%.3f", 1.0f); +} + +void SoundManager::deleteInactiveEmitters() +{ + std::unordered_map::iterator it; + for (it = m_Sources.begin(); it != m_Sources.end();) { + if (m_World->ValidEntity(it->first) + && m_World->HasComponent(it->first, "SoundEmitter")) { + if (getSourceState(it->second->ALsource) != AL_STOPPED) { + // Nothing to see here, move along + it++; + continue; + } else { + // Sound has been stopped / finished playing. + alDeleteBuffers(1, &it->second->ALsource); + alDeleteSources(1, &it->second->ALsource); + m_World->DeleteEntity(it->first); + delete it->second; + it = m_Sources.erase(it); + } + } else { + // Entity / Component has been removed + stopSound(it->second); + alDeleteBuffers(1, &it->second->ALsource); + alDeleteSources(1, &it->second->ALsource); + delete it->second; + it = m_Sources.erase(it); + } + } +} + +void SoundManager::updateEmitters(double dt) +{ + std::unordered_map::iterator it; + for (it = m_Sources.begin(); it != m_Sources.end(); it++) { + // Get previous pos + if (!m_World->ValidEntity(it->first)) { + return; + } + if (!m_World->HasComponent(it->first, "SoundEmitter")) + return; + + glm::vec3 previousPos; + alGetSource3f(it->second->ALsource, AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); + // Get next pos + if (!m_World->HasComponent(it->first, "Transform")) + return; + if (!m_World->ValidEntity(m_World->GetParent(it->first))) { + return; + } + glm::vec3 nextPos = Transform::AbsolutePosition(m_World, it->first); + // Calculate velocity + glm::vec3 velocity = glm::vec3(nextPos - previousPos) / (float)dt; + setSourcePos(it->second->ALsource, nextPos); + setSourceVel(it->second->ALsource, velocity); + + auto emitter = m_World->GetComponent(it->first, "SoundEmitter"); + setSoundProperties(it->second, &emitter); + + // Path changed + if (it->second->SoundResource->Path() != (std::string)emitter["FilePath"]) { + it->second->SoundResource = ResourceManager::Load((std::string)emitter["FilePath"]); + if (it->second->SoundResource->Buffer() != 0) { + playSound(it->second); + } + } + } +} + +void SoundManager::updateListener(double dt) +{ + // Should only be one listener. + auto listenerComponents = m_World->GetComponents("Listener"); + if (listenerComponents == nullptr || !m_LocalPlayer.Valid()) { + return; + } + for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { + EntityWrapper listener(m_World, (*it).EntityID); + if (!listener.Valid()) { + break; + } + if (listener.IsChildOf(m_LocalPlayer) || listener == m_LocalPlayer) { + glm::vec3 previousPos; + alGetListener3f(AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); // Get previous pos + glm::vec3 nextPos = Transform::AbsolutePosition(listener); // Get next (current) pos + glm::vec3 velocity = glm::vec3(nextPos - previousPos) / (float)dt; // Calculate velocity + setListenerPos(nextPos); + setListenerVel(velocity); + setListenerOri(glm::eulerAngles(Transform::AbsoluteOrientation(listener))); + break; + } + } +} + +Source* SoundManager::createSource(std::string filePath) +{ + ALuint alSource; + alGenSources((ALuint)1, &alSource); + alSourcef(alSource, AL_REFERENCE_DISTANCE, 1.0); + alSourcef(alSource, AL_MAX_DISTANCE, FLT_MAX); + Source* source = new Source(); + source->ALsource = alSource; + source->SoundResource = ResourceManager::Load(filePath); + return source; +} + +void SoundManager::playSound(Source* source) +{ + alSourcei(source->ALsource, AL_BUFFER, source->SoundResource->Buffer()); + alSourcePlay(source->ALsource); +} + +void SoundManager::playQueue(QueuedBuffers qb) +{ + for (int i = 0; i < qb.second.size(); i++) { + alSourceQueueBuffers(qb.first, 1, &qb.second[i]); + } + alSourcePlay(qb.first); +} + +void SoundManager::stopSound(Source* source) +{ + alSourceStop(source->ALsource); +} + +bool SoundManager::OnPlaySoundOnEntity(const Events::PlaySoundOnEntity & e) +{ + Source* source = createSource(e.FilePath); + source->Type = SoundType::SFX; + EntityID child = m_World->CreateEntity(e.EmitterID); + m_World->AttachComponent(child, "Transform"); + m_World->AttachComponent(child, "SoundEmitter"); + m_Sources[child] = source; + playSound(source); + return false; +} + +bool SoundManager::OnPlaySoundOnPosition(const Events::PlaySoundOnPosition & e) +{ + Source* source = createSource(e.FilePath); + auto emitterID = m_World->CreateEntity(); + auto transform = m_World->AttachComponent(emitterID, "Transform"); + (glm::vec3&)transform["Position"] = e.Position; + auto emitter = m_World->AttachComponent(emitterID, "SoundEmitter"); + (float&)(double)emitter["Gain"] = e.Gain; + (float&)(double)emitter["Pitch"] = e.Pitch; + (bool&)emitter["Loop"] = e.Loop; + (float&)(double)emitter["MaxDistance"] = e.MaxDistance; + (float&)(double)emitter["RollOffFactor"] = e.RollOffFactor; + (float&)(double)emitter["ReferenceDistance"] = e.ReferenceDistance; + source->Type = SoundType::SFX; + m_Sources[emitterID] = source; + playSound(source); + return true; +} + +bool SoundManager::OnPauseSound(const Events::PauseSound & e) +{ + alSourcePause(m_Sources[e.EmitterID]->ALsource); + return true; +} + +bool SoundManager::OnStopSound(const Events::StopSound & e) +{ + alSourceStop(m_Sources[e.EmitterID]->ALsource); + return true; +} + +bool SoundManager::OnContinueSound(const Events::ContinueSound & e) +{ + alSourcePlay(m_Sources[e.EmitterID]->ALsource); + return true; +} + +bool SoundManager::OnPlayBackgroundMusic(const Events::PlayBackgroundMusic & e) +{ + auto listenerComponents = m_World->GetComponents("Listener"); + for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { + if ((*it).EntityID != m_LocalPlayer.ID) { + break; + } + auto emitterChild = m_World->CreateEntity((*it).EntityID); + auto emitter = m_World->AttachComponent(emitterChild, "SoundEmitter"); + (bool&)emitter["Loop"] = true; + (std::string&)emitter["FilePath"] = e.FilePath; + m_World->AttachComponent(emitterChild, "Transform"); + Source* source = createSource(e.FilePath); + source->Type = SoundType::BGM; + setSoundProperties(source, &emitter); + m_Sources[emitterChild] = source; + playSound(source); + } + return true; +} + +bool SoundManager::OnSetBGMGain(const Events::SetBGMGain & e) +{ + m_BGMVolumeChannel = e.Gain; + return true; +} + +bool SoundManager::OnSetSFXGain(const Events::SetSFXGain & e) +{ + m_SFXVolumeChannel = e.Gain; + return true; +} + +bool SoundManager::OnComponentAttached(const Events::ComponentAttached & e) +{ + if (e.Component.Info.Name == "SoundEmitter") { + auto component = m_World->GetComponent(e.Entity.ID, "SoundEmitter"); + Source* source = createSource(component["FilePath"]); + m_Sources[e.Entity.ID] = source; + } + return false; +} + +bool SoundManager::OnPause(const Events::Pause & e) +{ + for (auto it = m_Sources.begin(); it != m_Sources.end(); it++) { + alSourcePause(it->second->ALsource); + } + return false; +} + +bool SoundManager::OnResume(const Events::Resume &e) +{ + for (auto it = m_Sources.begin(); it != m_Sources.end(); it++) { + alSourcePlay(it->second->ALsource); + } + return false; +} + + +bool SoundManager::OnPlayerSpawned(const Events::PlayerSpawned &e) +{ + if (e.PlayerID == -1) { // Local player + m_LocalPlayer = e.Player; + return true; + } + return false; +} + + +bool SoundManager::OnPlayQueueOnEntity(const Events::PlayQueueOnEntity &e) +{ + Source* source = createSource(*e.FilePaths.begin()); + std::vector buffers; + buffers.push_back(source->SoundResource->Buffer()); + source->Type = SoundType::BGM; + std::vector::const_iterator it; + for (it = e.FilePaths.begin() + 1; it != e.FilePaths.end(); it++) { + buffers.push_back(ResourceManager::Load(*it)->Buffer()); + } + playQueue(QueuedBuffers(source->ALsource, buffers)); + return true; +} + +ALenum SoundManager::getSourceState(ALuint source) +{ + ALenum state; + alGetSourcei(source, AL_SOURCE_STATE, &state); + return state; +} + +void SoundManager::setGain(Source * source, float gain) +{ + alSourcef(source->ALsource, AL_GAIN, gain); +} + +void SoundManager::setSoundProperties(Source* source, ComponentWrapper* soundComponent) +{ + float gain = (source->Type == SoundType::SFX) ? m_SFXVolumeChannel : m_BGMVolumeChannel; + alSourcef(source->ALsource, AL_GAIN, (float)(double)(*soundComponent)["Gain"] * gain); + alSourcef(source->ALsource, AL_PITCH, (float)(double)(*soundComponent)["Pitch"]); + alSourcei(source->ALsource, AL_LOOPING, (int)(bool)(*soundComponent)["Loop"]); // YOLO + alSourcef(source->ALsource, AL_MAX_DISTANCE, (float)(double)(*soundComponent)["MaxDistance"]); + alSourcef(source->ALsource, AL_ROLLOFF_FACTOR, (float)(double)(*soundComponent)["RollOffFactor"]); + alSourcef(source->ALsource, AL_REFERENCE_DISTANCE, (float)(double)(*soundComponent)["ReferenceDistance"]); +} + +void SoundManager::initOpenAL() +{ + // Initialize OpenAL + m_ALCdevice = alcOpenDevice(nullptr); + if (m_ALCdevice != nullptr) { + m_ALCcontext = alcCreateContext(m_ALCdevice, nullptr); + alcMakeContextCurrent(m_ALCcontext); + } else { + LOG_ERROR("OpenAL failed to initialize."); + } +} + +void SoundManager::setListenerOri(glm::vec3 ori) +{ + // Calculate forward and up vector. + glm::vec3 forward = glm::vec3(0.0, 0.0, -1.0); + forward = glm::rotateX(forward, ori.x); + forward = glm::rotateY(forward, ori.y); + forward = glm::rotateZ(forward, ori.z); + glm::normalize(forward); + glm::vec3 up = glm::vec3(0.0, 1.0, 0.0); + up = glm::rotateX(up, ori.x); + up = glm::rotateY(up, ori.y); + up = glm::rotateZ(up, ori.z); + glm::normalize(up); + ALfloat lOri[6] = { forward.x, forward.y, forward.z, up.x, up.y, up.z }; + alListenerfv(AL_ORIENTATION, lOri); +} \ No newline at end of file diff --git a/src/Engine/Sound/SoundSystem.cpp b/src/Engine/Sound/SoundSystem.cpp deleted file mode 100644 index cd83d9c6..00000000 --- a/src/Engine/Sound/SoundSystem.cpp +++ /dev/null @@ -1,308 +0,0 @@ -#include "Sound/SoundSystem.h" - -SoundSystem::SoundSystem(World* world, EventBroker* eventBroker, bool editorMode) -{ - m_EventBroker = eventBroker; - m_World = world; - m_EditorEnabled = editorMode; - - initOpenAL(); - - alSpeedOfSound(340.29f); - alDistanceModel(AL_LINEAR_DISTANCE); - alDopplerFactor(1); - - EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnEntity, &SoundSystem::OnPlaySoundOnEntity); - EVENT_SUBSCRIBE_MEMBER(m_EPlaySoundOnPosition, &SoundSystem::OnPlaySoundOnPosition); - EVENT_SUBSCRIBE_MEMBER(m_EPlayBackgroundMusic, &SoundSystem::OnPlayBackgroundMusic); - EVENT_SUBSCRIBE_MEMBER(m_EStopSound, &SoundSystem::OnStopSound); - EVENT_SUBSCRIBE_MEMBER(m_EPauseSound, &SoundSystem::OnPauseSound); - EVENT_SUBSCRIBE_MEMBER(m_EContinueSound, &SoundSystem::OnContinueSound); - EVENT_SUBSCRIBE_MEMBER(m_ESetBGMGain, &SoundSystem::OnSetBGMGain); - EVENT_SUBSCRIBE_MEMBER(m_ESetSFXGain, &SoundSystem::OnSetSFXGain); -} - -SoundSystem::~SoundSystem() -{ - stopEmitters(); // Stopps emitters - deleteInactiveEmitters(); // Deletes stopped emitters - // Delete entities - std::unordered_map::iterator it; - for (it = m_Sources.begin(); it != m_Sources.end(); it++) { - m_World->DeleteEntity((*it).first); - } - m_Sources.clear(); - - alcDestroyContext(m_ALCcontext); - alcCloseDevice(m_ALCdevice); -} - -void SoundSystem::stopEmitters() -{ - std::unordered_map::iterator it; - for (it = m_Sources.begin(); it != m_Sources.end(); it++) { - if (getSourceState(it->second->ALsource) == AL_PLAYING) { - stopSound(it->second); - } - } -} - -void SoundSystem::Update(double dt) -{ - m_EventBroker->Process(); - addNewEmitters(dt); // can be optimized with "EEntityCreated" - deleteInactiveEmitters(); // can be optimized with "EEntityDeleted" - updateEmitters( dt); - updateListener( dt); -} - -void SoundSystem::deleteInactiveEmitters() -{ - std::unordered_map::iterator it; - for (it = m_Sources.begin(); it != m_Sources.end();) { - if (m_World->ValidEntity(it->first) - && m_World->HasComponent(it->first, "SoundEmitter")) { - if (getSourceState(it->second->ALsource) != AL_STOPPED) { - // Nothing to see here, move along - it++; - continue; - } else { - // Sound has been stopped / finished playing. - alDeleteBuffers(1, &it->second->ALsource); - alDeleteSources(1, &it->second->ALsource); - m_World->DeleteEntity(it->first); - delete it->second; - it = m_Sources.erase(it); - } - } else { - // Entity / Component has been removed - stopSound((*it).second); - alDeleteBuffers(1, &it->second->ALsource); - alDeleteSources(1, &it->second->ALsource); - delete it->second; - it = m_Sources.erase(it); - } - } -} - -void SoundSystem::addNewEmitters(double dt) -{ - auto emitterComponents = m_World->GetComponents("SoundEmitter"); - if (emitterComponents == nullptr) { - return; - } - for (auto it = emitterComponents->begin(); it != emitterComponents->end(); it++) { - EntityID emitter = (*it).EntityID; - std::unordered_map::iterator source; - source = m_Sources.find(emitter); - if (source == m_Sources.end()) { // Did not exist, add it - Source* source = createSource((std::string)(*it)["FilePath"]); - m_Sources[emitter] = source; - } - } -} - -void SoundSystem::updateEmitters(double dt) -{ - std::unordered_map::iterator it; - for (it = m_Sources.begin(); it != m_Sources.end(); it++) { - // Get previous pos - glm::vec3 previousPos; - alGetSource3f(it->second->ALsource, AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); - // Get next pos - glm::vec3 nextPos = Transform::AbsolutePosition(m_World, it->first); - // Calculate velocity - glm::vec3 velocity = glm::vec3(nextPos - previousPos) / (float)dt; - setSourcePos(it->second->ALsource, nextPos); - setSourceVel(it->second->ALsource, velocity); - float gain; - 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); - - // To make an emitter play when spawned in editor mode - if (m_EditorEnabled) { - // Path changed - if (it->second->SoundResource->Path() != (std::string)emitter["FilePath"]) { - it->second->SoundResource = ResourceManager::Load((std::string)emitter["FilePath"]); - if (it->second->SoundResource->Buffer() != 0) { - playSound(it->second); - } - } - } - } -} - -void SoundSystem::updateListener(double dt) -{ - // Should only be one listener. - auto listenerComponents = m_World->GetComponents("Listener"); - if (listenerComponents == nullptr) { - return; - } - for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { - EntityID listener = (*it).EntityID; - glm::vec3 previousPos; - alGetListener3f(AL_POSITION, &previousPos.x, &previousPos.y, &previousPos.z); // Get previous pos - glm::vec3 nextPos = Transform::AbsolutePosition(m_World, listener); // Get next (current) pos - glm::vec3 velocity = glm::vec3(nextPos - previousPos) / (float)dt; // Calculate velocity - setListenerPos(nextPos); - setListenerVel(velocity); - setListenerOri(glm::eulerAngles(Transform::AbsoluteOrientation(m_World, listener))); - } -} - -Source* SoundSystem::createSource(std::string filePath) -{ - ALuint alSource; - alGenSources((ALuint)1, &alSource); - alSourcef(alSource, AL_REFERENCE_DISTANCE, 1.0); - alSourcef(alSource, AL_MAX_DISTANCE, FLT_MAX); - Source* source = new Source(); - source->ALsource = alSource; - source->SoundResource = ResourceManager::Load(filePath); - return source; -} - -void SoundSystem::playSound(Source* source) -{ - alSourcei(source->ALsource, AL_BUFFER, source->SoundResource->Buffer()); - alSourcePlay(source->ALsource); -} - -void SoundSystem::stopSound(Source* source) -{ - alSourceStop(source->ALsource); -} - -bool SoundSystem::OnPlaySoundOnEntity(const Events::PlaySoundOnEntity & e) -{ - Source* source = createSource(e.FilePath); - source->Type = SoundType::SFX; - m_Sources[e.EmitterID] = source; - playSound(source); - return false; -} - -bool SoundSystem::OnPlaySoundOnPosition(const Events::PlaySoundOnPosition & e) -{ - Source* source = createSource(e.FilePath); - auto emitterID = m_World->CreateEntity(); - auto transform = m_World->AttachComponent(emitterID, "Transform"); - (glm::vec3&)transform["Position"] = e.Position; - auto emitter = m_World->AttachComponent(emitterID, "SoundEmitter"); - (float&)(double)emitter["Gain"] = e.Gain; - (float&)(double)emitter["Pitch"] = e.Pitch; - (bool&)emitter["Loop"] = e.Loop; - (float&)(double)emitter["MaxDistance"] = e.MaxDistance; - (float&)(double)emitter["RollOffFactor"] = e.RollOffFactor; - (float&)(double)emitter["ReferenceDistance"] = e.ReferenceDistance; - auto model = m_World->AttachComponent(emitterID, "Model"); - (std::string&)model["Resource"] = "Models/Core/UnitCube.mesh"; // 360NoScope UnitCube - source->Type = SoundType::SFX; - m_Sources[emitterID] = source; - playSound(source); - return true; -} - -bool SoundSystem::OnPauseSound(const Events::PauseSound & e) -{ - alSourcePause(m_Sources[e.EmitterID]->ALsource); - return true; -} - -bool SoundSystem::OnStopSound(const Events::StopSound & e) -{ - alSourceStop(m_Sources[e.EmitterID]->ALsource); - return true; -} - -bool SoundSystem::OnContinueSound(const Events::ContinueSound & e) -{ - alSourcePlay(m_Sources[e.EmitterID]->ALsource); - return true; -} - -bool SoundSystem::OnPlayBackgroundMusic(const Events::PlayBackgroundMusic & e) -{ - auto listenerComponents = m_World->GetComponents("Listener"); - for (auto it = listenerComponents->begin(); it != listenerComponents->end(); it++) { - auto emitterChild = m_World->CreateEntity((*it).EntityID); - auto emitter = m_World->AttachComponent(emitterChild, "SoundEmitter"); - (bool&)emitter["Loop"] = true; - (std::string&)emitter["FilePath"] = e.FilePath; - m_World->AttachComponent(emitterChild, "Transform"); - Source* source = createSource(e.FilePath); - source->Type = SoundType::BGM; - m_Sources[emitterChild] = source; - playSound(source); - } - return true; -} - -bool SoundSystem::OnSetBGMGain(const Events::SetBGMGain & e) -{ - m_BGMVolumeChannel = e.Gain; - return true; -} - -bool SoundSystem::OnSetSFXGain(const Events::SetSFXGain & e) -{ - m_SFXVolumeChannel = e.Gain; - return true; -} - -void SoundSystem::setListenerOri(glm::vec3 ori) -{ - // Calculate forward and up vector. - glm::vec3 forward = glm::vec3(0.0, 0.0, -1.0); - forward = glm::rotateX(forward, ori.x); - forward = glm::rotateY(forward, ori.y); - forward = glm::rotateZ(forward, ori.z); - glm::normalize(forward); - glm::vec3 up = glm::vec3(0.0, 1.0, 0.0); - up = glm::rotateX(up, ori.x); - up = glm::rotateY(up, ori.y); - up = glm::rotateZ(up, ori.z); - glm::normalize(up); - ALfloat lOri[6] = { forward.x, forward.y, forward.z, up.x, up.y, up.z }; - alListenerfv(AL_ORIENTATION, lOri); -} - -ALenum SoundSystem::getSourceState(ALuint source) -{ - ALenum state; - alGetSourcei(source, AL_SOURCE_STATE, &state); - return state; -} - -void SoundSystem::setGain(Source * source, float gain) -{ - alSourcef(source->ALsource, AL_GAIN, gain); -} - -void SoundSystem::setSoundProperties(ALuint source, ComponentWrapper* soundComponent) -{ - alSourcef(source, AL_GAIN, (float)(double)(*soundComponent)["Gain"]); - alSourcef(source, AL_PITCH, (float)(double)(*soundComponent)["Pitch"]); - alSourcei(source, AL_LOOPING, (int)(bool)(*soundComponent)["Loop"]); // YOLO - alSourcef(source, AL_MAX_DISTANCE, (float)(double)(*soundComponent)["MaxDistance"]); - alSourcef(source, AL_ROLLOFF_FACTOR, (float)(double)(*soundComponent)["RollOffFactor"]); - alSourcef(source, AL_REFERENCE_DISTANCE, (float)(double)(*soundComponent)["ReferenceDistance"]); -} - -void SoundSystem::initOpenAL() -{ - // Initialize OpenAL - m_ALCdevice = alcOpenDevice(nullptr); - if (m_ALCdevice != nullptr) { - m_ALCcontext = alcCreateContext(m_ALCdevice, nullptr); - alcMakeContextCurrent(m_ALCcontext); - } else { - LOG_ERROR("OpenAL failed to initialize."); - } -} \ No newline at end of file diff --git a/src/Game/CMakeLists.txt b/src/Game/CMakeLists.txt index 157af23c..db923364 100644 --- a/src/Game/CMakeLists.txt +++ b/src/Game/CMakeLists.txt @@ -1,6 +1,6 @@ project(TacticalZ-Game) -find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono) +find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono program_options) set(INCLUDE_PATH ${CMAKE_SOURCE_DIR}/include/Game) include_directories( @@ -22,13 +22,17 @@ file(GLOB SOURCE_FILES_Events ) source_group(Events FILES ${SOURCE_FILES_Events}) +file(GLOB SOURCE_FILES_Network + "${INCLUDE_PATH}/Network/*.h" + "Network/*.cpp" +) +source_group(Network FILES ${SOURCE_FILES_Network}) set(SOURCE_FILES ${SOURCE_FILES} "Game.cpp" ${SOURCE_FILES_Systems} ${SOURCE_FILES_Events} - - + ${SOURCE_FILES_Network} ) set(LIBRARIES diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 5875bc81..8ee6dbed 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -1,5 +1,6 @@ #include "Game.h" -#include "Collision/CollidableOctreeSystem.h" +#include "Collision/FillOctreeSystem.h" +#include "Collision/FillFrustumOctreeSystem.h" #include "Collision/EntityAABB.h" #include "Collision/TriggerSystem.h" #include "Collision/CollisionSystem.h" @@ -11,21 +12,28 @@ #include "Systems/PlayerDeathSystem.h" #include "Core/EntityFileWriter.h" #include "Game/Systems/CapturePointSystem.h" +#include "Game/Systems/CapturePointHUDSystem.h" #include "Game/Systems/PickupSpawnSystem.h" #include "Game/Systems/DamageIndicatorSystem.h" #include "Game/Systems/WeaponSystem.h" -#include "Game/Systems/PlayerHUD.h" +#include "Rendering/AnimationSystem.h" +#include "Game/Systems/PlayerHUDSystem.h" +#include "Rendering/BoneAttachmentSystem.h" #include "Game/Systems/LifetimeSystem.h" -#include "../Engine/Rendering/AnimationSystem.h" #include "../Engine/Core/UniformScaleSystem.h" +#include "Rendering/AnimationSystem.h" +#include "Network/MultiplayerSnapshotFilter.h" Game::Game(int argc, char* argv[]) { + parseArgs(argc, argv); + ResourceManager::RegisterType("ConfigFile"); ResourceManager::RegisterType("Sound"); ResourceManager::RegisterType("Model"); ResourceManager::RegisterType("RawModel"); ResourceManager::RegisterType("Texture"); + ResourceManager::RegisterType("Png"); ResourceManager::RegisterType("ShaderProgram"); ResourceManager::RegisterType("EntityFile"); ResourceManager::RegisterType("FontFile"); @@ -75,64 +83,82 @@ Game::Game(int argc, char* argv[]) fp.MergeEntities(m_World); } + // Create the sound manager + m_SoundManager = new SoundManager(m_World, m_EventBroker); + + // Initialize network + if (m_Config->Get("Networking.StartNetwork", false)) { + if (m_IsServer) { + m_NetworkServer = new Server(m_World, m_EventBroker, m_NetworkPort); + m_Renderer->SetWindowTitle(m_Renderer->WindowTitle() + " SERVER"); + } else if (m_IsClient) { + m_NetworkClient = new Client(m_World, m_EventBroker, std::make_unique(m_EventBroker)); + m_NetworkClient->Connect(m_NetworkAddress, m_NetworkPort); + m_Renderer->SetWindowTitle(m_Renderer->WindowTitle() + " CLIENT"); + } + } // Create Octrees - 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); + // TODO: Perhaps the world bounds should be set in some non-arbitrary way instead of this. + AABB boxContainingTheWorld(glm::vec3(-300), glm::vec3(300)); + m_OctreeCollision = new Octree(boxContainingTheWorld, 4); + m_OctreeTrigger = new Octree(boxContainingTheWorld, 4); + m_OctreeFrustrumCulling = new Octree(boxContainingTheWorld, 4); // Create system pipeline - m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker); + m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker, m_IsClient, m_IsServer); // All systems with orderlevel 0 will be updated first. unsigned int updateOrderLevel = 0; + m_SystemPipeline->AddSystem(updateOrderLevel); + ++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_SystemPipeline->AddSystem(updateOrderLevel); - m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); + m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_OctreeCollision); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); // Populate Octree with collidables ++updateOrderLevel; - m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision, "Collidable"); - m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeTrigger, "Player"); - m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision, "Collidable"); + m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeTrigger, "Player"); + m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeFrustrumCulling); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); // Collision and TriggerSystem should update after player. ++updateOrderLevel; + m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeTrigger); ++updateOrderLevel; - m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_RenderFrame); + m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_RenderFrame, m_OctreeFrustrumCulling); ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_RenderFrame); - // Invoke network - if (m_Config->Get("Networking.StartNetwork", false)) { - //boost::thread workerThread(&Game::networkFunction, this); - networkFunction(); - } - - // Invoke sound system - m_SoundSystem = new SoundSystem(m_World, m_EventBroker, m_Config->Get("Debug.EditorEnabled", false)); - m_LastTime = glfwGetTime(); } Game::~Game() { delete m_SystemPipeline; - delete m_SoundSystem; delete m_OctreeFrustrumCulling; delete m_OctreeCollision; delete m_OctreeTrigger; + delete m_SoundManager; + if (m_NetworkClient != nullptr) { + delete m_NetworkClient; + } + if (m_NetworkServer != nullptr) { + delete m_NetworkServer; + } delete m_World; delete m_FrameStack; delete m_InputProxy; @@ -160,40 +186,59 @@ void Game::Tick() m_InputProxy->Process(); m_EventBroker->Swap(); + m_SoundManager->Update(dt); + // Update network - if (m_IsClientOrServer) { - m_ClientOrServer->Update(); + m_EventBroker->Process(); + if (m_NetworkClient != nullptr) { + m_NetworkClient->Update(); } + if (m_NetworkServer != nullptr) { + m_NetworkServer->Update(); + } + //m_SoundManager->Update(dt); + // Iterate through systems and update world! m_EventBroker->Process(); m_SystemPipeline->Update(dt); - debugTick(dt); m_Renderer->Update(dt); - m_SoundSystem->Update(dt); - GLERROR("Game::Tick m_RenderQueueFactory->Update"); m_Renderer->Draw(*m_RenderFrame); m_RenderFrame->Clear(); - GLERROR("Game::Tick m_Renderer->Draw"); m_EventBroker->Swap(); m_EventBroker->Clear(); } -void Game::debugTick(double dt) +int Game::parseArgs(int argc, char* argv[]) { - m_EventBroker->Process(); + namespace po = boost::program_options; + + po::options_description desc("Options"); + desc.add_options() + ("help", "Help") + ("server,s", po::bool_switch(&m_IsServer), "Launch game in server mode") + ("connect", po::value(&m_NetworkAddress)->default_value(""), "Connect to this address in client mode") + ("port,p", po::value(&m_NetworkPort), "Port to listen on or connect to"); + ; + + po::variables_map vm; + try { + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + } catch (std::exception& e) { + LOG_ERROR(e.what()); + return 1; + } + + if (vm.count("help")) { + std::cout << desc << std::endl; + exit(1); + } + + // HACK: Right now, client and server are mutually exclusive + m_IsClient = true; + if (m_IsServer) { + m_IsClient = false; + } + + return 0; } - -void Game::networkFunction() -{ - bool isServer = m_Config->Get("Networking.IsServer", false); - if (!isServer) { - m_IsClientOrServer = true; - m_ClientOrServer = new Client(m_Config); - } - if (isServer) { - m_IsClientOrServer = true; - m_ClientOrServer = new Server(); - } - m_ClientOrServer->Start(m_World, m_EventBroker); - -} \ No newline at end of file diff --git a/src/Game/Network/MultiplayerSnapshotFilter.cpp b/src/Game/Network/MultiplayerSnapshotFilter.cpp new file mode 100644 index 00000000..65d40189 --- /dev/null +++ b/src/Game/Network/MultiplayerSnapshotFilter.cpp @@ -0,0 +1,33 @@ +#include "Network/MultiplayerSnapshotFilter.h" + +MultiplayerSnapshotFilter::MultiplayerSnapshotFilter(EventBroker* eventBroker) + : m_EventBroker(eventBroker) +{ + EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &MultiplayerSnapshotFilter::OnPlayerSpawned); +} + +bool MultiplayerSnapshotFilter::FilterComponent(EntityWrapper entity, SharedComponentWrapper& component) +{ + if (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer)) { + return false; + } + + if (component.Info.Name == "Physics") { + return false; + } + + if (component.Info.Name == "Transform" || component.Info.Name == "Physics") { + m_EventBroker->Publish(Events::Interpolate(entity, component)); + return false; + } + + return true; +} + +bool MultiplayerSnapshotFilter::OnPlayerSpawned(Events::PlayerSpawned ePlayerSpawned) +{ + if (ePlayerSpawned.PlayerID == -1) { + m_LocalPlayer = ePlayerSpawned.Player; + } + return true; +} \ No newline at end of file diff --git a/src/Game/Systems/CapturePointHUDSystem.cpp b/src/Game/Systems/CapturePointHUDSystem.cpp new file mode 100644 index 00000000..784c7e16 --- /dev/null +++ b/src/Game/Systems/CapturePointHUDSystem.cpp @@ -0,0 +1,52 @@ +#include "Systems/CapturePointHUDSystem.h" + +CapturePointHUDSystem::CapturePointHUDSystem(SystemParams params) + : System(params) + , ImpureSystem() +{ +} + + +void CapturePointHUDSystem::Update(double dt) +{ + bool LoadCheck = true; + int redTeam; + int blueTeam; + int spectatorTeam; + + auto CapturePointHUDElements = m_World->GetComponents("CapturePointHUD"); + auto CapturePoints = m_World->GetComponents("CapturePoint"); + + for (auto& cCapturePointHUD : *CapturePointHUDElements) { + int HUD_ID = cCapturePointHUD["CapturePointNumber"]; + EntityWrapper entityHUD = EntityWrapper(m_World, cCapturePointHUD.EntityID); + EntityWrapper entityHUDparent = entityHUD.Parent(); + + for (auto& cCapturePoint : *CapturePoints) { + EntityWrapper entityCP = EntityWrapper(m_World, cCapturePoint.EntityID); + + //Check if the HUD corresponds to the Capture Point Number + if (HUD_ID == (int)entityCP["CapturePoint"]["CapturePointNumber"]) { + ComponentWrapper& teamComponent = entityCP["Team"]; + if (LoadCheck) { + redTeam = (int)teamComponent["Team"].Enum("Red"); + blueTeam = (int)teamComponent["Team"].Enum("Blue"); + spectatorTeam = (int)teamComponent["Team"].Enum("Spectator"); + LoadCheck = false; + } + //Color hud with team color + auto capturePointTeam = (int)teamComponent["Team"]; + entityHUDparent["Sprite"]["Color"] = capturePointTeam == blueTeam ? glm::vec4(0, 0.2f, 1, 0.7) : capturePointTeam == redTeam ? glm::vec4(1, 0.2f, 0, 0.7) : glm::vec4(1, 1, 1, 0.3); + + //Progress is scaled with time + double currentCaptureTime = (double)entityCP["CapturePoint"]["CaptureTimer"]; + double progress = glm::abs(currentCaptureTime)/15.0; + int currentCapturingTeam = currentCaptureTime > 0 ? redTeam : currentCaptureTime < 0 ? blueTeam : spectatorTeam; + ((glm::vec3&)entityHUD["Transform"]["Orientation"]).z = currentCapturingTeam == redTeam ? glm::half_pi()+glm::pi() : glm::half_pi(); + glm::vec4 fillColor = currentCapturingTeam == redTeam ? glm::vec4(1, 0.2f, 0, 0.7) : glm::vec4(0, 0.2f, 1, 0.7); + entityHUD["Fill"]["Color"] = fillColor; + entityHUD["Fill"]["Percentage"] = progress; + } + } + } +} \ No newline at end of file diff --git a/src/Game/Systems/CapturePointSystem.cpp b/src/Game/Systems/CapturePointSystem.cpp index d26dde5f..9a108ff9 100644 --- a/src/Game/Systems/CapturePointSystem.cpp +++ b/src/Game/Systems/CapturePointSystem.cpp @@ -1,8 +1,8 @@ #include "Systems/CapturePointSystem.h" #include -CapturePointSystem::CapturePointSystem(World* world, EventBroker* eventBroker) - : System(world, eventBroker) +CapturePointSystem::CapturePointSystem(SystemParams params) + : System(params) , PureSystem("CapturePoint") { //subscribe/listenTo playerdamage,healthpickup events (using the eventBroker) @@ -57,7 +57,7 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp int blueTeamPlayersStandingInside = 0; if (capturePointEntity.HasComponent("Model")) { //Now sets team color to the capturepoint, or white if it is uncaptured. - 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); + capturePointEntity["Model"]["Color"] = ownedBy == blueTeam ? glm::vec4(0, 0.2f, 1, 0.3) : ownedBy == redTeam ? glm::vec4(1, 0.2f, 0, 0.3) : glm::vec4(1, 1, 1, 0.3); } //calculate next possible capturePoint for both teams @@ -106,10 +106,10 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp //colorize next possible capturepoint if (nextPossibleCapturePoint["Red"] == capturePointNumber) { - capturePointEntity["Model"]["Color"] = glm::vec4(1, 1, 0, 1); + capturePointEntity["Model"]["Color"] = glm::vec4(1, 1, 0, 0.3); } if (nextPossibleCapturePoint["Blue"] == capturePointNumber) { - capturePointEntity["Model"]["Color"] = glm::vec4(0, 1, 1, 1); + capturePointEntity["Model"]["Color"] = glm::vec4(0, 1, 1, 0.3); } //check how many players are standing inside and are healthy diff --git a/src/Game/Systems/ExplosionEffectSystem.cpp b/src/Game/Systems/ExplosionEffectSystem.cpp new file mode 100644 index 00000000..2704d2da --- /dev/null +++ b/src/Game/Systems/ExplosionEffectSystem.cpp @@ -0,0 +1,14 @@ +#include "Systems/ExplosionEffectSystem.h" + +void ExplosionEffectSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) +{ + 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; + //} +} + diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index de290aa5..bb02ea13 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -1,7 +1,7 @@ #include "Systems/HealthSystem.h" -HealthSystem::HealthSystem(World* m_World, EventBroker* eventBroker) - : System(m_World, eventBroker) +HealthSystem::HealthSystem(SystemParams params) + : System(params) , PureSystem("Health") { //subscribe/listenTo playerdamage,healthpickup events (using the eventBroker) diff --git a/src/Game/Systems/InterpolationSystem.cpp b/src/Game/Systems/InterpolationSystem.cpp index f2de710d..430c01c1 100644 --- a/src/Game/Systems/InterpolationSystem.cpp +++ b/src/Game/Systems/InterpolationSystem.cpp @@ -1,84 +1,98 @@ #include "Systems/InterpolationSystem.h" -InterpolationSystem::InterpolationSystem(World* world, EventBroker* eventBroker) - : System(world, eventBroker) - , PureSystem("Transform") +InterpolationSystem::InterpolationSystem(SystemParams params) + : System(params) { ConfigFile* config = ResourceManager::Load("Config.ini"); m_SnapshotInterval = config->Get("Networking.SnapshotInterval", 0.05f); EVENT_SUBSCRIBE_MEMBER(m_EInterpolate, &InterpolationSystem::OnInterpolate); - EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &InterpolationSystem::OnPlayerSpawned); } -void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt) +void InterpolationSystem::Update(double dt) { - // Don't interpolate entities that might already have been removed - if (!entity.Valid()) { - return; + // Position + for (auto& kv : m_InterpolatePosition) { + EntityWrapper entity = kv.first; + if (!entity.Valid()) { + continue; + } + auto& iPosition = kv.second; + glm::vec3& position = iPosition.Component[iPosition.Field]; + + iPosition.Alpha += dt; + float alpha = glm::min(iPosition.Alpha / m_SnapshotInterval, 1.0); + position = iPosition.Start + ((iPosition.Goal - iPosition.Start) * alpha); } - if (m_NextTransform.find(transform.EntityID) != m_NextTransform.end()) { // Exists in map - m_NextTransform[transform.EntityID].interpolationTime += static_cast(dt); - Transform sTransform = m_NextTransform[transform.EntityID]; - float time = sTransform.interpolationTime; - if (time > m_SnapshotInterval) { - if (m_LastReceivedTransform.find(transform.EntityID) != m_LastReceivedTransform.end()) { - m_NextTransform[transform.EntityID] = m_LastReceivedTransform[transform.EntityID]; - m_NextTransform[transform.EntityID].interpolationTime = time - m_SnapshotInterval; - sTransform = m_NextTransform[transform.EntityID]; - m_LastReceivedTransform.erase(transform.EntityID); - } else { - m_NextTransform.erase(transform.EntityID); - } + // Orientation + for (auto& kv : m_InterpolateOrientation) { + EntityWrapper entity = kv.first; + if (!entity.Valid()) { + continue; } - if (transform.Info.Name == "Transform") { - bool isLocalPlayer = entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer); - // Position - glm::vec3 nextPosition = sTransform.Position; - glm::vec3 currentPosition = static_cast(transform["Position"]); - // HACK: Don't force position for players - if (!isLocalPlayer) { - (glm::vec3&)transform["Position"] += vectorInterpolation(currentPosition, nextPosition, sTransform.interpolationTime); - } - // Orientation - // Don't force orientation for players - if (!isLocalPlayer) { - glm::quat nextOrientation = sTransform.Orientation; - glm::quat currentOrientation = glm::quat(static_cast(transform["Orientation"])); - (glm::vec3&)transform["Orientation"] = glm::eulerAngles(glm::slerp(currentOrientation, nextOrientation, sTransform.interpolationTime / m_SnapshotInterval)); - } - // Scale - glm::vec3 nextScale = sTransform.Scale; - glm::vec3 currentScale = static_cast(transform["Scale"]); - (glm::vec3&)transform["Scale"] += vectorInterpolation(currentScale, nextScale, sTransform.interpolationTime); + auto& iOrientation = kv.second; + glm::vec3& orientation = iOrientation.Component[iOrientation.Field]; + + iOrientation.Alpha += dt / m_SnapshotInterval; + iOrientation.Alpha = glm::min(iOrientation.Alpha, 1.0); + orientation = glm::eulerAngles(glm::slerp(iOrientation.Start, iOrientation.Goal, (float)iOrientation.Alpha)); + } + + // Velocity + for (auto& kv : m_InterpolateVelocity) { + EntityWrapper entity = kv.first; + if (!entity.Valid()) { + continue; } + auto& iVelocity = kv.second; + glm::vec3& position = iVelocity.Component[iVelocity.Field]; + + iVelocity.Alpha += dt; + float alpha = glm::min(iVelocity.Alpha / m_SnapshotInterval, 1.0); + position = iVelocity.Start + ((iVelocity.Goal - iVelocity.Start) * alpha); } } -bool InterpolationSystem::OnPlayerSpawned(Events::PlayerSpawned& e) +bool InterpolationSystem::OnInterpolate(Events::Interpolate& e) { - m_LocalPlayer = e.Player; + if (e.Component.Info.Name == "Transform") { + auto cTransform = e.Entity["Transform"]; + + // Position + Interpolation iPosition( + cTransform, + "Position", + cTransform["Position"], + e.Component["Position"] + ); + m_InterpolatePosition.erase(e.Entity); + m_InterpolatePosition.insert(std::make_pair(e.Entity, iPosition)); + + // Orientation + Interpolation iOrientation( + cTransform, + "Orientation", + glm::quat((glm::vec3&)cTransform["Orientation"]), + glm::quat((glm::vec3&)e.Component["Orientation"]) + ); + m_InterpolateOrientation.erase(e.Entity); + m_InterpolateOrientation.insert(std::make_pair(e.Entity, iOrientation)); + } else if (e.Component.Info.Name == "Physics") { + auto cPhysics = e.Entity["Physics"]; + if (!e.Entity.HasComponent("Player")) { + return false; + } + + // Velocity + Interpolation iVelocity( + cPhysics, + "Velocity", + cPhysics["Velocity"], + e.Component["Velocity"] + ); + m_InterpolateVelocity.erase(e.Entity); + m_InterpolateVelocity.insert(std::make_pair(e.Entity, iVelocity)); + } + return true; } - -bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e) -{ - Transform transform; - int offset = 0; - // Read the data - memcpy(&transform.Position, e.DataArray.get() + offset, sizeof(glm::vec3)); - offset += sizeof(glm::vec3); - glm::vec3 tempOrientation; - memcpy(&tempOrientation, e.DataArray.get() + offset, sizeof(glm::vec3)); - transform.Orientation = glm::quat(tempOrientation); - offset += sizeof(glm::vec3); - memcpy(&transform.Scale, e.DataArray.get() + offset, sizeof(glm::vec3)); - transform.interpolationTime = 0.0f; - - if (m_NextTransform.find(e.Entity) != m_NextTransform.end()) { // Did exist - m_LastReceivedTransform[e.Entity] = transform; - } else { // Did not - m_NextTransform[e.Entity] = transform; - } - return false; -} diff --git a/src/Game/Systems/PickupSpawnSystem.cpp b/src/Game/Systems/PickupSpawnSystem.cpp index e9f201c1..159f716b 100644 --- a/src/Game/Systems/PickupSpawnSystem.cpp +++ b/src/Game/Systems/PickupSpawnSystem.cpp @@ -1,7 +1,7 @@ #include "Systems/PickupSpawnSystem.h" -PickupSpawnSystem::PickupSpawnSystem(World* m_World, EventBroker* eventBroker) - : System(m_World, eventBroker) +PickupSpawnSystem::PickupSpawnSystem(SystemParams params) + : System(params) { EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &PickupSpawnSystem::OnTriggerTouch); } diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp index 60c31ce5..29ed9832 100644 --- a/src/Game/Systems/PlayerDeathSystem.cpp +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -1,7 +1,7 @@ #include "Systems/PlayerDeathSystem.h" -PlayerDeathSystem::PlayerDeathSystem(World* m_World, EventBroker* eventBroker) - : System(m_World, eventBroker) +PlayerDeathSystem::PlayerDeathSystem(SystemParams params) + : System(params) { EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerDeathSystem::OnPlayerDeath); } diff --git a/src/Game/Systems/PlayerHUD.cpp b/src/Game/Systems/PlayerHUDSystem.cpp similarity index 85% rename from src/Game/Systems/PlayerHUD.cpp rename to src/Game/Systems/PlayerHUDSystem.cpp index 55d0c3f1..898d8bea 100644 --- a/src/Game/Systems/PlayerHUD.cpp +++ b/src/Game/Systems/PlayerHUDSystem.cpp @@ -1,21 +1,6 @@ -#include "Game/Systems/PlayerHUD.h" +#include "Game/Systems/PlayerHUDSystem.h" -PlayerHUD::PlayerHUD(World* world, EventBroker* eventBrokerer) - :System(world, eventBrokerer) - , m_World(world) - , m_EventBroker(eventBrokerer) -{ - - -} - -PlayerHUD::~PlayerHUD() -{ - - -} - -void PlayerHUD::Update(double dt) +void PlayerHUDSystem::Update(double dt) { auto healthHUDs = m_World->GetComponents("HealthHUD"); if (healthHUDs == nullptr) { diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index 7b244562..93f0cd3d 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -1,8 +1,7 @@ #include "Systems/PlayerMovementSystem.h" -PlayerMovementSystem::PlayerMovementSystem(World* world, EventBroker* eventBroker) - : System(world, eventBroker) - , PureSystem("Player") +PlayerMovementSystem::PlayerMovementSystem(SystemParams params) + : System(params) { EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &PlayerMovementSystem::OnPlayerSpawned); } @@ -15,6 +14,12 @@ PlayerMovementSystem::~PlayerMovementSystem() } void PlayerMovementSystem::Update(double dt) +{ + updateMovementControllers(dt); + updateVelocity(dt); +} + +void PlayerMovementSystem::updateMovementControllers(double dt) { for (auto& kv : m_PlayerInputControllers) { EntityWrapper player = kv.first; @@ -24,12 +29,20 @@ void PlayerMovementSystem::Update(double dt) continue; } + // Aim pitch EntityWrapper cameraEntity = player.FirstChildByName("Camera"); if (cameraEntity.Valid()) { glm::vec3& cameraOrientation = cameraEntity["Transform"]["Orientation"]; cameraOrientation.x += controller->Rotation().x; // Limit camera pitch so we don't break our necks cameraOrientation.x = glm::clamp(cameraOrientation.x, -glm::half_pi(), glm::half_pi()); + // Set third person model aim pitch + EntityWrapper playerModel = player.FirstChildByName("PlayerModel"); + if (playerModel.Valid()) { + ComponentWrapper cAnimationOffset = playerModel["AnimationOffset"]; + double time = (cameraOrientation.x + glm::half_pi()) / glm::pi(); + cAnimationOffset["Time"] = time; + } } ComponentWrapper& cTransform = player["Transform"]; @@ -56,6 +69,12 @@ void PlayerMovementSystem::Update(double dt) } else { wishSpeed = playerMovementSpeed; } + if (player.ID == m_LocalPlayer.ID) { + if (glm::length(wishDirection) == 0) { + // If no key is pressed, reset the distance moved since last step. + m_DistanceMoved = 0; + } + } glm::vec3& velocity = cPhysics["Velocity"]; bool isOnGround = (bool)cPhysics["IsOnGround"]; ImGui::Text(isOnGround ? "On ground" : "In air"); @@ -90,12 +109,20 @@ void PlayerMovementSystem::Update(double dt) //you cant jump and dash at the same time - since there is no friction in the air and we would thus dash much further in the air if (!controller->PlayerIsDashing() && controller->Jumping() && !controller->Crouching() && (isOnGround || !controller->DoubleJumping())) { (bool)cPhysics["IsOnGround"] = false; - if (velocity.y == 0.f) { + if (isOnGround) { controller->SetDoubleJumping(false); } else { + //put a hexagon at the players feet + auto hexagonEffect = ResourceManager::Load("Schema/Entities/DoubleJumpHexagon.xml"); + EntityFileParser parser(hexagonEffect); + EntityID hexagonEffectID = parser.MergeEntities(m_World); + EntityWrapper hexagonEW = EntityWrapper(m_World, hexagonEffectID); + hexagonEW["Transform"]["Position"] = (glm::vec3)player["Transform"]["Position"]; controller->SetDoubleJumping(true); + Events::DoubleJump e; + m_EventBroker->Publish(e); } - velocity.y += 4.f; + velocity.y = 4.f; } if (player.HasComponent("AABB")) { @@ -111,24 +138,74 @@ void PlayerMovementSystem::Update(double dt) EntityWrapper playerModel = player.FirstChildByName("PlayerModel"); if (playerModel.Valid()) { ComponentWrapper cAnimation = playerModel["Animation"]; + std::string& animationName1 = cAnimation["AnimationName1"]; + std::string& animationName2 = cAnimation["AnimationName2"]; + double& animationTime1 = cAnimation["Time1"]; + double& animationTime2 = cAnimation["Time2"]; + double& animationSpeed1 = cAnimation["Speed1"]; + double& animationSpeed2 = cAnimation["Speed2"]; + double& animationWeight1 = cAnimation["Weight1"]; + double& animationWeight2 = cAnimation["Weight2"]; float movementLength = glm::length(groundVelocity); //TODO: add assault dash animation here if (glm::length(controller->Movement()) > 0.f) { - if (controller->Crouching()) { - cAnimation["Name"] = "Crouch Walk"; - (double&)cAnimation["Speed"] = 1.f * -glm::sign(controller->Movement().z); + double forwardMovement = controller->Movement().z; + double strafeMovement = controller->Movement().x; + + if (controller->Crouching() && animationName1 != "CrouchWalk") { + animationName1 = "CrouchWalk"; + animationSpeed1 = 1.0 * -glm::sign(controller->Movement().z); } else { - cAnimation["Name"] = "Run"; - (double&)cAnimation["Speed"] = 2.f * -glm::sign(controller->Movement().z); + if (glm::abs(forwardMovement) > 0) { + if (animationName1 != "Run") { + animationName1 = "Run"; + if (animationName2 == "StrafeLeft" || animationName2 == "StrafeRight") { + animationTime1 = animationTime2; + } else { + animationTime1 = 0.0; + } + } + animationSpeed1 = 2.f * -glm::sign(forwardMovement); + } + + if (glm::abs(strafeMovement) > 0) { + if (animationName2 != "StrafeLeft" && animationName2 != "StrafeRight") { + if (strafeMovement < 0) { + animationName2 = "StrafeLeft"; + } + if (strafeMovement > 0) { + animationName2 = "StrafeRight"; + } + if (animationName1 == "Run") { + animationTime2 = animationTime1; + } else { + animationTime2 = 0.0; + } + } + animationSpeed2 = 2.f * glm::abs(strafeMovement); + } + + double strafeWeight = glm::abs(strafeMovement) / (glm::abs(forwardMovement) + glm::abs(strafeMovement)); + animationWeight2 = strafeWeight; + animationWeight1 = 1.0 - strafeWeight; } } else { if (controller->Crouching()) { - cAnimation["Name"] = "Crouch"; - (double&)cAnimation["Speed"] = 1.f; + animationName1 = "Crouch"; + animationName2 = ""; + animationSpeed1 = 1.0; + animationSpeed2 = 0.0; + animationWeight1 = 1.0; + animationWeight2 = 0.0; } else { - cAnimation["Name"] = "Hold Pos"; - (double&)cAnimation["Speed"] = 1.f; + animationName1 = "Idle"; + animationName2 = ""; + animationSpeed1 = 1.f; + animationSpeed2 = 0.0; + animationWeight1 = 1.0; + animationWeight2 = 0.0; + //cAnimation["AnimationName2"] = "Idle"; } } } @@ -136,16 +213,19 @@ void PlayerMovementSystem::Update(double dt) controller->Reset(); } + playerStep(dt); } -void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) + +void PlayerMovementSystem::updateVelocity(double dt) { - ComponentWrapper& cTransform = entity["Transform"]; - if (!entity.HasComponent("Physics")) { + // Only apply velocity to local player + if (!LocalPlayer.Valid()) { return; } - ComponentWrapper& cPhysics = entity["Physics"]; + ComponentWrapper& cTransform = LocalPlayer["Transform"]; + ComponentWrapper& cPhysics = LocalPlayer["Physics"]; glm::vec3& velocity = cPhysics["Velocity"]; bool isOnGround = (bool)cPhysics["IsOnGround"]; @@ -163,6 +243,7 @@ void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp velocity.z *= multiplier; } + // Gravity if (cPhysics["Gravity"]) { velocity.y -= 9.82f * (float)dt; } @@ -171,10 +252,37 @@ void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp position += velocity * (float)dt; } +void PlayerMovementSystem::playerStep(double dt) +{ + if (!m_LocalPlayer.Valid()) { + return; + } + // Position of the local player, used see how far a player has moved. + glm::vec3 pos = (glm::vec3)m_World->GetComponent(m_LocalPlayer.ID, "Transform")["Position"]; + // Used to see if a player is airborne. + bool grounded = (bool)m_World->GetComponent(m_LocalPlayer.ID, "Physics")["IsOnGround"]; + m_DistanceMoved += glm::length(pos - m_LastPosition); + // Set the last position for next iteration + m_LastPosition = pos; + if (m_DistanceMoved > m_PlayerStepLength && grounded) { + // Player moved a step's distance + // Create footstep sound + Events::PlaySoundOnEntity e; + e.EmitterID = m_LocalPlayer.ID; + e.FilePath = m_LeftFoot ? "Audio/footstep/footstep2.wav" : "Audio/footstep/footstep3.wav"; + m_LeftFoot = !m_LeftFoot; + m_EventBroker->Publish(e); + m_DistanceMoved = 0.f; + } +} + bool PlayerMovementSystem::OnPlayerSpawned(Events::PlayerSpawned& e) { // When a player spawns, create an input controller for them m_PlayerInputControllers[e.Player] = new FirstPersonInputController(m_EventBroker, e.PlayerID); - + if (e.PlayerID == -1) { + // Keep track of the local player + m_LocalPlayer = e.Player; + } return true; } diff --git a/src/Game/Systems/PlayerSpawnSystem.cpp b/src/Game/Systems/PlayerSpawnSystem.cpp index 5f46cce3..507ed0f5 100644 --- a/src/Game/Systems/PlayerSpawnSystem.cpp +++ b/src/Game/Systems/PlayerSpawnSystem.cpp @@ -1,7 +1,7 @@ #include "Systems/PlayerSpawnSystem.h" -PlayerSpawnSystem::PlayerSpawnSystem(World* m_World, EventBroker* eventBroker) - : System(m_World, eventBroker) +PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params) + : System(params) { EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerSpawnSystem::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_OnPlayerSpawnerd, &PlayerSpawnSystem::OnPlayerSpawned); @@ -71,6 +71,9 @@ bool PlayerSpawnSystem::OnInputCommand(const Events::InputCommand& e) bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e) { // When a player is actually spawned (since the actual spawning is handled on the server) + if (!IsClient) { + return false; + } // Check if a player already exists if (m_PlayerEntities.count(e.PlayerID) != 0) { diff --git a/src/Game/Systems/SoundSystem.cpp b/src/Game/Systems/SoundSystem.cpp new file mode 100644 index 00000000..10dc61f7 --- /dev/null +++ b/src/Game/Systems/SoundSystem.cpp @@ -0,0 +1,180 @@ +#include "Game/Systems/SoundSystem.h" + +SoundSystem::SoundSystem(SystemParams params) + : System(params) + , PureSystem("SoundEmitter") +{ + ConfigFile* config = ResourceManager::Load("Config.ini"); + m_Announcer = ResourceManager::Load("Config.ini")->Get("Sound.Announcer", "female"); + EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &SoundSystem::OnPlayerSpawned); + EVENT_SUBSCRIBE_MEMBER(m_InputCommand, &SoundSystem::OnInputCommand); + EVENT_SUBSCRIBE_MEMBER(m_EDoubleJump, &SoundSystem::OnDoubleJump); + EVENT_SUBSCRIBE_MEMBER(m_EDashAbility, &SoundSystem::OnDashAbility); + EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &SoundSystem::OnPlayerDamage); + EVENT_SUBSCRIBE_MEMBER(m_ECaptured, &SoundSystem::OnCaptured); + EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &SoundSystem::OnTriggerTouch); +} + +void SoundSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) +{ } + +void SoundSystem::Update(double dt) +{ + // Temp for play test. + if (m_DrumsIsPlaying) { + m_DrumsIsPlaying = !drumTimer(dt); + } +} + +bool SoundSystem::OnPlayerSpawned(const Events::PlayerSpawned &e) +{ + if (e.PlayerID == -1) { // Local player + m_World->AttachComponent(e.Player.ID, "Listener"); + Events::PlaySoundOnEntity go; + go.EmitterID = LocalPlayer.ID; + go.FilePath = "Audio/announcer/" + m_Announcer + "/go.wav"; + m_EventBroker->Publish(go); + // TEMP: starts bgm + { + Events::PlayBackgroundMusic ev; + ev.FilePath = "Audio/bgm/ambient.wav"; + m_EventBroker->Publish(ev); + } + } + return true; +} + +bool SoundSystem::OnInputCommand(const Events::InputCommand & e) +{ + if (e.Command == "Jump" && e.Value > 0) { + if (e.PlayerID == -1) { // local player + playerJumps(); + return true; + } + } + if (e.Command == "TakeDamage" && e.Value > 0) { + Events::PlayerDamage ev; + ev.Player = LocalPlayer; + ev.Damage = 1.0; + m_EventBroker->Publish(ev); + } + + return false; +} + +void SoundSystem::playerJumps() +{ + if (!LocalPlayer.Valid()) { + return; + } + + bool grounded = (bool)m_World->GetComponent(LocalPlayer.ID, "Physics")["IsOnGround"]; + if (grounded) { + Events::PlaySoundOnEntity e; + e.EmitterID = LocalPlayer.ID; + e.FilePath = "Audio/jump/jump1.wav"; + m_EventBroker->Publish(e); + } +} + +bool SoundSystem::drumTimer(double dt) +{ + m_DrumTimer += dt; + if (m_DrumTimer > 15) { + m_DrumTimer = 0.0; + return true; + } else { + return false; + } +} + +bool SoundSystem::OnCaptured(const Events::Captured & e) +{ + int homeTeam = (int)m_World->GetComponent(e.CapturePointID, "Team")["Team"]; + int team = (int)m_World->GetComponent(LocalPlayer.ID, "Team")["Team"]; + Events::PlaySoundOnEntity ev; + if (team == homeTeam) { + ev.FilePath = "Audio/announcer/" + m_Announcer + "/objective_achieved.wav"; + } else { + ev.FilePath = "Audio/announcer/" + m_Announcer + "/objective_failed.wav"; // have not been tested + } + ev.EmitterID = LocalPlayer.ID; + m_EventBroker->Publish(ev); + // Temp for play test. + m_DrumsIsPlaying = false; + return false; +} + +// Testing purposes atm... +bool SoundSystem::OnPlayerDamage(const Events::PlayerDamage & e) +{ + // Should check for only local players here... + std::uniform_int_distribution dist(1, 12); + int rand = dist(generator); + std::vector paths; + paths.push_back("Audio/hurt/hurt" + std::to_string(rand) + ".wav"); + + // // Breathe + // int ammountOfbreaths = (static_cast(e.Damage) / 10) + 2; // TEMP: Idk something stupid like this shit + // for (int i = 0; i < ammountOfbreaths; i++) { + // paths.push_back("Audio/exhausted/breath.wav"); + // } + Events::PlayQueueOnEntity ev; + ev.Emitter = LocalPlayer; + ev.FilePaths = paths; + m_EventBroker->Publish(ev); + return false; +} + +bool SoundSystem::OnPlayerDeath(const Events::PlayerDeath & e) +{ + Events::PlaySoundOnEntity ev; + ev.EmitterID = LocalPlayer.ID; + ev.FilePath = "Audio/die/die2.wav"; + m_EventBroker->Publish(ev); + return false; +} + +bool SoundSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup & e) +{ + Events::PlaySoundOnEntity ev; + ev.EmitterID = LocalPlayer.ID; + ev.FilePath = "Audio/pickup/pickup2.wav"; + m_EventBroker->Publish(ev); + return false; +} + +bool SoundSystem::OnTriggerTouch(const Events::TriggerTouch & e) +{ + // Temp for play test. + if (m_DrumsIsPlaying) { + return false; + } + if (m_World->HasComponent(e.Trigger.ID, "CapturePoint")) { + Events::PlaySoundOnEntity ev; // should be BGM + ev.EmitterID = LocalPlayer.ID; + ev.FilePath = "Audio/bgm/drumstest.wav"; + m_EventBroker->Publish(ev); + // Temp for play test. + m_DrumsIsPlaying = true; + } + return false; +} + +bool SoundSystem::OnDoubleJump(const Events::DoubleJump & e) +{ + Events::PlaySoundOnEntity ev; + ev.EmitterID = LocalPlayer.ID; + ev.FilePath = "Audio/jump/jump2.wav"; + m_EventBroker->Publish(ev); + return false; +} + +bool SoundSystem::OnDashAbility(const Events::DashAbility &e) +{ + Events::PlaySoundOnEntity ev; + ev.EmitterID = LocalPlayer.ID; + ev.FilePath = "Audio/jump/dash1.wav"; + m_EventBroker->Publish(ev); + return false; +} \ No newline at end of file diff --git a/src/Game/Systems/SpawnerSystem.cpp b/src/Game/Systems/SpawnerSystem.cpp index 7a0a13c9..99f5df93 100644 --- a/src/Game/Systems/SpawnerSystem.cpp +++ b/src/Game/Systems/SpawnerSystem.cpp @@ -1,7 +1,7 @@ #include "Systems/SpawnerSystem.h" -SpawnerSystem::SpawnerSystem(World* world, EventBroker* eventBroker) - : System(world, eventBroker) +SpawnerSystem::SpawnerSystem(SystemParams params) + : System(params) { EVENT_SUBSCRIBE_MEMBER(m_OnSpawnerSpawn, &SpawnerSystem::OnSpawnerSpawn); } @@ -51,7 +51,7 @@ 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); // TODO: Quaternions, bitch - //spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint.World, spawnPoint.ID)); + spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint)); return spawnedEntity; } diff --git a/src/Game/Systems/WeaponSystem.cpp b/src/Game/Systems/WeaponSystem.cpp index bc7c86b6..8b6ba85b 100644 --- a/src/Game/Systems/WeaponSystem.cpp +++ b/src/Game/Systems/WeaponSystem.cpp @@ -1,13 +1,15 @@ #include "Systems/WeaponSystem.h" -WeaponSystem::WeaponSystem(World* world, EventBroker* eventBroker, IRenderer* renderer) - : System(world, eventBroker) - , ImpureSystem() +WeaponSystem::WeaponSystem(SystemParams params, IRenderer* renderer, Octree* collisionOctree) + : System(params) + , PureSystem("Player") + , m_SystemParams(params) , m_Renderer(renderer) + , m_CollisionOctree(collisionOctree) { - EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &WeaponSystem::OnPlayerSpawned); EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &WeaponSystem::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EShoot, &WeaponSystem::OnShoot); + EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &WeaponSystem::OnPlayerSpawned); } void WeaponSystem::Update(double dt) @@ -15,90 +17,84 @@ void WeaponSystem::Update(double dt) } -bool WeaponSystem::OnPlayerSpawned(const Events::PlayerSpawned& e) +void WeaponSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPlayer, double dt) { + // Update potential weapon behaviour for player + auto it = m_ActiveWeapons.find(entity); + if (it == m_ActiveWeapons.end()) { + selectWeapon(entity, 1); + } + + m_ActiveWeapons.at(entity)->Update(dt); +} + +bool WeaponSystem::OnInputCommand(Events::InputCommand& e) +{ + EntityWrapper player = e.Player; if (e.PlayerID == -1) { - m_LocalPlayer = e.Player; + player = LocalPlayer; } - return true; -} -bool WeaponSystem::OnInputCommand(const Events::InputCommand& e) -{ - // Only shoot client-side! - if (e.PlayerID != -1) { + // Make sure player is alive + if (!player.Valid()) { return false; } - // Only shoot if the player is alive - if (!m_LocalPlayer.Valid()) { - return false; - } - - if (e.Command == "PrimaryFire" && e.Value > 0) { - Events::Shoot eShoot; - if (e.PlayerID == -1) { - eShoot.Player = m_LocalPlayer; - } else { - eShoot.Player = e.Player; + // Weapon selection + if (e.Command == "SelectWeapon") { + if (e.Value != 0) { + //selectWeapon(player, static_cast(e.Value)); + } + } + + // Fire + if (e.Command == "PrimaryFire") { + if (m_ActiveWeapons.find(player) != m_ActiveWeapons.end()) { + auto weapon = m_ActiveWeapons.at(player); + if (e.Value > 0) { + weapon->Fire(); + } else { + weapon->CeaseFire(); + } } - m_EventBroker->Publish(eShoot); } return true; } -bool WeaponSystem::OnShoot(Events::Shoot& eShoot) +void WeaponSystem::selectWeapon(EntityWrapper player, ComponentInfo::EnumType slot) +{ + // Primary + if (slot == 1) { + // TODO: if class... + if (m_ActiveWeapons.count(player) == 0) { + m_ActiveWeapons.insert(std::make_pair(player, std::make_shared(m_SystemParams, m_CollisionOctree, player))); + } else { + //m_ActiveWeapons.erase(player); + } + } + + // Secondary + if (slot == 2) { + //m_ActiveWeapons[player] = std::make_shared(); + } +} + +bool WeaponSystem::OnPlayerSpawned(Events::PlayerSpawned& e) +{ + // Select primary weapon on player spawn + // TODO: Select the active one specified by player component + return true; +} + +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) { + // Only run further picking code for the local player! + if (eShoot.Player != LocalPlayer) { return false; } @@ -139,4 +135,4 @@ bool WeaponSystem::OnShoot(Events::Shoot& eShoot) m_EventBroker->Publish(ePlayerDamage); return true; -} +} \ No newline at end of file diff --git a/tools/MayaExporter/MayaExporter/Export.cpp b/tools/MayaExporter/MayaExporter/Export.cpp index d8f1abd4..3497fd04 100644 --- a/tools/MayaExporter/MayaExporter/Export.cpp +++ b/tools/MayaExporter/MayaExporter/Export.cpp @@ -47,13 +47,24 @@ bool Export::Meshes(std::string pathName, bool selectedOnly) for (unsigned int i = 0; i < connections.length(); i++) { if (connections[i].node().apiType() == MFn::kSkinClusterFilter) { - MGlobal::select(shape.parent(i), MGlobal::kReplaceList); - MGlobal::displayInfo(MString() + "Moving " + thisNode.name() + " to bindPose."); + shape.parent(0, &status); + if (status != MS::kSuccess) { + MGlobal::displayError(MString() + "shape.parent(0, &status) failed with: " + status.errorString()); + } + status = MGlobal::select(shape.parent(0), MGlobal::kReplaceList); + if (status != MS::kSuccess) { + MGlobal::displayError(MString() + "Parent to " + thisNode.name() + " failed"); + } + + MFnDependencyNode tmp(shape.parent(0)); + MGlobal::displayInfo(MString() + "Moving " + tmp.name() + " to bindPose."); + status = MGlobal::executeCommand("GoToBindPose;"); if (status != MS::kSuccess) { MGlobal::displayError(MString() + "GoToBindPose: " + status.errorString()); } - MGlobal::displayInfo(MString() + "Has moved " + thisNode.name() + " to bindPose."); + + MGlobal::displayInfo(MString() + "Has moved " + tmp.name() + " to bindPose."); } } } @@ -109,6 +120,8 @@ bool Export::Materials(std::string pathName) bool Export::Animations(std::string pathName, std::vector animInfo) { + allAnimations.clear(); + allBindPoses.clear(); if (MAnimControl::currentTime().unit() != MTime::kNTSCField) { MGlobal::displayError(MString() + "Please change to 60 FPS under Preferences/Settings!"); diff --git a/tools/MayaExporter/MayaExporter/Material.cpp b/tools/MayaExporter/MayaExporter/Material.cpp index 03521231..a5717aa6 100644 --- a/tools/MayaExporter/MayaExporter/Material.cpp +++ b/tools/MayaExporter/MayaExporter/Material.cpp @@ -82,16 +82,36 @@ bool Material::findColorTexture(MaterialNode& material_node, MFnDependencyNode& workspace); FullPath = FullPath.substr(workspace.length()); FullPath = FullPath.substr(FullPath.find_first_of("/") + 1); - material_node.ColorMapFile = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); - material_node.ColorMapFileLength = material_node.ColorMapFile.length() + 1; - // Test - MGlobal::displayInfo(MString() + "getAbsolutePathToResources: " + workspace); - MGlobal::displayInfo(MString() + "Texture file: " + FullPath.c_str()); + MaterialNode::Texture newTexture; + + newTexture.FileName = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); + newTexture.FileNameLength = newTexture.FileName.length() + 1; + + MPlug uvRepeatFile = TextureNode.findPlug("repeatUV"); + + uvRepeatFile.connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kPlace2dTexture)) { + MFnDependencyNode place2DTexture(AllConnections[i].node()); + MPlug uvRepeat = place2DTexture.findPlug("repeatUV"); + + newTexture.UVTiling[0] = uvRepeat.child(0).asFloat(); + newTexture.UVTiling[1] = uvRepeat.child(1).asFloat(); + } + } + + material_node.ColorMaps.push_back(newTexture); + if(material_node.type == MaterialNode::MaterialType::Basic) + material_node.type = MaterialNode::MaterialType::SingleTextures; return true; + + } else if (AllConnections[i].node().hasFn(MFn::kLayeredTexture)) { + MGlobal::displayInfo(MString() + "find splat map"); + return findSplatTextures(material_node, material_node.ColorMaps, MFnDependencyNode(AllConnections[i].node())); } } - return false; } @@ -120,9 +140,31 @@ bool Material::findNormalTexture(MaterialNode& material_node, MFnDependencyNode& workspace); FullPath = FullPath.substr(workspace.length()); FullPath = FullPath.substr(FullPath.find_first_of("/") + 1); - material_node.NormalMapFile = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); - material_node.NormalMapFileLength = material_node.NormalMapFile.length() + 1; + + MaterialNode::Texture newTexture; + + newTexture.FileName = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); + newTexture.FileNameLength = newTexture.FileName.length() + 1; + + MPlug uvRepeatFile = TextureNode.findPlug("repeatUV"); + + uvRepeatFile.connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kPlace2dTexture)) { + MFnDependencyNode place2DTexture(AllConnections[i].node()); + MPlug uvRepeat = place2DTexture.findPlug("repeatUV"); + + newTexture.UVTiling[0] = uvRepeat.child(0).asFloat(); + newTexture.UVTiling[1] = uvRepeat.child(1).asFloat(); + } + } + + material_node.NormalMaps.push_back(newTexture); return true; + } else if (AllConnections[i].node().hasFn(MFn::kLayeredTexture)) { + MGlobal::displayInfo(MString() + "find splat map"); + return findSplatTextures(material_node, material_node.NormalMaps, MFnDependencyNode(AllConnections[i].node())); } } } @@ -150,9 +192,34 @@ bool Material::findSpecularTexture(MaterialNode& material_node, MFnDependencyNod workspace); FullPath = FullPath.substr(workspace.length()); FullPath = FullPath.substr(FullPath.find_first_of("/") + 1); - material_node.SpecularMapFile = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); - material_node.SpecularMapFileLength = material_node.SpecularMapFile.length() + 1; + + MaterialNode::Texture newTexture; + + newTexture.FileName = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); + newTexture.FileNameLength = newTexture.FileName.length() + 1; + + MPlug uvRepeatFile = TextureNode.findPlug("repeatUV"); + + uvRepeatFile.connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kPlace2dTexture)) { + //C:\Users\kamisama\Desktop\TacticalZ\assets\test + MFnDependencyNode place2DTexture(AllConnections[i].node()); + MPlug uvRepeat = place2DTexture.findPlug("repeatUV"); + + newTexture.UVTiling[0] = uvRepeat.child(0).asFloat(); + newTexture.UVTiling[1] = uvRepeat.child(1).asFloat(); + } + } + + material_node.SpecularMaps.push_back(newTexture); + if (material_node.type == MaterialNode::MaterialType::Basic) + material_node.type = MaterialNode::MaterialType::SingleTextures; return true; + } else if (AllConnections[i].node().hasFn(MFn::kLayeredTexture)) { + MGlobal::displayInfo(MString() + "find splat map"); + return findSplatTextures(material_node, material_node.SpecularMaps, MFnDependencyNode(AllConnections[i].node())); } } return false; @@ -168,7 +235,7 @@ bool Material::findIncandescenceTexture(MaterialNode& material_node, MFnDependen for (int i = 0; i < AllConnections.length(); i++) { if (AllConnections[i].node().hasFn(MFn::kFileTexture)) { MFnDependencyNode TextureNode(AllConnections[i].node()); - + std::string FullPath = TextureNode.findPlug("ftn").asString().asChar(); m_TexturePaths.push_back(FullPath); @@ -177,14 +244,141 @@ bool Material::findIncandescenceTexture(MaterialNode& material_node, MFnDependen workspace); FullPath = FullPath.substr(workspace.length()); FullPath = FullPath.substr(FullPath.find_first_of("/") + 1); - material_node.IncandescenceMapFile = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); - material_node.IncandescenceMapFileLength = material_node.IncandescenceMapFile.length() + 1; + + MaterialNode::Texture newTexture; + + newTexture.FileName = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); + newTexture.FileNameLength = newTexture.FileName.length() + 1; + + MPlug uvRepeatFile = TextureNode.findPlug("repeatUV"); + + uvRepeatFile.connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kPlace2dTexture)) { + MFnDependencyNode place2DTexture(AllConnections[i].node()); + MPlug uvRepeat = place2DTexture.findPlug("repeatUV"); + + newTexture.UVTiling[0] = uvRepeat.child(0).asFloat(); + newTexture.UVTiling[1] = uvRepeat.child(1).asFloat(); + } + } + + material_node.IncandescenceMaps.push_back(newTexture); + if (material_node.type == MaterialNode::MaterialType::Basic) + material_node.type = MaterialNode::MaterialType::SingleTextures; return true; + + } else if (AllConnections[i].node().hasFn(MFn::kLayeredTexture)) { + MGlobal::displayInfo(MString() + "find splat map"); + return findSplatTextures(material_node, material_node.IncandescenceMaps, MFnDependencyNode(AllConnections[i].node())); } } return false; } +//C:\Users\kamisama\Desktop\TacticalZ\assets\test + +bool Material::findSplatTextures(MaterialNode& material_node, std::vector& textureVector, MFnDependencyNode& node) { + //Get all Inputs in LayeredTexture + MPlug inputs = node.findPlug("inputs"); + MGlobal::displayInfo(MString() + "inputs.numElements(): " + inputs.numElements()); + + MPlugArray AllConnections; + MStatus test; + //Try to find splat texture if using custom splatmap build up. + inputs[0].child(1).connectedTo(AllConnections, true, false); + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kMultiplyDivide)) { + MGlobal::displayInfo(MString() + "found kMultiplyDivide"); + MFnDependencyNode multiplyDivide(AllConnections[i].node()); + multiplyDivide.findPlug("input1", &test).child(0).connectedTo(AllConnections, true, false);; + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kFileTexture)) { + MFnDependencyNode TextureNode(AllConnections[i].node()); + + std::string FullPath = TextureNode.findPlug("ftn").asString().asChar(); + m_TexturePaths.push_back(FullPath); + + MString workspace; + MStatus status = MGlobal::executeCommand(MString("workspace -q -rd;"), + workspace); + FullPath = FullPath.substr(workspace.length()); + FullPath = FullPath.substr(FullPath.find_first_of("/") + 1); + + MaterialNode::Texture newTexture; + + newTexture.FileName = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); + newTexture.FileNameLength = newTexture.FileName.length() + 1; + + MPlug uvRepeatFile = TextureNode.findPlug("repeatUV"); + + uvRepeatFile.connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kPlace2dTexture)) { + MFnDependencyNode place2DTexture(AllConnections[i].node()); + MPlug uvRepeat = place2DTexture.findPlug("repeatUV"); + + newTexture.UVTiling[0] = uvRepeat.child(0).asFloat(); + newTexture.UVTiling[1] = uvRepeat.child(1).asFloat(); + } + } + material_node.SplatMap = newTexture; + material_node.type = MaterialNode::MaterialType::SplatMapping; + } + } + } + } + + for (unsigned int i = 0; i < inputs.numElements(); i++) { + //Get connections to color in input[i] + inputs[i].child(0).connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kFileTexture)) { + MFnDependencyNode TextureNode(AllConnections[i].node()); + + std::string FullPath = TextureNode.findPlug("ftn").asString().asChar(); + m_TexturePaths.push_back(FullPath); + + MString workspace; + MStatus status = MGlobal::executeCommand(MString("workspace -q -rd;"), + workspace); + FullPath = FullPath.substr(workspace.length()); + FullPath = FullPath.substr(FullPath.find_first_of("/") + 1); + + MaterialNode::Texture newTexture; + + newTexture.FileName = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size()); + newTexture.FileNameLength = newTexture.FileName.length() + 1; + + MPlug uvRepeatFile = TextureNode.findPlug("repeatUV"); + + uvRepeatFile.connectedTo(AllConnections, true, false); + + for (int i = 0; i < AllConnections.length(); i++) { + if (AllConnections[i].node().hasFn(MFn::kPlace2dTexture)) { + MFnDependencyNode place2DTexture(AllConnections[i].node()); + MPlug uvRepeat = place2DTexture.findPlug("repeatUV"); + + newTexture.UVTiling[0] = uvRepeat.child(0).asFloat(); + newTexture.UVTiling[1] = uvRepeat.child(1).asFloat(); + } + } + textureVector.push_back(newTexture); + break; + } + } + if (AllConnections.length() == 0) { + MaterialNode::Texture newTexture; + newTexture.FileNameLength = 0; + textureVector.push_back(newTexture); + } + } + return true; +} + // Returns the absolute path for all textures. Use for copying texture files. std::vector* Material::TexturePaths() { @@ -209,7 +403,6 @@ std::vector* Material::DoIt(Mesh mesh) meshHasMaterial = true; MaterialStorage.IndexStart = totalIndices; MaterialStorage.IndexEnd = totalIndices + aMeshMaterial.second.size() - 1; - break; } totalIndices += aMeshMaterial.second.size(); } @@ -226,7 +419,10 @@ std::vector* Material::DoIt(Mesh mesh) MaterialStorage.ReflectionFactor = 0.0f; MaterialStorage.SpecularExponent = 0.0f; } - + MaterialStorage.NumColorMaps = MaterialStorage.ColorMaps.size(); + MaterialStorage.NumNormalMaps = MaterialStorage.NormalMaps.size(); + MaterialStorage.NumSpecularMaps = MaterialStorage.SpecularMaps.size(); + MaterialStorage.NumIncandescenceMaps = MaterialStorage.IncandescenceMaps.size(); m_AllMaterials.push_back(MaterialStorage); } matIt.next(); diff --git a/tools/MayaExporter/MayaExporter/Material.h b/tools/MayaExporter/MayaExporter/Material.h index e405dd07..d70a6399 100644 --- a/tools/MayaExporter/MayaExporter/Material.h +++ b/tools/MayaExporter/MayaExporter/Material.h @@ -11,62 +11,123 @@ #include "OutputData.h" #include "Mesh.h" + +//#define ColorMapSplat 1 +//#define SpecularMapSplat 1 << 1 +//#define NormalMapSplat 1 << 2 +//#define IncandescenceMapSplat 1 << 3 + + + class MaterialNode : public OutputData { public: + class Texture : public OutputData { + public: + unsigned int FileNameLength = 0; + std::string FileName; + float UVTiling[2]{ 1.0f, 1.0f }; + + virtual void WriteBinary(std::ostream& out) + { + out.write((char*)&FileNameLength, sizeof(unsigned int)); + out.write(FileName.c_str(), FileNameLength); + out.write((char*)&UVTiling, sizeof(float) * 2); + } + + virtual void WriteASCII(std::ostream& out) const + { + out << "FileNameLength: " << FileNameLength << endl; + out << "FileName: " << FileName << endl; + out << "UV tiling: " << UVTiling[0] << " " << UVTiling[1] << endl; + } + }; + + enum class MaterialType { Basic = 1, SplatMapping, SingleTextures }; + + MaterialType type = MaterialType::Basic; + std::string Name; float ReflectionFactor; float SpecularExponent; - float DiffuseColor[3]{ 1.0f, 1.0f, 1.0f }; - unsigned int ColorMapFileLength = 0; - std::string ColorMapFile; + float DiffuseColor[3]{ 1.0f, 1.0f, 1.0f }; + float SpecularColor[3]{ 1.0f, 1.0f, 1.0f }; + float IncandescenceColor[3]{ 1.0f, 1.0f, 1.0f }; - float SpecularColor[3]{ 1.0f, 1.0f, 1.0f }; - unsigned int SpecularMapFileLength = 0; - std::string SpecularMapFile; + unsigned int IndexStart; + unsigned int IndexEnd; - unsigned int NormalMapFileLength = 0; - std::string NormalMapFile; - - float IncandescenceColor[3]{ 1.0f, 1.0f, 1.0f }; - unsigned int IncandescenceMapFileLength = 0; - std::string IncandescenceMapFile; - - unsigned int IndexStart; - unsigned int IndexEnd; + unsigned char NumColorMaps = 0; + unsigned char NumSpecularMaps = 0; + unsigned char NumNormalMaps = 0; + unsigned char NumIncandescenceMaps = 0; + Texture SplatMap; + std::vector ColorMaps; + std::vector SpecularMaps; + std::vector NormalMaps; + std::vector IncandescenceMaps; virtual void WriteBinary(std::ostream& out) { - out.write((char*)&ColorMapFileLength, sizeof(unsigned int)); - out.write((char*)&NormalMapFileLength, sizeof(unsigned int)); - out.write((char*)&SpecularMapFileLength, sizeof(unsigned int)); - out.write((char*)&IncandescenceMapFileLength, sizeof(unsigned int)); - + + out.write((char*)&type, sizeof(MaterialType)); out.write((char*)&SpecularExponent, sizeof(float)); out.write((char*)&ReflectionFactor, sizeof(float)); + out.write((char*)&DiffuseColor, sizeof(float) * 3); out.write((char*)&SpecularColor, sizeof(float) * 3); out.write((char*)&IncandescenceColor, sizeof(float) * 3); + out.write((char*)&IndexStart, sizeof(unsigned int)); out.write((char*)&IndexEnd, sizeof(unsigned int)); + if (type != MaterialType::Basic) { + if (type == MaterialType::SplatMapping) { + SplatMap.WriteBinary(out); + } + out.write((char*)&NumColorMaps, sizeof(unsigned char)); + out.write((char*)&NumSpecularMaps, sizeof(unsigned char)); + out.write((char*)&NumNormalMaps, sizeof(unsigned char)); + out.write((char*)&NumIncandescenceMaps, sizeof(unsigned char)); + } - out.write(ColorMapFile.c_str(), ColorMapFileLength); - out.write(NormalMapFile.c_str(), NormalMapFileLength); - out.write(SpecularMapFile.c_str(), SpecularMapFileLength); - out.write(IncandescenceMapFile.c_str(), IncandescenceMapFileLength); + if (type != MaterialType::Basic) { + for (auto aTexture : ColorMaps) { + aTexture.WriteBinary(out); + } + for (auto aTexture : SpecularMaps) { + aTexture.WriteBinary(out); + } + for (auto aTexture : NormalMaps) { + aTexture.WriteBinary(out); + } + for (auto aTexture : IncandescenceMaps) { + aTexture.WriteBinary(out); + } + } } virtual void WriteASCII(std::ostream& out) const { out << "New Material _ not in binary" << endl; - out << "number of indices: " << Name << " _ not in binary" << endl; - out << "ColorMapFile length: " << ColorMapFileLength << endl; - out << "NormalMapFile length: " << NormalMapFileLength << endl; - out << "SpecularMapFile length: " << SpecularMapFileLength << endl; - out << "IncandescenceMapFile length: " << IncandescenceMapFileLength << endl; + out << "MaterialType(enum): "; + switch (type) { + case MaterialType::Basic: + out << "Basic"; + break; + case MaterialType::SplatMapping: + out << "SplatMapping"; + break; + case MaterialType::SingleTextures: + out << "SingleTextures"; + break; + }; + + out << endl; + + out << "Material Name: " << Name << " _ not in binary" << endl; out << "SpecularExponent: " << SpecularExponent << endl; out << "ReflectionFactor: " << ReflectionFactor << endl; @@ -76,17 +137,38 @@ public: out << "IndexStart: " << IndexStart << endl; out << "IndexEnd: " << IndexEnd << endl; - if (ColorMapFileLength > 0) - out << "ColorMapFile: " << ColorMapFile << endl; + switch (type) { + case MaterialType::SplatMapping: + out << "SplatMap _ not in binary " << endl; + SplatMap.WriteASCII(out); + //Intended fall trought + case MaterialType::SingleTextures: + out << "NumColormaps (is unsigned char in Binary): " << ((unsigned int)NumColorMaps) << endl; + out << "NumSpecularMap (is unsigned char in Binary): " << ((unsigned int)NumSpecularMaps) << endl; + out << "NumNormalMap (is unsigned char in Binary): " << ((unsigned int)NumNormalMaps) << endl; + out << "NumIncandescenceMap (is unsigned char in Binary): " << ((unsigned int)NumIncandescenceMaps )<< endl; - if (NormalMapFileLength > 0) - out << "NormalMapFile: " << NormalMapFile << endl; - - if (SpecularMapFileLength > 0) - out << "SpecularMapFile: " << SpecularMapFile << endl; - - if (IncandescenceMapFileLength > 0) - out << "IncandescenceMapFile: " << IncandescenceMapFile << endl; + out << "ColorMaps _ not in binary " << endl; + for (auto aTexture : ColorMaps) { + aTexture.WriteASCII(out); + } + + out << "SpecularMaps _ not in binary " << endl; + for (auto aTexture : SpecularMaps) { + aTexture.WriteASCII(out); + } + + out << "NormalMaps _ not in binary " << endl; + for (auto aTexture : NormalMaps) { + aTexture.WriteASCII(out); + } + + out << "IncandescenceMaps _ not in binary " << endl; + for (auto aTexture : IncandescenceMaps) { + aTexture.WriteASCII(out); + } + break; + }; } }; @@ -107,6 +189,7 @@ private: bool findNormalTexture(MaterialNode& material_node, MFnDependencyNode& node); bool findSpecularTexture(MaterialNode& material_node, MFnDependencyNode& node); bool findIncandescenceTexture(MaterialNode& material_node, MFnDependencyNode& node); + bool findSplatTextures(MaterialNode& material_node, std::vector& textureVector, MFnDependencyNode& node); void grabLambertProperties(MaterialNode& material_node, MFnDependencyNode& node); void grabBlinnProperties(MaterialNode& material_node, MFnDependencyNode& node); void grabPhongProperties(MaterialNode& material_node, MFnDependencyNode& node); diff --git a/tools/MayaExporter/MayaExporter/MayaExporter.vcxproj b/tools/MayaExporter/MayaExporter/MayaExporter.vcxproj index 4a7ac07e..b9384a45 100644 --- a/tools/MayaExporter/MayaExporter/MayaExporter.vcxproj +++ b/tools/MayaExporter/MayaExporter/MayaExporter.vcxproj @@ -40,8 +40,9 @@ v140 - Application + DynamicLibrary v140 + Unicode @@ -77,6 +78,7 @@ $(SolutionDir)$(Platform)\$(Configuration)\ + .mll @@ -135,7 +137,7 @@ NDEBUG;QT_DLL;QT_NO_DEBUG;QT_NO_IMPORT_QT47_QML;UNICODE;WIN32;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories) + C:\Program Files\Autodesk\Maya2016\include;.\GeneratedFiles;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories) MultiThreadedDLL @@ -144,7 +146,7 @@ Windows - $(OutDir)\$(ProjectName).exe + $(OutDir)$(TargetName)$(TargetExt) $(QTDIR)\lib;%(AdditionalLibraryDirectories) false qtmain.lib;%(AdditionalDependencies) diff --git a/tools/MayaExporter/MayaExporter/Menu.cpp b/tools/MayaExporter/MayaExporter/Menu.cpp index 9cc6de91..02810018 100644 --- a/tools/MayaExporter/MayaExporter/Menu.cpp +++ b/tools/MayaExporter/MayaExporter/Menu.cpp @@ -60,8 +60,6 @@ Menu::Menu(QDialog* dialog) m_ExportPath = new QLineEdit; m_FileDialog = new QFileDialog; - QString tmpPath("C:/Users/Nickelodion/Desktop/workspace/tacticalZ/assets/models/"); - m_ExportPath->setText(tmpPath); QLabel* exportLabel = new QLabel; exportLabel->setText("Export Path:"); QLabel* nameLabel = new QLabel; diff --git a/tools/MayaExporter/MayaExporter/Mesh.cpp b/tools/MayaExporter/MayaExporter/Mesh.cpp index 6af8a557..ee5a6022 100644 --- a/tools/MayaExporter/MayaExporter/Mesh.cpp +++ b/tools/MayaExporter/MayaExporter/Mesh.cpp @@ -8,95 +8,91 @@ MeshClass::MeshClass() } -std::map MeshClass::GetWeightData() -{ - MS status; - map weightMap; - - MItDependencyNodes it(MFn::kSkinClusterFilter); - - while (!it.isDone()) { - - MObject object = it.thisNode(&status); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + " it.thisNode() ERROR: " + status.errorString()); - break; - } - MFnSkinCluster skinCluster(object, &status); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "skinCluster() ERROR: " + status.errorString()); - break; - } - MDagPathArray influences; - - unsigned int nrOfInfluences = skinCluster.influenceObjects(influences,&status); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "skinCluster.influenceObjects() ERROR: " + status.errorString()); - break; - } - - unsigned int index; - index = skinCluster.indexForOutputConnection(0,&status); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "skinCluster.indexForOutputConnection() ERROR: " + status.errorString()); - break; - } - MDagPath skinPath; - status = skinCluster.getPathAtIndex(index, skinPath); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "skinCluster.getPathAtIndex() ERROR: " + status.errorString()); - break; - } - - MItGeometry geomIter(skinPath); - //for (unsigned int i = 0; i < nrOfInfluences; i++) { - // MGlobal::displayInfo(MString() + " Influence object name: " + influences[i].partialPathName().asChar()); - //} - WeightInfo weightInfo; - - while (!geomIter.isDone()) { - MObject comp = geomIter.component(&status); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "geomIter.component() ERROR: " + status.errorString()); - break; - } - MFloatArray weights; - unsigned int influenceCount; - status = skinCluster.getWeights(skinPath, comp, weights, influenceCount); - if (status != MS::kSuccess) { - MGlobal::displayError(MString() + "skinCluster.getWeights() ERROR: " + status.errorString()); - break; - } - MFnDependencyNode test(comp); - unsigned int nrOfWeights = 0; - - for (unsigned int j = 0; j < weights.length() && nrOfWeights != 4; j++) { - if (weights[j] > 0.00001) { - weightInfo.BoneWeights[nrOfWeights] = weights[j]; - weightInfo.BoneIndices[nrOfWeights] = j; - nrOfWeights++; - } - } - - float totalWeight = 0.0f; - for (unsigned int i = 0; i < 4; i++) { - totalWeight += weightInfo.BoneWeights[i]; - } - for (unsigned int i = 0; i < 4; i++) { - weightInfo.BoneWeights[i] /= totalWeight; - } - weightMap[geomIter.index()] = weightInfo; - - - for (unsigned int k = 0; k!=nrOfWeights; k++) { - MGlobal::displayInfo(MString() + "influence: " + weightInfo.BoneIndices[k] + " weight: " + weightInfo.BoneWeights[k]); - } - geomIter.next(); - } - it.next(); - } - return weightMap; -} +//std::map MeshClass::GetWeightData() +//{ +// MS status; +// map weightMap; +// +// MItDependencyNodes it(MFn::kSkinClusterFilter); +// +// while (!it.isDone()) { +// +// MObject object = it.thisNode(&status); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + " it.thisNode() ERROR: " + status.errorString()); +// break; +// } +// MFnSkinCluster skinCluster(object, &status); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + "skinCluster() ERROR: " + status.errorString()); +// break; +// } +// MDagPathArray influences; +// +// unsigned int nrOfInfluences = skinCluster.influenceObjects(influences,&status); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + "skinCluster.influenceObjects() ERROR: " + status.errorString()); +// break; +// } +// +// unsigned int index; +// index = skinCluster.indexForOutputConnection(0,&status); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + "skinCluster.indexForOutputConnection() ERROR: " + status.errorString()); +// break; +// } +// MDagPath skinPath; +// status = skinCluster.getPathAtIndex(index, skinPath); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + "skinCluster.getPathAtIndex() ERROR: " + status.errorString()); +// break; +// } +// +// MItGeometry geomIter(skinPath); +// //for (unsigned int i = 0; i < nrOfInfluences; i++) { +// // MGlobal::displayInfo(MString() + " Influence object name: " + influences[i].partialPathName().asChar()); +// //} +// WeightInfo weightInfo; +// +// while (!geomIter.isDone()) { +// MObject comp = geomIter.component(&status); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + "geomIter.component() ERROR: " + status.errorString()); +// break; +// } +// MFloatArray weights; +// unsigned int influenceCount; +// status = skinCluster.getWeights(skinPath, comp, weights, influenceCount); +// if (status != MS::kSuccess) { +// MGlobal::displayError(MString() + "skinCluster.getWeights() ERROR: " + status.errorString()); +// break; +// } +// MFnDependencyNode test(comp); +// unsigned int nrOfWeights = 0; +// +// for (unsigned int j = 0; j < weights.length() && nrOfWeights != 4; j++) { +// if (weights[j] > 0.00001) { +// weightInfo.BoneWeights[nrOfWeights] = weights[j]; +// weightInfo.BoneIndices[nrOfWeights] = j; +// nrOfWeights++; +// } +// } +// +// float totalWeight = 0.0f; +// for (unsigned int i = 0; i < 4; i++) { +// totalWeight += weightInfo.BoneWeights[i]; +// } +// for (unsigned int i = 0; i < 4; i++) { +// weightInfo.BoneWeights[i] /= totalWeight; +// } +// weightMap[geomIter.index()] = weightInfo; +// +// geomIter.next(); +// } +// it.next(); +// } +// return weightMap; +//} Mesh MeshClass::GetMeshData(MObjectArray object) { @@ -112,8 +108,6 @@ Mesh MeshClass::GetMeshData(MObjectArray object) MFnDependencyNode thisNode(node); MPlugArray connections; thisNode.findPlug("inMesh").connectedTo(connections, true, true); - MGlobal::displayInfo(MString() + "inMesh"); - bool hasSkin = false; MPlug weightList, weights; MObject weightListObject; for (unsigned int i = 0; i < connections.length(); i++) { @@ -122,7 +116,7 @@ Mesh MeshClass::GetMeshData(MObjectArray object) weightList = skinCluster.findPlug("weightList", &status); weightListObject = weightList.attribute(); weights = skinCluster.findPlug("weights"); - hasSkin = true; + newMesh.hasSkin = true; break; } } @@ -138,7 +132,6 @@ Mesh MeshClass::GetMeshData(MObjectArray object) } for (int pathID = 0; pathID < dagPaths.length(); pathID++) { - MGlobal::displayInfo(dagPaths[pathID].fullPathName()); MDagPath thisMeshPath(dagPaths[pathID]); MMatrix transformMatrix = thisMeshPath.inclusiveMatrix(&status); @@ -173,8 +166,7 @@ Mesh MeshClass::GetMeshData(MObjectArray object) break; } map> materialFaceIDs; - MGlobal::displayInfo(MString() + "shaderIndexList: " + shaderIndexList.length()); - MGlobal::displayInfo(MString() + "shaderList: " + shaderList.length()); + MPlugArray plugArray; for (int i = 0; i < shaderIndexList.length(); i++) { MFnDependencyNode shader(shaderList[shaderIndexList[i]]); @@ -261,43 +253,33 @@ Mesh MeshClass::GetMeshData(MObjectArray object) //mesh.getPoint(vertexIndex, pos, MSpace::kPostTransform); pos = positions[vertexIndex]; pos = pos * transformMatrix; - if (abs(pos.x) > 0.0001) - thisVertex.Pos[0] = pos.x; - if (abs(pos.y) > 0.0001) - thisVertex.Pos[1] = pos.y; - if (abs(pos.z) > 0.0001) - thisVertex.Pos[2] = pos.z; + + thisVertex.Pos[0] = pos.x; + thisVertex.Pos[1] = pos.y; + thisVertex.Pos[2] = pos.z; status = faceVert.getNormal(normal, MSpace::kObject); if (status != MS::kSuccess) { MGlobal::displayError(MString() + "faceVert.getNormal() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName()); break; } - if (abs(normal[0]) > 0.0001) - thisVertex.Normal[0] = normal[0]; - if (abs(normal[1]) > 0.0001) - thisVertex.Normal[1] = normal[1]; - if (abs(normal[2]) > 0.0001) - thisVertex.Normal[2] = normal[2]; + + thisVertex.Normal[0] = normal[0]; + thisVertex.Normal[1] = normal[1]; + thisVertex.Normal[2] = normal[2]; MFloatVector Tangent = Tangents[faceVert.tangentId()]; //MVector tmp = faceVert.getTangent(MSpace::kObject, NULL); //tmp.get(biTangent); - if (abs(Tangent[0]) > 0.0001) - thisVertex.Tangent[0] = Tangent[0]; - if (abs(Tangent[1]) > 0.0001) - thisVertex.Tangent[1] = Tangent[1]; - if (abs(Tangent[2]) > 0.0001) - thisVertex.Tangent[2] = Tangent[2]; + thisVertex.Tangent[0] = Tangent[0]; + thisVertex.Tangent[1] = Tangent[1]; + thisVertex.Tangent[2] = Tangent[2]; MFloatVector biNormal = biNormals[faceVert.tangentId()]; //faceVert.getBinormal().get(biNormal); - if (abs(biNormal[0]) > 0.0001) - thisVertex.BiNormal[0] = biNormal[0]; - if (abs(biNormal[1]) > 0.0001) - thisVertex.BiNormal[1] = biNormal[1]; - if (abs(biNormal[2]) > 0.0001) - thisVertex.BiNormal[2] = biNormal[2]; + thisVertex.BiNormal[0] = biNormal[0]; + thisVertex.BiNormal[1] = biNormal[1]; + thisVertex.BiNormal[2] = biNormal[2]; status = faceVert.getUV(UV); if (status != MS::kSuccess) { @@ -308,7 +290,8 @@ Mesh MeshClass::GetMeshData(MObjectArray object) thisVertex.Uv[1] = UV[1]; - if (hasSkin) { + if (newMesh.hasSkin) { + thisVertex.useWeights = true; float totalWeight = 0.0f; unsigned int totalBones = 0; MIntArray jointIDs /* ??? */; @@ -324,9 +307,11 @@ Mesh MeshClass::GetMeshData(MObjectArray object) } for (unsigned int i = 0; i < 4; i++) { - thisVertex.BoneWeights[i] = thisVertex.BoneWeights[i] / totalWeight; + //thisVertex.BoneWeights[i] = thisVertex.BoneWeights[i] / totalWeight; } - } + } else { + thisVertex.useWeights = false; + } //float totalWeight = thisVertex.BoneWeights[0] + thisVertex.BoneWeights[1] + thisVertex.BoneWeights[2] + thisVertex.BoneWeights[3]; //if (totalWeight > 0.0001f) { diff --git a/tools/MayaExporter/MayaExporter/Mesh.h b/tools/MayaExporter/MayaExporter/Mesh.h index 11f6bcf8..affc4320 100644 --- a/tools/MayaExporter/MayaExporter/Mesh.h +++ b/tools/MayaExporter/MayaExporter/Mesh.h @@ -11,6 +11,7 @@ class VertexLayout : public OutputData { public: + bool useWeights = true; float Pos[3]{ 0 }; float Normal[3]{ 0 }; float Tangent[3]{ 0 }; @@ -26,8 +27,10 @@ public: out.write((char*)&Tangent, sizeof(float) * 3); out.write((char*)&BiNormal, sizeof(float) * 3); out.write((char*)&Uv, sizeof(float) * 2); - out.write((char*)&BoneIndices, sizeof(float) * 4); - out.write((char*)&BoneWeights, sizeof(float) * 4); + if (useWeights) { + out.write((char*)&BoneIndices, sizeof(float) * 4); + out.write((char*)&BoneWeights, sizeof(float) * 4); + } } virtual void WriteASCII(std::ostream& out) const @@ -37,8 +40,10 @@ public: out << Tangent[0] << " " << Tangent[1] << " " << Tangent[2] << endl; out << BiNormal[0] << " " << BiNormal[1] << " " << BiNormal[2] << endl; out << Uv[0] << " " << Uv[1] << endl; - out << BoneIndices[0] << " " << BoneIndices[1] << " " << BoneIndices[2] << " " << BoneIndices[3] << endl; - out << BoneWeights[0] << " " << BoneWeights[1] << " " << BoneWeights[2] << " " << BoneWeights[3] << endl; + if (useWeights) { + out << BoneIndices[0] << " " << BoneIndices[1] << " " << BoneIndices[2] << " " << BoneIndices[3] << endl; + out << BoneWeights[0] << " " << BoneWeights[1] << " " << BoneWeights[2] << " " << BoneWeights[3] << endl; + } } bool operator==(const VertexLayout& right) @@ -57,6 +62,7 @@ public: class Mesh : public OutputData { public: + bool hasSkin = false; unsigned int NumVertices; unsigned int NumIndices; std::vector Vertices; @@ -64,6 +70,7 @@ public: virtual void WriteBinary(std::ostream& out) { + out.write((char*)&hasSkin, sizeof(bool)); out.write((char*)&NumVertices, sizeof(int)); out.write((char*)&NumIndices, sizeof(int)); for (auto aVertex : Vertices) { @@ -79,6 +86,11 @@ public: virtual void WriteASCII(std::ostream& out) const { out << "New Mesh _ not in binary" << endl; + out << "hasSkin: "; + if(hasSkin) + out << "true" << endl; + else + out << "false" << endl; out << "Number of vertices: " << NumVertices << endl; out << "number of indices: " << NumIndices << endl; int vertexNumber = 0; diff --git a/tools/MayaExporter/MayaExporter/Skeleton.cpp b/tools/MayaExporter/MayaExporter/Skeleton.cpp index c30311b8..2e432476 100644 --- a/tools/MayaExporter/MayaExporter/Skeleton.cpp +++ b/tools/MayaExporter/MayaExporter/Skeleton.cpp @@ -60,7 +60,7 @@ // // return m_AllSkeletons; //} -std::string attr[9] = { "scaleX", "scaleY", "scaleZ", "translateX", "translateY", "translateZ", "rotateX", "rotateY", "rotateZ" }; +static std::string attr[9] = { "scaleX", "scaleY", "scaleZ", "translateX", "translateY", "translateZ", "rotateX", "rotateY", "rotateZ" }; Animation Skeleton::GetAnimData(std::string animationName, int startFrame, int endFrame) { @@ -68,100 +68,294 @@ Animation Skeleton::GetAnimData(std::string animationName, int startFrame, int e std::vector animatedJoints; std::vector m_Hierarchy; - Animation returnData; - double oneDivSixty = 1 / 60.0; - returnData.Name = animationName; + Animation returnData; + double oneDivSixty = 1 / 60.0; + returnData.Name = animationName; returnData.nameLength = animationName.size() + 1; - returnData.Duration = (endFrame - startFrame) * oneDivSixty; + returnData.Duration = (endFrame - startFrame) * oneDivSixty; - MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint); - while (!jointIt.isDone()) - { - m_Hierarchy.push_back(jointIt.item()); + std::map, 4>> joinCheckMap; + std::map exportJoint; - MFnDependencyNode depNode(jointIt.item()); - for (int i = 0; i < 9; i++) - { - MStatus tmp; - MPlug plug = depNode.findPlug(attr[i].c_str(), &tmp); + //MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint); + //for (unsigned int i = startFrame; i <= endFrame; i++) + //{ + // MAnimControl::setCurrentTime(MTime(i, MTime::kNTSCField)); + // while (!jointIt.isDone()) + // { + // m_Hierarchy.push_back(jointIt.item()); - MPlugArray connections; - plug.connectedTo(connections, true, false, 0); - for (int j = 0; j != connections.length(); j++) { - MObject connected = connections[j].node(); + // MFnTransform MayaJoint(jointIt.item()); + // MMatrix transformationMatrix = MayaJoint.transformationMatrix(); - if (connected.hasFn(MFn::kAnimCurve)) { + // if (i == startFrame) + // { + // double doubleMat[4][4]; + // transformationMatrix.get(doubleMat); - MFnAnimCurve jointAnim(connected); + // joinCheckMap[MayaJoint.name().asChar()][0][0] = doubleMat[0][0]; + // joinCheckMap[MayaJoint.name().asChar()][0][1] = doubleMat[0][1]; + // joinCheckMap[MayaJoint.name().asChar()][0][2] = doubleMat[0][2]; + // joinCheckMap[MayaJoint.name().asChar()][0][3] = doubleMat[0][3]; + // joinCheckMap[MayaJoint.name().asChar()][1][0] = doubleMat[1][0]; + // joinCheckMap[MayaJoint.name().asChar()][1][1] = doubleMat[1][1]; + // joinCheckMap[MayaJoint.name().asChar()][1][2] = doubleMat[1][2]; + // joinCheckMap[MayaJoint.name().asChar()][1][3] = doubleMat[1][3]; + // joinCheckMap[MayaJoint.name().asChar()][2][0] = doubleMat[2][0]; + // joinCheckMap[MayaJoint.name().asChar()][2][1] = doubleMat[2][1]; + // joinCheckMap[MayaJoint.name().asChar()][2][2] = doubleMat[2][2]; + // joinCheckMap[MayaJoint.name().asChar()][2][3] = doubleMat[2][3]; + // joinCheckMap[MayaJoint.name().asChar()][3][0] = doubleMat[3][0]; + // joinCheckMap[MayaJoint.name().asChar()][3][1] = doubleMat[3][1]; + // joinCheckMap[MayaJoint.name().asChar()][3][2] = doubleMat[3][2]; + // joinCheckMap[MayaJoint.name().asChar()][3][3] = doubleMat[3][3]; - unsigned int startKeyFrameIndex = jointAnim.findClosest(MTime(startFrame, MTime::kNTSCField), &tmp); + // exportJoint[MayaJoint.name().asChar()] = false; + // } + // else if(!exportJoint[MayaJoint.name().asChar()])//!exportJoint[MayaJoint.name().asChar()]) + // { + // double doubleMat[4][4]; - if (tmp == MStatus::kFailure) - MGlobal::displayInfo(MString() + "Fail :c"); + // doubleMat[0][0] = joinCheckMap[MayaJoint.name().asChar()][0][0]; + // doubleMat[0][1] = joinCheckMap[MayaJoint.name().asChar()][0][1]; + // doubleMat[0][2] = joinCheckMap[MayaJoint.name().asChar()][0][2]; + // doubleMat[0][3] = joinCheckMap[MayaJoint.name().asChar()][0][3]; + // doubleMat[1][0] = joinCheckMap[MayaJoint.name().asChar()][1][0]; + // doubleMat[1][1] = joinCheckMap[MayaJoint.name().asChar()][1][1]; + // doubleMat[1][2] = joinCheckMap[MayaJoint.name().asChar()][1][2]; + // doubleMat[1][3] = joinCheckMap[MayaJoint.name().asChar()][1][3]; + // doubleMat[2][0] = joinCheckMap[MayaJoint.name().asChar()][2][0]; + // doubleMat[2][1] = joinCheckMap[MayaJoint.name().asChar()][2][1]; + // doubleMat[2][2] = joinCheckMap[MayaJoint.name().asChar()][2][2]; + // doubleMat[2][3] = joinCheckMap[MayaJoint.name().asChar()][2][3]; + // doubleMat[3][0] = joinCheckMap[MayaJoint.name().asChar()][3][0]; + // doubleMat[3][1] = joinCheckMap[MayaJoint.name().asChar()][3][1]; + // doubleMat[3][2] = joinCheckMap[MayaJoint.name().asChar()][3][2]; + // doubleMat[3][3] = joinCheckMap[MayaJoint.name().asChar()][3][3]; - if (startFrame * oneDivSixty <= jointAnim.time(startKeyFrameIndex).value() && jointAnim.time(startKeyFrameIndex).value() <= endFrame * oneDivSixty) { - animatedJoints.push_back(jointIt.item()); - i = 9; - break; - } + // MMatrix tmp(doubleMat); + // if (!tmp.isEquivalent(transformationMatrix)) { + // MGlobal::displayInfo(MString() + MayaJoint.name() + " is exported"); + // exportJoint[MayaJoint.name().asChar()] = true; + // animatedJoints.push_back(MayaJoint.object()); + // } + // } - unsigned int endKeyFrameIndex = jointAnim.findClosest(MTime(endFrame, MTime::kNTSCField)); - MGlobal::displayInfo(MString() + startKeyFrameIndex + " " + endKeyFrameIndex); + /*for (int i = 0; i < 9; i++) + { + MStatus tmp; + MPlug plug = depNode.findPlug(attr[i].c_str(), &tmp); - if (startFrame * oneDivSixty <= jointAnim.time(endKeyFrameIndex).value() && jointAnim.time(endKeyFrameIndex).value() <= endFrame * oneDivSixty || endKeyFrameIndex - startKeyFrameIndex > 0) { - animatedJoints.push_back(jointIt.item()); - i = 9; - break; - } + MPlugArray connections; + plug.connectedTo(connections, true, false, 0); + for (int j = 0; j != connections.length(); j++) { + MObject connected = connections[j].node(); - MFnTransform MayaJoint(jointIt.item()); + if (connected.hasFn(MFn::kAnimCurve)) { - MPlug BindPose = MayaJoint.findPlug("bindPose"); - MDataHandle DataHandle; - BindPose.getValue(DataHandle); - MFnMatrixData MartixFn(DataHandle.data()); - MMatrix BindPoseMatrix = MartixFn.matrix(); + MFnAnimCurve jointAnim(connected); - if (!BindPoseMatrix.isEquivalent(MayaJoint.transformationMatrix())) - { - MGlobal::displayError(MString() + animationName.c_str() + " is using " + MayaJoint.name() + " that is not in bind pose nor is it key framed in the animation, the exported animation will NOT correspond to the animation in Maya"); - } - } - } - } + //MGlobal::displayInfo(MString() + "curve : " + jointAnim.name()); + //MGlobal::displayInfo(MString() + "curve keys : " + jointAnim.numKeys()); + //MGlobal::displayInfo(MString() + "curve keyframes : " + jointAnim.numKeyframes()); + //MGlobal::displayInfo(MString() + "startFrame : " + startFrame); + //MGlobal::displayInfo(MString() + "endFrame : " + endFrame); - jointIt.next(); - } + unsigned int startKeyFrameIndex = jointAnim.findClosest(MTime(startFrame, MTime::kNTSCField), &tmp); - int currentFrame = startFrame; - while (currentFrame != endFrame + 1) { // ANDREAS - Animation::Keyframe thisKeyFrame; - thisKeyFrame.Index = currentFrame - startFrame; - thisKeyFrame.Time = thisKeyFrame.Index * oneDivSixty; + if (tmp == MStatus::kFailure) + MGlobal::displayInfo(MString() + "Fail :c"); - MAnimControl::setCurrentTime(MTime(currentFrame, MTime::kNTSCField)); - MTime time = MAnimControl::currentTime(); + if (startFrame * oneDivSixty <= jointAnim.time(startKeyFrameIndex).value() && jointAnim.time(startKeyFrameIndex).value() <= endFrame * oneDivSixty) { + //MGlobal::displayInfo(MString() + "Start key time : " + jointAnim.time(startKeyFrameIndex).value()); - for (auto aJoint : animatedJoints){ - MFnTransform thisJoint(aJoint); - Animation::Keyframe::JointProperty joint; - auto it = std::find(m_Hierarchy.begin(), m_Hierarchy.end(), thisJoint.object()); - if (it != m_Hierarchy.end()) { - joint.ID = it - m_Hierarchy.begin(); - } - else { - MGlobal::displayError(MString() + "Could not find joint ID for: " + thisJoint.name()); - } - - MTransformationMatrix Matrix = thisJoint.transformation(); - MPlug BindPose = thisJoint.findPlug("bindPose"); - MDataHandle DataHandle; - BindPose.getValue(DataHandle); - MFnMatrixData MartixFn(DataHandle.data()); - MMatrix BindPoseMatrix = MartixFn.matrix(); - Matrix = Matrix.asMatrix(); - + if (startFrame <= jointAnim.time(startKeyFrameIndex).value() && jointAnim.time(startKeyFrameIndex).value() <= endFrame ) { + animatedJoints.push_back(jointIt.item()); + i = 9; + break; + } + + unsigned int endKeyFrameIndex = jointAnim.findClosest(MTime(endFrame, MTime::kNTSCField)); + MGlobal::displayInfo(MString() + startKeyFrameIndex + " " + endKeyFrameIndex); + MGlobal::displayInfo(MString() + "Fail!!!!!!!!!!!!!!!!!!!!!!!!!"); + + if (startFrame * oneDivSixty <= jointAnim.time(endKeyFrameIndex).value() && jointAnim.time(endKeyFrameIndex).value() <= endFrame * oneDivSixty || endKeyFrameIndex - startKeyFrameIndex > 0) { + //MGlobal::displayInfo(MString() + "End key index : " + endKeyFrameIndex); + //MGlobal::displayInfo(MString() + "end key time : " + jointAnim.time(endKeyFrameIndex).value()); + + /*MGlobal::displayInfo(MString() + "start keyfram index: " + startKeyFrameIndex + ". End keyfram index: " + endKeyFrameIndex + ".");*/ + + /*if (startFrame <= jointAnim.time(endKeyFrameIndex).value() && jointAnim.time(endKeyFrameIndex).value() <= endFrame || endKeyFrameIndex - startKeyFrameIndex > 0) { + animatedJoints.push_back(jointIt.item()); + i = 9; + break; + } + + MFnTransform MayaJoint(jointIt.item()); + + MPlug BindPose = MayaJoint.findPlug("bindPose"); + MDataHandle DataHandle; + BindPose.getValue(DataHandle); + MFnMatrixData MartixFn(DataHandle.data()); + MMatrix BindPoseMatrix = MartixFn.matrix(); + + if (!BindPoseMatrix.isEquivalent(MayaJoint.transformationMatrix())) + { + MGlobal::displayError(MString() + animationName.c_str() + " is using " + MayaJoint.name() + " that is not in bind pose nor is it key framed in the animation, the exported animation will NOT correspond to the animation in Maya"); + } + } + } + } + + } // end of int i loop*/ + /* jointIt.next(); + } + jointIt.reset(); + }*/ + + MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint); + unsigned int jointID = 0; + + while (!jointIt.isDone()) { + int currentFrame = startFrame; + Animation::JointAnimation thisJointAnimation; + bool haxBool = false; + while (currentFrame < endFrame) { + Animation::JointAnimation::KeyFrame thisKeyFrame; + //thisKeyFrame.Index = currentFrame - startFrame; + //thisKeyFrame.Time = thisKeyFrame.Index * oneDivSixty; + + MAnimControl::setCurrentTime(MTime(currentFrame, MTime::kNTSCField)); + MTime time = MAnimControl::currentTime(); + + MFnTransform thisJoint(jointIt.currentItem()); + MTransformationMatrix transformationMatrix = thisJoint.transformationMatrix(); + + double doubleMat[4][4]; + + if (currentFrame != startFrame) { + //Animation::JointAnimation joint; + + doubleMat[0][0] = joinCheckMap[thisJoint.name().asChar()][0][0]; + doubleMat[0][1] = joinCheckMap[thisJoint.name().asChar()][0][1]; + doubleMat[0][2] = joinCheckMap[thisJoint.name().asChar()][0][2]; + doubleMat[0][3] = joinCheckMap[thisJoint.name().asChar()][0][3]; + doubleMat[1][0] = joinCheckMap[thisJoint.name().asChar()][1][0]; + doubleMat[1][1] = joinCheckMap[thisJoint.name().asChar()][1][1]; + doubleMat[1][2] = joinCheckMap[thisJoint.name().asChar()][1][2]; + doubleMat[1][3] = joinCheckMap[thisJoint.name().asChar()][1][3]; + doubleMat[2][0] = joinCheckMap[thisJoint.name().asChar()][2][0]; + doubleMat[2][1] = joinCheckMap[thisJoint.name().asChar()][2][1]; + doubleMat[2][2] = joinCheckMap[thisJoint.name().asChar()][2][2]; + doubleMat[2][3] = joinCheckMap[thisJoint.name().asChar()][2][3]; + doubleMat[3][0] = joinCheckMap[thisJoint.name().asChar()][3][0]; + doubleMat[3][1] = joinCheckMap[thisJoint.name().asChar()][3][1]; + doubleMat[3][2] = joinCheckMap[thisJoint.name().asChar()][3][2]; + doubleMat[3][3] = joinCheckMap[thisJoint.name().asChar()][3][3]; + + MMatrix LastJointMatrix(doubleMat); + //Is same as last KeyFrame + if (LastJointMatrix.isEquivalent(transformationMatrix.asMatrix())) { + //jointID++; + //jointIt.next(); + currentFrame++; + haxBool = false; + continue; + } else if(!haxBool){ + haxBool = true; + MTransformationMatrix LastJointTransformationMatrix = LastJointMatrix; + MObject jointOrientObj = thisJoint.attribute("jointOrient"); + MFnNumericAttribute jointOrient(jointOrientObj); + double jointOrientDouble[3]; + jointOrient.getDefault(jointOrientDouble[0], jointOrientDouble[1], jointOrientDouble[2]); + //MGlobal::displayError(MString() + "Joint Matrix: "); + //MGlobal::displayError(MString() + Matrix.asMatrix()[0][0] + " " + Matrix.asMatrix()[0][1] + " " + Matrix.asMatrix()[0][2] + " " + Matrix.asMatrix()[0][3]); + //MGlobal::displayError(MString() + Matrix.asMatrix()[1][0] + " " + Matrix.asMatrix()[1][1] + " " + Matrix.asMatrix()[1][2] + " " + Matrix.asMatrix()[1][3]); + //MGlobal::displayError(MString() + Matrix.asMatrix()[2][0] + " " + Matrix.asMatrix()[2][1] + " " + Matrix.asMatrix()[2][2] + " " + Matrix.asMatrix()[2][3]); + //MGlobal::displayError(MString() + Matrix.asMatrix()[3][0] + " " + Matrix.asMatrix()[3][1] + " " + Matrix.asMatrix()[3][2] + " " + Matrix.asMatrix()[3][3]); + + MEulerRotation joEuler(jointOrientDouble[0], jointOrientDouble[1], jointOrientDouble[2]); + MQuaternion jo = joEuler.asQuaternion(); + + double tmp[4]; + LastJointTransformationMatrix.getRotationQuaternion(tmp[0], tmp[1], tmp[2], tmp[3]); + MQuaternion rotation(tmp); + + rotation = rotation * jo; + rotation.get(tmp); + + //Animation::JointAnimation::KeyFrame keyframe; + Animation::JointAnimation::KeyFrame previousKeyFrame; + previousKeyFrame.Index = currentFrame - startFrame - 1; + previousKeyFrame.Time = previousKeyFrame.Index * oneDivSixty; + + previousKeyFrame.Rotation[0] = tmp[0]; + previousKeyFrame.Rotation[1] = tmp[1]; + previousKeyFrame.Rotation[2] = tmp[2]; + previousKeyFrame.Rotation[3] = tmp[3]; + LastJointTransformationMatrix.getTranslation(MSpace::kTransform).get(tmp); + previousKeyFrame.Position[0] = tmp[0]; + previousKeyFrame.Position[1] = tmp[1]; + previousKeyFrame.Position[2] = tmp[2]; + LastJointTransformationMatrix.getScale(tmp, MSpace::kTransform); + previousKeyFrame.Scale[0] = tmp[0]; + previousKeyFrame.Scale[1] = tmp[1]; + previousKeyFrame.Scale[2] = tmp[2]; + + thisJointAnimation.m_KeyFrames.push_back(previousKeyFrame); + } + } + + transformationMatrix.asMatrix().get(doubleMat); + + //Save transformationMatrix to joinCheckMap + joinCheckMap[thisJoint.name().asChar()][0][0] = doubleMat[0][0]; + joinCheckMap[thisJoint.name().asChar()][0][1] = doubleMat[0][1]; + joinCheckMap[thisJoint.name().asChar()][0][2] = doubleMat[0][2]; + joinCheckMap[thisJoint.name().asChar()][0][3] = doubleMat[0][3]; + joinCheckMap[thisJoint.name().asChar()][1][0] = doubleMat[1][0]; + joinCheckMap[thisJoint.name().asChar()][1][1] = doubleMat[1][1]; + joinCheckMap[thisJoint.name().asChar()][1][2] = doubleMat[1][2]; + joinCheckMap[thisJoint.name().asChar()][1][3] = doubleMat[1][3]; + joinCheckMap[thisJoint.name().asChar()][2][0] = doubleMat[2][0]; + joinCheckMap[thisJoint.name().asChar()][2][1] = doubleMat[2][1]; + joinCheckMap[thisJoint.name().asChar()][2][2] = doubleMat[2][2]; + joinCheckMap[thisJoint.name().asChar()][2][3] = doubleMat[2][3]; + joinCheckMap[thisJoint.name().asChar()][3][0] = doubleMat[3][0]; + joinCheckMap[thisJoint.name().asChar()][3][1] = doubleMat[3][1]; + joinCheckMap[thisJoint.name().asChar()][3][2] = doubleMat[3][2]; + joinCheckMap[thisJoint.name().asChar()][3][3] = doubleMat[3][3]; + + if (currentFrame == startFrame) { + MPlug thisJointBindPose = thisJoint.findPlug("bindPose"); + MDataHandle DataHandle; + thisJointBindPose.getValue(DataHandle); + MFnMatrixData MartixFn(DataHandle.data()); + MMatrix thisJointBindPoseMatrix = MartixFn.matrix(); + + MFnTransform Parent(thisJoint.parent(0), &status); + if (status == MS::kSuccess && thisJoint.parent(0).apiType() == MFn::kJoint) { + MTransformationMatrix Matrix = Parent.transformation(); + MPlug parentBindPose = Parent.findPlug("bindPose"); + MDataHandle DataHandle; + parentBindPose.getValue(DataHandle); + MFnMatrixData MartixFn(DataHandle.data()); + MMatrix parentBindPoseMatrix = MartixFn.matrix(); + + thisJointBindPoseMatrix = thisJointBindPoseMatrix * parentBindPoseMatrix.inverse(); + } + + if (thisJointBindPoseMatrix.isEquivalent(transformationMatrix.asMatrix())) { + //jointID++; + //jointIt.next(); + currentFrame++; + MGlobal::displayError(MString() + thisJoint.name() + " is in bindPose"); + continue; + } + haxBool = true; + } + MObject jointOrientObj = thisJoint.attribute("jointOrient"); MFnNumericAttribute jointOrient(jointOrientObj); double jointOrientDouble[3]; @@ -175,95 +369,97 @@ Animation Skeleton::GetAnimData(std::string animationName, int startFrame, int e MEulerRotation joEuler(jointOrientDouble[0], jointOrientDouble[1], jointOrientDouble[2]); MQuaternion jo = joEuler.asQuaternion(); - double tmp[4]; - Matrix.getRotationQuaternion(tmp[0], tmp[1], tmp[2], tmp[3]); + double tmp[4]; + transformationMatrix.getRotationQuaternion(tmp[0], tmp[1], tmp[2], tmp[3]); MQuaternion rotation(tmp); rotation = rotation * jo; rotation.get(tmp); - joint.Rotation[0] = tmp[0]; - joint.Rotation[1] = tmp[1]; - joint.Rotation[2] = tmp[2]; - joint.Rotation[3] = tmp[3]; - Matrix.getTranslation(MSpace::kTransform).get(tmp); - joint.Position[0] = tmp[0]; - joint.Position[1] = tmp[1]; - joint.Position[2] = tmp[2]; - Matrix.getScale(tmp, MSpace::kTransform); - joint.Scale[0] = tmp[0]; - joint.Scale[1] = tmp[1]; - joint.Scale[2] = tmp[2]; + //Animation::JointAnimation::KeyFrame keyframe; + thisKeyFrame.Index = currentFrame - startFrame; + thisKeyFrame.Time = thisKeyFrame.Index * oneDivSixty; - thisKeyFrame.JointProperties.push_back(joint); - } - returnData.Keyframes.push_back(thisKeyFrame); - currentFrame++; - } + thisKeyFrame.Rotation[0] = tmp[0]; + thisKeyFrame.Rotation[1] = tmp[1]; + thisKeyFrame.Rotation[2] = tmp[2]; + thisKeyFrame.Rotation[3] = tmp[3]; + transformationMatrix.getTranslation(MSpace::kTransform).get(tmp); + thisKeyFrame.Position[0] = tmp[0]; + thisKeyFrame.Position[1] = tmp[1]; + thisKeyFrame.Position[2] = tmp[2]; + transformationMatrix.getScale(tmp, MSpace::kTransform); + thisKeyFrame.Scale[0] = tmp[0]; + thisKeyFrame.Scale[1] = tmp[1]; + thisKeyFrame.Scale[2] = tmp[2]; - returnData.NumKeyFrames = returnData.Keyframes.size(); - returnData.NumberOfJoints = animatedJoints.size(); + thisJointAnimation.m_KeyFrames.push_back(thisKeyFrame); - return returnData; + currentFrame++; + } + //thisKeyFrame.NumberOfJoints = thisKeyFrame.JointProperties.size(); + thisJointAnimation.numberOFKeyFrames = thisJointAnimation.m_KeyFrames.size(); + returnData.JointsFrameMap[jointID] = (thisJointAnimation); + + jointID++; + jointIt.next(); + } + returnData.NumOfJointFrames = returnData.JointsFrameMap.size(); + return returnData; } std::vector Skeleton::GetBindPoses() { MStatus status; - std::vector m_AllSkeletons; - std::vector m_Hierarchy; + std::vector m_AllSkeletons; + std::vector m_Hierarchy; - MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint); - BindPoseSkeletonNode SkeletonStorage; - while (!jointIt.isDone()) { - MFnTransform MayaJoint(jointIt.currentItem()); - BindPoseSkeletonNode::BindPoseJoint NewJoint; + MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint); + BindPoseSkeletonNode SkeletonStorage; + while (!jointIt.isDone()) { + MFnTransform MayaJoint(jointIt.currentItem()); + BindPoseSkeletonNode::BindPoseJoint NewJoint; - if (MFnDependencyNode(MayaJoint.parent(0)).name() == "world") { - if (SkeletonStorage.Joints.size() != 0) { - m_AllSkeletons.push_back(SkeletonStorage); + if (MFnDependencyNode(MayaJoint.parent(0)).object().apiType() != MFn::kJoint) { + if (SkeletonStorage.Joints.size() != 0) { + m_AllSkeletons.push_back(SkeletonStorage); - SkeletonStorage.Joints.clear(); - SkeletonStorage.Name.clear(); - } - SkeletonStorage.Name = std::string(MayaJoint.name().asChar()); - NewJoint.ParentID = -1; // This joint is root - } - else { - auto it = std::find(m_Hierarchy.begin(), m_Hierarchy.end(), MayaJoint.parent(0)); - if (it != m_Hierarchy.end()) { - NewJoint.ParentID = it - m_Hierarchy.begin(); - } - else { - MGlobal::displayError(MString() + "Could not find joint parent for: " + MayaJoint.name()); - } - } - m_Hierarchy.push_back(MayaJoint.object()); + SkeletonStorage.Joints.clear(); + SkeletonStorage.Name.clear(); + } + SkeletonStorage.Name = std::string(MayaJoint.name().asChar()); + NewJoint.ParentID = -1; // This joint is root + } else { + auto it = std::find(m_Hierarchy.begin(), m_Hierarchy.end(), MayaJoint.parent(0)); + if (it != m_Hierarchy.end()) { + NewJoint.ParentID = it - m_Hierarchy.begin(); + } else { + MGlobal::displayError(MString() + "Could not find joint parent for: " + MayaJoint.name()); + } + } + m_Hierarchy.push_back(MayaJoint.object()); - MPlug BindPose = MayaJoint.findPlug("bindPose", &status); - if (status != MS::kSuccess) { + MPlug BindPose = MayaJoint.findPlug("bindPose", &status); + if (status != MS::kSuccess) { MGlobal::displayError(MString() + "Could not find bindPose plug: " + status.errorString()); } - MDataHandle DataHandle; - BindPose.getValue(DataHandle); - MFnMatrixData MartixFn(DataHandle.data()); - MMatrix Matrix = MartixFn.matrix(); + MDataHandle DataHandle; + BindPose.getValue(DataHandle); + MFnMatrixData MartixFn(DataHandle.data()); + MMatrix Matrix = MartixFn.matrix(); MVector tmp = MayaJoint.transformation().getTranslation(MSpace::kObject); - MGlobal::displayError(MString() + "translation befor: " + tmp[0] + " " + tmp[1] + " " + tmp[2]); //Matrix[3][0] *= -1; //Matrix[3][2] *= -1; //Matrix[3][1] *= -1; double test[3]; MayaJoint.transformation().getScale(test, MSpace::kObject); - MGlobal::displayError(MString() + "scale: " + test[0] + " " + test[1] + " " + test[2]); MTransformationMatrix::RotationOrder order = MTransformationMatrix::RotationOrder::kXYZ; MayaJoint.transformation().getRotation(test, order); - MGlobal::displayError(MString() + "rotation: " + test[0] + " " + test[1] + " " + test[2]); - + //----- test @@ -310,33 +506,33 @@ std::vector Skeleton::GetBindPoses() Matrix = Matrix.inverse(); - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - NewJoint.OffsetMatrix[i][j] = Matrix.matrix[i][j]; - } - } + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + NewJoint.OffsetMatrix[i][j] = Matrix.matrix[i][j]; + } + } - NewJoint.Name = MayaJoint.name().asChar(); + NewJoint.Name = MayaJoint.name().asChar(); NewJoint.NameLength = MayaJoint.name().length() + 1; NewJoint.ID = SkeletonStorage.Joints.size(); - //double tmp[3]; - //((MTransformationMatrix)Matrix).eulerRotation().asVector().get(tmp); - //NewJoint.Rotation[0] = tmp[0]; - //NewJoint.Rotation[1] = tmp[1]; - //NewJoint.Rotation[2] = tmp[2]; - //((MTransformationMatrix)Matrix).getScale(tmp, MSpace::Space::kTransform); - //NewJoint.Scale[0] = tmp[0]; - //NewJoint.Scale[1] = tmp[1]; - //NewJoint.Scale[2] = tmp[2]; - //((MTransformationMatrix)Matrix).getTranslation(MSpace::Space::kTransform).get(tmp); - //NewJoint.Translation[0] = tmp[0]; - //NewJoint.Translation[1] = tmp[1]; - //NewJoint.Translation[2] = tmp[2]; - SkeletonStorage.Joints.push_back(NewJoint); + //double tmp[3]; + //((MTransformationMatrix)Matrix).eulerRotation().asVector().get(tmp); + //NewJoint.Rotation[0] = tmp[0]; + //NewJoint.Rotation[1] = tmp[1]; + //NewJoint.Rotation[2] = tmp[2]; + //((MTransformationMatrix)Matrix).getScale(tmp, MSpace::Space::kTransform); + //NewJoint.Scale[0] = tmp[0]; + //NewJoint.Scale[1] = tmp[1]; + //NewJoint.Scale[2] = tmp[2]; + //((MTransformationMatrix)Matrix).getTranslation(MSpace::Space::kTransform).get(tmp); + //NewJoint.Translation[0] = tmp[0]; + //NewJoint.Translation[1] = tmp[1]; + //NewJoint.Translation[2] = tmp[2]; + SkeletonStorage.Joints.push_back(NewJoint); SkeletonStorage.numBones++; - jointIt.next(); - } - m_AllSkeletons.push_back(SkeletonStorage); + jointIt.next(); + } + m_AllSkeletons.push_back(SkeletonStorage); - return m_AllSkeletons; + return m_AllSkeletons; } \ No newline at end of file diff --git a/tools/MayaExporter/MayaExporter/Skeleton.h b/tools/MayaExporter/MayaExporter/Skeleton.h index 6a288c8a..3dfbe8a5 100644 --- a/tools/MayaExporter/MayaExporter/Skeleton.h +++ b/tools/MayaExporter/MayaExporter/Skeleton.h @@ -3,50 +3,63 @@ #include #include +#include #include #include "MayaIncludes.h" #include "OutputData.h" class Animation : public OutputData { public: - struct Keyframe - { - struct JointProperty - { - int ID = 0; + //struct Keyframe + //{ + // struct JointProperty + // { + // int ID = 0; + // float Position[3]{ 0 }; + // float Rotation[4]{ 0 }; + // float Scale[3]{ 0 }; + // }; + + // int Index = 0; + // float Time = 0; + // int NumberOfJoints; + // std::vector JointProperties; + //}; + + struct JointAnimation { + struct KeyFrame { + int Index = 0; + float Time = 0; float Position[3]{ 0 }; float Rotation[4]{ 0 }; float Scale[3]{ 0 }; - }; - - int Index = 0; - float Time = 0; - std::vector JointProperties; - }; + }; + unsigned int numberOFKeyFrames = 0; + std::vector m_KeyFrames; + }; std::string Name; int nameLength = 0; float Duration = 0; - int NumKeyFrames = 0; - int NumberOfJoints = 0; - std::vector Keyframes; + int NumOfJointFrames = 0; + std::map JointsFrameMap; virtual void WriteBinary(std::ostream& out) { out.write((char*)&nameLength, sizeof(int)); out.write(Name.c_str(), Name.size() + 1); out.write((char*)&Duration, sizeof(float)); - out.write((char*)&NumKeyFrames, sizeof(int)); - out.write((char*)&NumberOfJoints, sizeof(int)); + out.write((char*)&NumOfJointFrames, sizeof(int)); //Här under loopas alla key frames igenom - for (auto aKeyframe : Keyframes) { - out.write((char*)&aKeyframe.Index, sizeof(int)); - out.write((char*)&aKeyframe.Time, sizeof(float)); - for (auto aJoint : aKeyframe.JointProperties) { - out.write((char*)&aJoint.ID, sizeof(int)); - out.write((char*)aJoint.Position, sizeof(float) * 3); - out.write((char*)aJoint.Rotation, sizeof(float) * 4); - out.write((char*)aJoint.Scale, sizeof(float) * 3); + for (auto aJointAnimation : JointsFrameMap) { + out.write((char*)&aJointAnimation.first, sizeof(int)); + out.write((char*)&aJointAnimation.second.numberOFKeyFrames, sizeof(int)); + for (auto aJointKeyFrame : aJointAnimation.second.m_KeyFrames) { + out.write((char*)&aJointKeyFrame.Index, sizeof(int)); + out.write((char*)&aJointKeyFrame.Time, sizeof(float)); + out.write((char*)&aJointKeyFrame.Position, sizeof(float) * 3); + out.write((char*)&aJointKeyFrame.Rotation, sizeof(float) * 4); + out.write((char*)&aJointKeyFrame.Scale, sizeof(float) * 3); } } } @@ -55,16 +68,17 @@ public: { out << "Animation Name: " << Name << endl; out << "Duration: " << Duration << endl; - out << "Number of KeyFrames: " << NumKeyFrames << endl; - out << "Number of Joints: " << NumberOfJoints << endl; - for (auto aKeyframe : Keyframes) { - out << "Frame: " << aKeyframe.Index << endl; - out << "Time: " << aKeyframe.Time << endl; - for (auto aJoint : aKeyframe.JointProperties) { - out << "Joint ID: " << aJoint.ID << endl; - out << aJoint.Position[0] << " " << aJoint.Position[1] << " " << aJoint.Position[2] << endl; - out << aJoint.Rotation[0] << " " << aJoint.Rotation[1] << " " << aJoint.Rotation[2] << " " << aJoint.Rotation[3] << endl; - out << aJoint.Scale[0] << " " << aJoint.Scale[1] << " " << aJoint.Scale[2] << endl; + out << "Number of KeyFrames: " << NumOfJointFrames << endl; + for (auto aJointAnimation : JointsFrameMap) { + out << "Bone: " << aJointAnimation.first << endl; + //out << "Time: " << aJointAnimation.Time << endl; + //out << "Number of Joints: " << aKeyframe.NumberOfJoints << endl; + for (auto aJointKeyFrame : aJointAnimation.second.m_KeyFrames) { + //out << "Joint ID: " << aJoint.ID << endl; + out << "Time: " << aJointKeyFrame.Time << endl; + out << aJointKeyFrame.Position[0] << " " << aJointKeyFrame.Position[1] << " " << aJointKeyFrame.Position[2] << endl; + out << aJointKeyFrame.Rotation[0] << " " << aJointKeyFrame.Rotation[1] << " " << aJointKeyFrame.Rotation[2] << " " << aJointKeyFrame.Rotation[3] << endl; + out << aJointKeyFrame.Scale[0] << " " << aJointKeyFrame.Scale[1] << " " << aJointKeyFrame.Scale[2] << endl; } }