diff --git a/assets b/assets index 672e8a2..15ac025 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 672e8a2b11ecaafc95a5b0286b5ec310c62438ad +Subproject commit 15ac02523ad374b4aaf60a16db89b1934de7f303 diff --git a/src/Component.h b/src/Component.h index 21d59f6..05e0628 100755 --- a/src/Component.h +++ b/src/Component.h @@ -7,6 +7,8 @@ struct Component { EntityID Entity; + + virtual Component* Clone() const = 0; }; class ComponentFactory : public Factory { }; diff --git a/src/Components/BarrelSteering.h b/src/Components/BarrelSteering.h new file mode 100644 index 0000000..1cd71be --- /dev/null +++ b/src/Components/BarrelSteering.h @@ -0,0 +1,23 @@ +#ifndef BarrelSteering_h__ +#define BarrelSteering_h__ + +#include "Component.h" + +namespace Components +{ + + struct BarrelSteering : Component + { + BarrelSteering() + : TurnSpeed(1.f), Axis(glm::vec3(0,1,0)){ } + float TurnSpeed; + glm::vec3 Axis; + EntityID ShotTemplate; + float ShotSpeed; + + virtual BarrelSteering* Clone() const override { return new BarrelSteering(*this); } + }; + +} + +#endif // BarrelSteering_h__ \ No newline at end of file diff --git a/src/Components/Box.h b/src/Components/BoxShape.h similarity index 66% rename from src/Components/Box.h rename to src/Components/BoxShape.h index b9ddea7..a8aed66 100644 --- a/src/Components/Box.h +++ b/src/Components/BoxShape.h @@ -6,14 +6,16 @@ namespace Components { -struct Box : Component +struct BoxShape : Component { - Box() + BoxShape() : Width(1.f), Height(1.f), Depth(1.f){ } float Width; float Height; float Depth; + + virtual BoxShape* Clone() const override { return new BoxShape(*this); } }; } diff --git a/src/Components/Camera.h b/src/Components/Camera.h index d30c537..fb3f7ef 100755 --- a/src/Components/Camera.h +++ b/src/Components/Camera.h @@ -17,6 +17,8 @@ struct Camera : Component float FOV; float NearClip; float FarClip; + + virtual Camera* Clone() const override { return new Camera(*this); } }; } diff --git a/src/Components/DirectionalLight.h b/src/Components/DirectionalLight.h index ee2dd72..1d7de1e 100755 --- a/src/Components/DirectionalLight.h +++ b/src/Components/DirectionalLight.h @@ -13,6 +13,8 @@ struct DirectionalLight : Component float MaxRange; float SpecularIntensity; Color Color; + + virtual DirectionalLight* Clone() const override { return new DirectionalLight(*this); } }; } diff --git a/src/Components/ExtendedMeshShape.h b/src/Components/ExtendedMeshShape.h new file mode 100644 index 0000000..e69de29 diff --git a/src/Components/FreeSteering.h b/src/Components/FreeSteering.h index a972eaf..ba40534 100755 --- a/src/Components/FreeSteering.h +++ b/src/Components/FreeSteering.h @@ -9,6 +9,8 @@ struct FreeSteering : Component { FreeSteering() : Speed(35) { } float Speed; + + virtual FreeSteering* Clone() const override { return new FreeSteering(*this); } }; } diff --git a/src/Components/HingeConstraint.h b/src/Components/HingeConstraint.h new file mode 100644 index 0000000..367d73a --- /dev/null +++ b/src/Components/HingeConstraint.h @@ -0,0 +1,20 @@ +#ifndef Components_HingeConstraint_h__ +#define Components_HingeConstraint_h__ + +#include "Component.h" + +namespace Components +{ + + struct HingeConstraint : Component + { + EntityID LinkedEntity; + glm::vec3 Pivot; + glm::vec3 Axis; + + virtual HingeConstraint* Clone() const override { return new HingeConstraint(*this); } + }; + +} + +#endif // Components_HingeConstraint_h__ diff --git a/src/Components/Input.h b/src/Components/Input.h index b1c11b5..15cb286 100755 --- a/src/Components/Input.h +++ b/src/Components/Input.h @@ -18,6 +18,8 @@ struct Input : Component std::array LastMouseState; float dX, dY; float WheelDelta; + + virtual Input* Clone() const override { return new Input(*this); } }; } diff --git a/src/Components/MeshShape.h b/src/Components/MeshShape.h new file mode 100644 index 0000000..81ea9c0 --- /dev/null +++ b/src/Components/MeshShape.h @@ -0,0 +1,19 @@ +#ifndef Components_MeshShape_h__ +#define Components_MeshShape_h__ + +#include + +#include "Component.h" + +namespace Components +{ + +struct MeshShape : Component +{ + std::string ResourceName; + + virtual MeshShape* Clone() const override { return new MeshShape(*this); } +}; + +} +#endif // !Components_MeshShape_h__ \ No newline at end of file diff --git a/src/Components/Model.h b/src/Components/Model.h index ad3b4f3..cacfe17 100755 --- a/src/Components/Model.h +++ b/src/Components/Model.h @@ -16,6 +16,8 @@ struct Model : Component Color Color; bool Visible; bool ShadowCaster; + + virtual Model* Clone() const override { return new Model(*this); } }; } diff --git a/src/Components/Particle.h b/src/Components/Particle.h new file mode 100644 index 0000000..d08b1a7 --- /dev/null +++ b/src/Components/Particle.h @@ -0,0 +1,25 @@ +#ifndef Components_Particle_h__ +#define Components_Particle_h__ + +#include "System.h" +#include "Component.h" +#include "Color.h" +#include + +namespace Components +{ + + struct Particle : Component + { + std::vector ColorSpectrum; + std::vector ScaleSpectrum; + double LifeTime; + std::vector VelocitySpectrum; + std::vector AngularVelocitySpectrum; + std::vector OrientationSpectrum; //Keep? + + virtual Particle* Clone() const override { return new Particle(*this); } + }; + +} +#endif // !Components_Particle_h__ \ No newline at end of file diff --git a/src/Components/ParticleEmitter.h b/src/Components/ParticleEmitter.h index 06a1658..bb57c99 100755 --- a/src/Components/ParticleEmitter.h +++ b/src/Components/ParticleEmitter.h @@ -5,20 +5,39 @@ #include "Color.h" #include +namespace Systems { class ParticleSystem; } + namespace Components { struct ParticleEmitter : Component { - int ParticleTemplate; + friend class Systems::ParticleSystem; + + ParticleEmitter() + : SpawnFrequency(0) + , SpawnCount(0) + , SpreadAngle(0) + , LifeTime(0) + , TimeSinceLastSpawn(0) { } + + EntityID ParticleTemplate; float SpawnFrequency; + float Speed; int SpawnCount; std::vector ColorSpectrum; - std::vector ScaleSpectrum; + std::vector ScaleSpectrum; float SpreadAngle; - float LifeTime; - std::vector VelocitySpectrum; - std::vector AngularVelocitySpectrum; + double LifeTime; + bool UseGoalVelocity; + glm::vec3 GoalVelocity; + std::vector AngularVelocitySpectrum; + std::vector OrientationSpectrum; //Keep? + + virtual ParticleEmitter* Clone() const override { return new ParticleEmitter(*this); } + +private: + double TimeSinceLastSpawn; }; } diff --git a/src/Components/Physics.h b/src/Components/Physics.h index df819c4..35844b5 100644 --- a/src/Components/Physics.h +++ b/src/Components/Physics.h @@ -13,6 +13,8 @@ struct Physics : Component float Mass; bool Static; + + virtual Physics* Clone() const override { return new Physics(*this); } }; } diff --git a/src/Components/PointLight.h b/src/Components/PointLight.h index a7a5d4a..9037b89 100755 --- a/src/Components/PointLight.h +++ b/src/Components/PointLight.h @@ -9,13 +9,24 @@ namespace Components struct PointLight : Component { - float Intensity; - float MaxRange; + PointLight() + : Specular(1.0f, 1.0f, 1.0f) + , Diffuse(1.0f, 1.0f, 1.0f) + , specularExponent(50.0f) + , ConstantAttenuation(1.0f) + , LinearAttenuation(0.f) + , QuadraticAttenuation(3.f) + { } + + float ConstantAttenuation, LinearAttenuation, QuadraticAttenuation; + Color color; + glm::vec3 Specular; glm::vec3 Diffuse; - float constantAttenuation, linearAttenuation, quadraticAttenuation; - float spotExponent; - Color color; + float specularExponent; + float Scale; + + virtual PointLight* Clone() const override { return new PointLight(*this); } }; } diff --git a/src/Components/SoundEmitter.h b/src/Components/SoundEmitter.h index b4c74ee..05c5f15 100755 --- a/src/Components/SoundEmitter.h +++ b/src/Components/SoundEmitter.h @@ -17,6 +17,8 @@ struct SoundEmitter : Component float Pitch; bool Loop; std::string Path; + + virtual SoundEmitter* Clone() const override { return new SoundEmitter(*this); } }; } diff --git a/src/Components/Sphere.h b/src/Components/SphereShape.h similarity index 59% rename from src/Components/Sphere.h rename to src/Components/SphereShape.h index 2d089dd..20ab74d 100644 --- a/src/Components/Sphere.h +++ b/src/Components/SphereShape.h @@ -6,12 +6,14 @@ namespace Components { -struct Sphere : Component +struct SphereShape : Component { - Sphere() + SphereShape() : Radius(1.f){ } float Radius; + + virtual SphereShape* Clone() const override { return new SphereShape(*this); } }; } diff --git a/src/Components/Sprite.h b/src/Components/Sprite.h index f54d3d0..29c930f 100755 --- a/src/Components/Sprite.h +++ b/src/Components/Sprite.h @@ -13,6 +13,8 @@ struct Sprite : Component { std::string SpriteFile; Color Color; + + virtual Sprite* Clone() const override { return new Sprite(*this); } }; } diff --git a/src/Components/TankSteering.h b/src/Components/TankSteering.h new file mode 100644 index 0000000..c9184b3 --- /dev/null +++ b/src/Components/TankSteering.h @@ -0,0 +1,14 @@ +#ifndef TankSteering_h__ +#define TankSteering_h__ + +#include "Component.h" + +namespace Components +{ + struct TankSteering : Component + { + TankSteering* Clone() const override { return new TankSteering(*this); } + }; +} + +#endif // TankSteering_h__ \ No newline at end of file diff --git a/src/Components/Template.h b/src/Components/Template.h index 4bcb25c..613622c 100755 --- a/src/Components/Template.h +++ b/src/Components/Template.h @@ -6,7 +6,12 @@ namespace Components { -struct Template : Component { }; +struct Template + : public Component +{ + virtual Template* Clone() const override { return nullptr; } +}; } + #endif // !Components_Template_h__ \ No newline at end of file diff --git a/src/Components/TowerSteering.h b/src/Components/TowerSteering.h new file mode 100644 index 0000000..f4f72b9 --- /dev/null +++ b/src/Components/TowerSteering.h @@ -0,0 +1,21 @@ +#ifndef TowerSteering_h__ +#define TowerSteering_h__ + +#include "Component.h" + + namespace Components +{ + +struct TowerSteering : Component +{ + TowerSteering() + : TurnSpeed(1.f), Axis(glm::vec3(0,1,0)){ } + + float TurnSpeed; + glm::vec3 Axis; + virtual TowerSteering* Clone() const override { return new TowerSteering(*this); } +}; + +} + +#endif // TowerSteering_h__ \ No newline at end of file diff --git a/src/Components/Transform.h b/src/Components/Transform.h index 2bfd58d..26b701e 100755 --- a/src/Components/Transform.h +++ b/src/Components/Transform.h @@ -6,7 +6,7 @@ namespace Components { -struct Transform : Component +struct Transform : public Component { Transform() : Scale(glm::vec3(1.f)) { } @@ -15,6 +15,8 @@ struct Transform : Component glm::quat Orientation; glm::vec3 Velocity; glm::vec3 Scale; + + virtual Transform* Clone() const override { return new Transform(*this); } }; } diff --git a/src/Components/Vehicle.h b/src/Components/Vehicle.h index e61c713..2957df5 100644 --- a/src/Components/Vehicle.h +++ b/src/Components/Vehicle.h @@ -10,7 +10,8 @@ namespace Components struct Vehicle : Component { Vehicle() - : MaxTorque(500.0f), MinRPM(1000.0f), OptimalRPM(5500.0f), MaxRPM(7500.0f), MaxSteeringAngle(35), TopSpeed(50.0f) { } + : MaxTorque(1000.0f), MinRPM(1000.0f), OptimalRPM(3000.0f), MaxRPM(4000.0f), MaxSteeringAngle(35), TopSpeed(130.0f), + MaxSpeedFullSteeringAngle(40.0f), SpringDamping(1.f){ } float MaxTorque; float MinRPM; @@ -18,7 +19,12 @@ struct Vehicle : Component float MaxRPM; // Degrees float MaxSteeringAngle; + //TopSpeed not working fully yet float TopSpeed; + float MaxSpeedFullSteeringAngle; + float SpringDamping; + + Vehicle* Clone() const override { return new Vehicle(*this); } }; } diff --git a/src/Components/Wheel.h b/src/Components/Wheel.h index d4917db..be3638b 100644 --- a/src/Components/Wheel.h +++ b/src/Components/Wheel.h @@ -14,7 +14,7 @@ struct Wheel : Component Wheel() : AxleID(0), Radius(0), Width(0), Mass(0), Steering(false), DownDirection(glm::vec3(0, -1, 0)), Friction(1.5f), SlipAngle(0.0f), - MaxBreakingTorque(1500.0f), ConnectedToHandbrake(false), SuspensionStrength(50.0f) { } + MaxBreakingTorque(1500.0f), ConnectedToHandbrake(false), SuspensionStrength(50.0f), TorqueRatio(0.25f) { } // The Hardpoint MUST be positioned INSIDE the chassis. glm::vec3 Hardpoint; @@ -30,10 +30,14 @@ struct Wheel : Component float SlipAngle; float MaxBreakingTorque; bool ConnectedToHandbrake; + // The wheels total TorqueRatio must be equal to 1 + float TorqueRatio; private: int ID; glm::quat OriginalOrientation; + + Wheel* Clone() const override { return new Wheel(*this); } }; } diff --git a/src/Components/WheelPair.h b/src/Components/WheelPair.h new file mode 100644 index 0000000..4e74a82 --- /dev/null +++ b/src/Components/WheelPair.h @@ -0,0 +1,18 @@ +#ifndef Components_WheelPair_h__ +#define Components_WheelPair_h__ + +#include "Component.h" + +namespace Components +{ + + struct WheelPair : Component + { + // Flag for pair wheels + + virtual WheelPair* Clone() const override { return new WheelPair(*this); } + }; + +} + +#endif // Components_WheelPair_h__ diff --git a/src/Engine.h b/src/Engine.h index 25337c4..c063960 100755 --- a/src/Engine.h +++ b/src/Engine.h @@ -19,7 +19,7 @@ public: m_InputManager = std::make_shared(m_Renderer->GetWindow(), m_EventBroker); - m_UIParent = std::make_shared(m_EventBroker); + //m_UIParent = std::make_shared(m_EventBroker); m_World = std::make_shared(m_EventBroker, m_Renderer); m_World->Initialize(); @@ -46,7 +46,7 @@ private: std::shared_ptr m_EventBroker; std::shared_ptr m_Renderer; std::shared_ptr m_InputManager; - std::shared_ptr m_UIParent; + //std::shared_ptr m_UIParent; // TODO: This should ultimately live in GameFrame std::shared_ptr m_World; diff --git a/src/Events/BindGamepadAxis.h b/src/Events/BindGamepadAxis.h new file mode 100644 index 0000000..b1e16f8 --- /dev/null +++ b/src/Events/BindGamepadAxis.h @@ -0,0 +1,21 @@ +#ifndef Events_BindGamepadAxis_h__ +#define Events_BindGamepadAxis_h__ + +#include + +#include "EventBroker.h" +#include "Events/GamepadAxis.h" + +namespace Events +{ + +struct BindGamepadAxis : Event +{ + Gamepad::Axis Axis; + std::string Command; + float Value; +}; + +} + +#endif // Events_BindGamepadAxis_h__ \ No newline at end of file diff --git a/src/Events/BindGamepadButton.h b/src/Events/BindGamepadButton.h new file mode 100644 index 0000000..72641d8 --- /dev/null +++ b/src/Events/BindGamepadButton.h @@ -0,0 +1,21 @@ +#ifndef Events_BindGamepadButton_h__ +#define Events_BindGamepadButton_h__ + +#include + +#include "EventBroker.h" +#include "Events/GamepadButton.h" + +namespace Events +{ + +struct BindGamepadButton : Event +{ + Gamepad::Button Button; + std::string Command; + float Value; +}; + +} + +#endif // Events_BindGamepadButton_h__ \ No newline at end of file diff --git a/src/Events/BindKey.h b/src/Events/BindKey.h index a774942..17c786f 100644 --- a/src/Events/BindKey.h +++ b/src/Events/BindKey.h @@ -1,6 +1,8 @@ #ifndef Events_BindKey_h__ #define Events_BindKey_h__ +#include + #include "EventBroker.h" namespace Events @@ -10,6 +12,7 @@ struct BindKey : Event { int KeyCode; std::string Command; + float Value; }; } diff --git a/src/Events/GamepadAxis.h b/src/Events/GamepadAxis.h new file mode 100644 index 0000000..3d47767 --- /dev/null +++ b/src/Events/GamepadAxis.h @@ -0,0 +1,32 @@ +#ifndef Events_GamepadAxis_h__ +#define Events_GamepadAxis_h__ + +#include "EventBroker.h" + +namespace Gamepad +{ + enum class Axis + { + LeftX, + LeftY, + RightX, + RightY, + LeftTrigger, + RightTrigger, + LAST = RightTrigger + }; +} + +namespace Events +{ + +struct GamepadAxis : Event +{ + int GamepadID; + Gamepad::Axis Axis; + float Value; +}; + +} + +#endif // Events_GamepadAxis_h__ \ No newline at end of file diff --git a/src/Events/GamepadButton.h b/src/Events/GamepadButton.h new file mode 100644 index 0000000..a99583c --- /dev/null +++ b/src/Events/GamepadButton.h @@ -0,0 +1,45 @@ +#ifndef Events_GamepadButton_h__ +#define Events_GamepadButton_h__ + +#include "EventBroker.h" + +namespace Gamepad +{ + enum class Button + { + Up, + Down, + Left, + Right, + Start, + Back, + LeftThumb, + RightThumb, + LeftShoulder, + RightShoulder, + A, + B, + X, + Y, + LAST = Y + }; +} + +namespace Events +{ + +struct GamepadButtonDown : Event +{ + int GamepadID; + Gamepad::Button Button; +}; + +struct GamepadButtonUp : Event +{ + int GamepadID; + Gamepad::Button Button; +}; + +} + +#endif // Events_GamepadButton_h__ \ No newline at end of file diff --git a/src/Events/InputCommand.h b/src/Events/InputCommand.h index bd18f6a..cde1dab 100644 --- a/src/Events/InputCommand.h +++ b/src/Events/InputCommand.h @@ -12,7 +12,7 @@ struct InputCommand : Event { unsigned int PlayerID; std::string Command; - boost::any Value; + float Value; }; } diff --git a/src/Events/SetVelocity.h b/src/Events/SetVelocity.h new file mode 100644 index 0000000..3bdb8a1 --- /dev/null +++ b/src/Events/SetVelocity.h @@ -0,0 +1,17 @@ +#ifndef Events_SetVelocity_h__ +#define Events_SetVelocity_h__ +#include "Entity.h" +#include "EventBroker.h" + +namespace Events +{ + + struct SetVelocity : Event + { + EntityID Entity; + glm::vec3 Velocity; + }; + +} + +#endif // Events_SetVelocity_h__ \ No newline at end of file diff --git a/src/Events/TankSteer.h b/src/Events/TankSteer.h new file mode 100644 index 0000000..3ee6dc9 --- /dev/null +++ b/src/Events/TankSteer.h @@ -0,0 +1,19 @@ +#ifndef Events_TankSteer_h__ +#define Events_TankSteer_h__ +#include "Entity.h" +#include "EventBroker.h" + +namespace Events +{ + +struct TankSteer : Event +{ + EntityID Entity; + float PositionX; + float PositionY; + bool Handbrake; +}; + +} + +#endif // Events_TankSteer_h__ \ No newline at end of file diff --git a/src/GUI/Frame.h b/src/GUI/Frame.h index 76bf98b..d587bbe 100644 --- a/src/GUI/Frame.h +++ b/src/GUI/Frame.h @@ -1,76 +1,75 @@ -#ifndef GUI_Frame_h__ -#define GUI_Frame_h__ - -#include - -#include "Util/Rectangle.h" -#include "EventBroker.h" - -// HACK: Decouple renderer plz -#include "Renderer.h" - -namespace GUI -{ - -class Frame : public Rectangle -{ -public: - enum class Anchor - { - Left, - Right, - Top, - Bottom - }; - - // Set up a base frame with an event broker - Frame(std::shared_ptr<::EventBroker> eventBroker) - : EventBroker(eventBroker) - , Rectangle() - { Initialize(); } - // Create a frame as a child - Frame(std::shared_ptr parent) - : Rectangle(static_cast(*parent)) // Clone parent rectangle using copy constructor - { SetParent(parent); Initialize(); } - - virtual void Initialize() { } - - std::shared_ptr Parent() const { return m_Parent; } - void SetParent(std::shared_ptr parent) - { - parent->AddChild(std::shared_ptr(this)); - m_Parent = parent; - EventBroker = parent->EventBroker; - } - - void AddChild(std::shared_ptr child) - { - m_Children.push_back(child); - if (m_Parent != nullptr) - { - m_Parent->AddChild(child); - } - } - - typedef std::list>::const_iterator FrameChildrenIterator; - FrameChildrenIterator begin() - { - return m_Children.begin(); - } - FrameChildrenIterator end() - { - return m_Children.end(); - } - - virtual void Update(double dt) { } - virtual void Draw(Renderer* renderer) { } - -protected: - std::shared_ptr<::EventBroker> EventBroker; - std::shared_ptr m_Parent; - std::list> m_Children; -}; - -} - -#endif // GUI_Frame_h__ +//#ifndef GUI_Frame_h__ +//#define GUI_Frame_h__ +// +//#include +// +//#include "Util/Rectangle.h" +//#include "EventBroker.h" +// +//// HACK: Decouple renderer plz +//#include "Renderer.h" +// +//namespace GUI +//{ +// +//class Frame : public Rectangle +//{ +//public: +// enum class Anchor +// { +// Left, +// Right, +// Top, +// Bottom +// }; +// +// // Set up a base frame with an event broker +// Frame(std::shared_ptr<::EventBroker> eventBroker) +// : EventBroker(eventBroker) +// , Rectangle() +// { Initialize(); } +// // Create a frame as a child +// Frame(std::shared_ptr parent) +// : Rectangle(static_cast(*parent)) // Clone parent rectangle using copy constructor +// { SetParent(parent); Initialize(); } +// +// virtual void Initialize() { } +// std::shared_ptr Parent() const { return m_Parent; } +// void SetParent(std::shared_ptr parent) +// { +// parent->AddChild(std::shared_ptr(this)); +// m_Parent = parent; +// EventBroker = parent->EventBroker; +// } +// +// void AddChild(std::shared_ptr child) +// { +// m_Children.push_back(child); +// if (m_Parent != nullptr) +// { +// m_Parent->AddChild(child); +// } +// } +// +// typedef std::list>::const_iterator FrameChildrenIterator; +// FrameChildrenIterator begin() +// { +// return m_Children.begin(); +// } +// FrameChildrenIterator end() +// { +// return m_Children.end(); +// } +// +// virtual void Update(double dt) { } +// virtual void Draw(Renderer* renderer) { } +// +//protected: +// std::shared_ptr<::EventBroker> EventBroker; +// std::shared_ptr m_Parent; +// std::list> m_Children; +//}; +// +//} +// +//#endif // GUI_Frame_h__ diff --git a/src/GameWorld.cpp b/src/GameWorld.cpp index 18ab5a2..151ad43 100755 --- a/src/GameWorld.cpp +++ b/src/GameWorld.cpp @@ -8,11 +8,50 @@ void GameWorld::Initialize() m_ResourceManager.Preload("Model", "Models/Placeholders/PhysicsTest/Plane.obj"); m_ResourceManager.Preload("Model", "Models/Placeholders/PhysicsTest/ArrowCube.obj"); - BindKey(GLFW_KEY_W, "+forward"); - BindKey(GLFW_KEY_S, "+backward"); - BindKey(GLFW_KEY_A, "+left"); - BindKey(GLFW_KEY_D, "+right"); - BindKey(GLFW_KEY_SPACE, "+up"); + BindKey(GLFW_KEY_W, "vertical", 1.f); + BindKey(GLFW_KEY_S, "vertical", -1.f); + BindKey(GLFW_KEY_A, "horizontal", -1.f); + BindKey(GLFW_KEY_D, "horizontal", 1.f); + BindGamepadAxis(Gamepad::Axis::LeftX, "horizontal", 1.f); + BindGamepadAxis(Gamepad::Axis::RightTrigger, "vertical", 1.f); + BindGamepadAxis(Gamepad::Axis::LeftTrigger, "vertical", -1.f); + + BindKey(GLFW_KEY_UP, "barrel_rotation", 1.f); + BindKey(GLFW_KEY_DOWN, "barrel_rotation", -1.f); + BindKey(GLFW_KEY_LEFT, "tower_rotation", -1.f); + BindKey(GLFW_KEY_RIGHT, "tower_rotation", 1.f); + BindGamepadAxis(Gamepad::Axis::RightX, "tower_rotation", 1.f); + BindGamepadAxis(Gamepad::Axis::RightY, "barrel_rotation", 1.f); + + BindKey(GLFW_KEY_SPACE, "handbrake", 1.f); + BindGamepadButton(Gamepad::Button::A, "handbrake", 1.f); + + BindKey(GLFW_KEY_Z, "shoot", 1.f); + + //BindGamepadButton(Gamepad::Button::Up, "Gamepad::Button::Up", 1.f); + //BindGamepadButton(Gamepad::Button::Down, "Gamepad::Button::Down", 1.f); + //BindGamepadButton(Gamepad::Button::Left, "Gamepad::Button::Left", 1.f); + //BindGamepadButton(Gamepad::Button::Right, "Gamepad::Button::Right", 1.f); + //BindGamepadButton(Gamepad::Button::Start, "Gamepad::Button::Start", 1.f); + //BindGamepadButton(Gamepad::Button::Back, "Gamepad::Button::Back", 1.f); + //BindGamepadButton(Gamepad::Button::LeftThumb, "Gamepad::Button::LeftThumb", 1.f); + //BindGamepadButton(Gamepad::Button::RightThumb, "Gamepad::Button::RightThumb", 1.f); + //BindGamepadButton(Gamepad::Button::LeftShoulder, "Gamepad::Button::LeftShoulder", 1.f); + //BindGamepadButton(Gamepad::Button::RightShoulder, "Gamepad::Button::RightShoulder", 1.f); + //BindGamepadButton(Gamepad::Button::A, "Gamepad::Button::A", 1.f); + //BindGamepadButton(Gamepad::Button::B, "Gamepad::Button::B", 1.f); + //BindGamepadButton(Gamepad::Button::X, "Gamepad::Button::X", 1.f); + //BindGamepadButton(Gamepad::Button::Y, "Gamepad::Button::Y", 1.f); +// +// BindKey(GLFW_KEY_UP, "vertical", -1.f); +// BindKey(GLFW_KEY_DOWN, "vertical", 1.f); +// BindKey(GLFW_KEY_LEFT, "horizontal", -1.f); +// BindKey(GLFW_KEY_RIGHT, "horizontal", 1.f); + /* + BindKey(GLFW_KEY_Q, "+tower_right"); + BindKey(GLFW_KEY_E, "+tower_left"); + + BindKey(GLFW_KEY_Q, "+up"); BindKey(GLFW_KEY_LEFT_CONTROL, "+down"); BindKey(GLFW_KEY_LEFT_ALT, "+slow"); BindKey(GLFW_KEY_LEFT_SHIFT, "+fast"); @@ -20,6 +59,12 @@ void GameWorld::Initialize() BindMouseButton(GLFW_MOUSE_BUTTON_2, "+attack2"); BindMouseButton(GLFW_MOUSE_BUTTON_3, "+attack3"); + + BindKey(GLFW_KEY_UP, "+cam_forward"); + BindKey(GLFW_KEY_DOWN, "+cam_backward"); + BindKey(GLFW_KEY_LEFT, "+cam_left"); + BindKey(GLFW_KEY_RIGHT, "+cam_right");*/ + RegisterComponents(); { @@ -38,63 +83,96 @@ void GameWorld::Initialize() { auto ground = CreateEntity(); auto transform = AddComponent(ground, "Transform"); - transform->Position = glm::vec3(0, -5, 0); - transform->Scale = glm::vec3(400.0f, 10.0f, 400.0f); + transform->Position = glm::vec3(0, 0, 0); + //transform->Scale = glm::vec3(400.0f, 10.0f, 400.0f); transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); auto model = AddComponent(ground, "Model"); - model->ModelFile = "Models/Placeholders/PhysicsTest/Cube.obj"; - auto box = AddComponent(ground, "Box"); - box->Width = 200; - box->Height = 5; - box->Depth = 200; - + //model->ModelFile = "Models/TestScene/testScene.obj"; + model->ModelFile = "Models/Placeholders/Terrain/Terrain2.obj"; + auto physics = AddComponent(ground, "Physics"); physics->Mass = 10; physics->Static = true; + + auto groundshape = CreateEntity(ground); + auto transformshape = AddComponent(groundshape, "Transform"); + auto meshShape = AddComponent(groundshape, "MeshShape"); + meshShape->ResourceName = "Models/Placeholders/Terrain/Terrain2.obj"; + //meshShape->ResourceName = "Models/TestScene/testScene.obj"; + + + CommitEntity(groundshape); CommitEntity(ground); } + - { + /*{ auto jeep = CreateEntity(); auto transform = AddComponent(jeep, "Transform"); - transform->Position = glm::vec3(0, 2, 0); - + transform->Position = glm::vec3(0, 5, 0); + transform->Orientation = glm::angleAxis(glm::pi()/2, glm::vec3(0, 1, 0)); auto physics = AddComponent(jeep, "Physics"); - physics->Mass = 1200; - auto box = AddComponent(jeep, "Box"); - box->Width = 1.487f; - box->Height = 0.727f; - box->Depth = 2.594f; + physics->Mass = 1800; + physics->Static = false; auto vehicle = AddComponent(jeep, "Vehicle"); - AddComponent(jeep, "Input"); + { + auto shape = CreateEntity(jeep); + auto transform = AddComponent(shape, "Transform"); + auto meshShape = AddComponent(shape, "MeshShape"); + meshShape->ResourceName = "Models/Jeep/Chassi/ChassiCollision.obj"; + CommitEntity(shape); + + // auto box = AddComponent(jeep, "Box"); + // box->Width = 1.487f; + // box->Height = 0.727f; + // box->Depth = 2.594f; + + } + { auto chassis = CreateEntity(jeep); auto transform = AddComponent(chassis, "Transform"); - transform->Position = glm::vec3(0, -0.6577f, 0); + transform->Position = glm::vec3(0, 0, 0); // 0.6577f auto model = AddComponent(chassis, "Model"); - model->ModelFile = "Models/JeepV2/Chassi/chassi.OBJ"; - + model->ModelFile = "Models/Jeep/Chassi/chassi.obj"; } + { + auto lightentity = CreateEntity(jeep); + auto transform = AddComponent(lightentity, "Transform"); + transform->Position = glm::vec3(0, 15, 0); + auto light = AddComponent(lightentity, "PointLight"); + light->Diffuse = glm::vec3(128.f/255.f, 172.f/255.f, 242.f/255.f); + light->Specular = glm::vec3(1.f); + light->constantAttenuation = 0.3f; + light->linearAttenuation = 0.003f; + light->quadraticAttenuation = 0.002f; + } + + + //Create wheels + float wheelOffset = 0.4f; + float springLength = 0.3f; + float suspensionStrength = 35.f; { auto wheel = CreateEntity(jeep); auto transform = AddComponent(wheel, "Transform"); - transform->Position = glm::vec3(1.4f, 0.5546f - 0.6577f - 0.2, -0.9242f); + transform->Position = glm::vec3(1.9f, 0.5546f - wheelOffset, -0.9242f); transform->Scale = glm::vec3(1.0f); auto model = AddComponent(wheel, "Model"); - model->ModelFile = "Models/JeepV2/WheelFront/wheelFront.obj"; + model->ModelFile = "Models/Jeep/WheelFront/wheelFront.obj"; auto Wheel = AddComponent(wheel, "Wheel"); - Wheel->Hardpoint = transform->Position + glm::vec3(0.f, 1.f, 0.f); + Wheel->Hardpoint = transform->Position + glm::vec3(0.f, springLength, 0.f); Wheel->AxleID = 0; Wheel->Mass = 50; Wheel->Radius = 0.837f; Wheel->Steering = true; - Wheel->SuspensionStrength = 40.f; - Wheel->Friction = 4.0f; + Wheel->SuspensionStrength = suspensionStrength; + Wheel->Friction = 4.f; Wheel->ConnectedToHandbrake = true; CommitEntity(wheel); } @@ -102,19 +180,19 @@ void GameWorld::Initialize() { auto wheel = CreateEntity(jeep); auto transform = AddComponent(wheel, "Transform"); - transform->Position = glm::vec3(-1.4f, 0.5546f - 0.6577f - 0.2, -0.9242f); + transform->Position = glm::vec3(-1.9f, 0.5546f - wheelOffset, -0.9242f); transform->Scale = glm::vec3(1.0f); transform->Orientation = glm::angleAxis(glm::pi(), glm::vec3(0, 0, 1)); auto model = AddComponent(wheel, "Model"); - model->ModelFile = "Models/JeepV2/WheelFront/wheelFront.obj"; + model->ModelFile = "Models/Jeep/WheelFront/wheelFront.obj"; auto Wheel = AddComponent(wheel, "Wheel"); - Wheel->Hardpoint = transform->Position + glm::vec3(0.f, 1.f, 0.f); + Wheel->Hardpoint = transform->Position + glm::vec3(0.f, springLength, 0.f); Wheel->AxleID = 0; Wheel->Mass = 50; Wheel->Radius = 0.837f; Wheel->Steering = true; - Wheel->SuspensionStrength = 40.f; - Wheel->Friction = 4.0f; + Wheel->SuspensionStrength = suspensionStrength; + Wheel->Friction = 4.f; Wheel->ConnectedToHandbrake = true; CommitEntity(wheel); } @@ -122,145 +200,545 @@ void GameWorld::Initialize() { auto wheel = CreateEntity(jeep); auto transform = AddComponent(wheel, "Transform"); - transform->Position = glm::vec3(0.2726f, 0.2805f - 0.6577f, 1.9307f); + transform->Position = glm::vec3(0.2726f, 0.2805f - wheelOffset, 1.9307f); auto model = AddComponent(wheel, "Model"); - model->ModelFile = "Models/JeepV2/WheelBack/wheelBack.obj"; + model->ModelFile = "Models/Jeep/WheelBack/wheelBack.obj"; auto Wheel = AddComponent(wheel, "Wheel"); - Wheel->Hardpoint = transform->Position + glm::vec3(0.f, 1.f, 0.f); + Wheel->Hardpoint = transform->Position + glm::vec3(0.f, springLength, 0.f); Wheel->AxleID = 1; - Wheel->Mass = 10; + Wheel->Mass = 50; Wheel->Radius = 0.737f; Wheel->Steering = false; - Wheel->SuspensionStrength = 50.f; - Wheel->Friction = 4.0f; + Wheel->SuspensionStrength = suspensionStrength; + Wheel->Friction = 4.f; + Wheel->ConnectedToHandbrake = true; CommitEntity(wheel); } { auto wheel = CreateEntity(jeep); auto transform = AddComponent(wheel, "Transform"); - transform->Position = glm::vec3(-0.2726f, 0.2805f - 0.6577f, 1.9307f); + transform->Position = glm::vec3(-0.2726f, 0.2805f - wheelOffset, 1.9307f); transform->Orientation = glm::angleAxis(glm::pi(), glm::vec3(0, 0, 1)); auto model = AddComponent(wheel, "Model"); - model->ModelFile = "Models/JeepV2/WheelBack/wheelBack.obj"; + model->ModelFile = "Models/Jeep/WheelBack/wheelBack.obj"; auto Wheel = AddComponent(wheel, "Wheel"); - Wheel->Hardpoint = transform->Position + glm::vec3(0.f, 1.f, 0.f); + Wheel->Hardpoint = transform->Position + glm::vec3(0.f, springLength, 0.f); Wheel->AxleID = 1; - Wheel->Mass = 10; + Wheel->Mass = 50; Wheel->Radius = 0.737f; Wheel->Steering = false; - Wheel->SuspensionStrength = 50.f; - Wheel->Friction = 4.0f; + Wheel->SuspensionStrength = suspensionStrength; + Wheel->Friction = 4.f; + Wheel->ConnectedToHandbrake = true; CommitEntity(wheel); } + CommitEntity(jeep); + }*/ + + + { + auto tank = CreateEntity(); + auto transform = AddComponent(tank, "Transform"); + transform->Position = glm::vec3(0, 5, 0); + //transform->Orientation = glm::angleAxis(0.f, glm::vec3(0, 1, 0)); + auto physics = AddComponent(tank, "Physics"); + physics->Mass = 45000; + physics->Static = false; + auto vehicle = AddComponent(tank, "Vehicle"); + vehicle->MaxTorque = 5200.f; + AddComponent(tank, "TankSteering"); + AddComponent(tank, "Input"); + + { + auto shape = CreateEntity(tank); + auto transform = AddComponent(shape, "Transform"); + auto meshShape = AddComponent(shape, "MeshShape"); + meshShape->ResourceName = "Models/Tank/Fix/ChassiCollision.obj"; + CommitEntity(shape); + + // auto box = AddComponent(jeep, "Box"); + // box->Width = 1.487f; + // box->Height = 0.727f; + // box->Depth = 2.594f; + + } + + { + auto chassis = CreateEntity(tank); + auto transform = AddComponent(chassis, "Transform"); + transform->Position = glm::vec3(0, 0, 0); + auto model = AddComponent(chassis, "Model"); + model->ModelFile = "Models/Tank/Fix/Chassi.obj"; + } + { + auto tower = CreateEntity(tank); + SetProperty(tower, "Name", "tower"); + auto transform = AddComponent(tower, "Transform"); + transform->Position = glm::vec3(0.f, 1.2f, 1.8f); + auto model = AddComponent(tower, "Model"); + model->ModelFile = "Models/Tank/Fix/Top.obj"; + auto towerSteering = AddComponent(tower, "TowerSteering"); + towerSteering->Axis = glm::vec3(0.f, 1.f, 0.f); + towerSteering->TurnSpeed = glm::pi()/4.f; + { + auto barrel = CreateEntity(tower); + auto transform = AddComponent(barrel, "Transform"); + transform->Position = glm::vec3(-0.018f, -0.2, -1.3f); + auto model = AddComponent(barrel, "Model"); + model->ModelFile = "Models/Tank/Fix/Barrel.obj"; + auto barrelSteering = AddComponent(barrel, "BarrelSteering"); + barrelSteering->Axis = glm::vec3(1.f, 0.f, 0.f); + barrelSteering->TurnSpeed = glm::pi()/4.f; + barrelSteering->ShotSpeed = 70.f; + { + auto shot = CreateEntity(barrel); + auto transform = AddComponent(shot, "Transform"); + transform->Position = glm::vec3(0.35f, 0.f, -2.f); + transform->Orientation = glm::angleAxis(-glm::pi()/2.f, glm::vec3(1, 0, 0)); + transform->Scale = glm::vec3(3.f); + AddComponent(shot, "Template"); + auto physics = AddComponent(shot, "Physics"); + physics->Mass = 10.f; + physics->Static = false; + auto modelComponent = AddComponent(shot, "Model"); + modelComponent->ModelFile = "Models/Placeholders/rocket/Rocket.obj"; + + { + auto shape = CreateEntity(shot); + auto transform = AddComponent(shape, "Transform"); + auto boxShape = AddComponent(shape, "BoxShape"); + boxShape->Width = 0.5f; + boxShape->Height = 0.5f; + boxShape->Depth = 0.5f; + CommitEntity(shape); + } + CommitEntity(shot); + barrelSteering->ShotTemplate = shot; + } + CommitEntity(barrel); + } + } + + { + auto lightentity = CreateEntity(tank); + auto transform = AddComponent(lightentity, "Transform"); + transform->Position = glm::vec3(0, 0, 0); + auto light = AddComponent(lightentity, "PointLight"); + //light->Diffuse = glm::vec3(128.f/255.f, 172.f/255.f, 242.f/255.f); + //light->Specular = glm::vec3(1.f); + /*light->ConstantAttenuation = 0.3f; + light->LinearAttenuation = 0.003f; + light->QuadraticAttenuation = 0.002f;*/ + } + +// auto wheelpair = CreateEntity(tank); +// SetProperty(wheelpair, "Name", "WheelPair"); +// AddComponent(wheelpair, "WheelPairThingy"); + + //Create wheels + float wheelOffset = 0.4f; + float springLength = 0.3f; + float suspensionStrength = 25.f; + + { + auto wheel = CreateEntity(tank); + auto transform = AddComponent(wheel, "Transform"); + transform->Position = glm::vec3(1.68f, -0.83f - wheelOffset, -2.6f); + transform->Orientation = glm::angleAxis(glm::pi(), glm::vec3(0, 1, 0)); + auto model = AddComponent(wheel, "Model"); + model->ModelFile = "Models/Tank/Fix/WheelPhysics.obj"; + auto Wheel = AddComponent(wheel, "Wheel"); + Wheel->Hardpoint = transform->Position + glm::vec3(0.f, springLength, 0.f); + Wheel->AxleID = 0; + Wheel->Mass = 2000; + Wheel->Radius = 0.6f; + Wheel->Steering = true; + Wheel->SuspensionStrength = suspensionStrength; + Wheel->Friction = 4.f; + Wheel->ConnectedToHandbrake = true; + Wheel->TorqueRatio = 0.125f; + Wheel->Width = 0.6f; + { + auto shape = CreateEntity(wheel); + auto shapetransform = AddComponent(shape, "Transform"); + shapetransform->Position = glm::vec3(0.f, 0.32f, 0.f) + transform->Position; + auto boxShape = AddComponent(shape, "BoxShape"); + boxShape->Width = 0.7f; + boxShape->Height = 0.34f; + boxShape->Depth = 0.7f; + CommitEntity(shape); + } + CommitEntity(wheel); + } + { + auto wheel = CreateEntity(tank); + auto transform = AddComponent(wheel, "Transform"); + transform->Position = glm::vec3(1.68f, -0.83f - wheelOffset, -0.83f); + transform->Orientation = glm::angleAxis(glm::pi(), glm::vec3(0, 1, 0)); + auto model = AddComponent(wheel, "Model"); + model->ModelFile = "Models/Tank/Fix/WheelPhysics.obj"; + auto Wheel = AddComponent(wheel, "Wheel"); + Wheel->Hardpoint = transform->Position + glm::vec3(0.f, springLength, 0.f); + Wheel->AxleID = 0; + Wheel->Mass = 2000; + Wheel->Radius = 0.6f; + Wheel->Steering = false; + Wheel->SuspensionStrength = suspensionStrength; + Wheel->Friction = 4.f; + Wheel->ConnectedToHandbrake = true; + Wheel->TorqueRatio = 0.125f; + Wheel->Width = 0.6f; + { + auto shape = CreateEntity(wheel); + auto shapetransform = AddComponent(shape, "Transform"); + shapetransform->Position = glm::vec3(0.f, 0.32f, 0.f) + transform->Position; + auto boxShape = AddComponent(shape, "BoxShape"); + boxShape->Width = 0.7f; + boxShape->Height = 0.34f; + boxShape->Depth = 0.7f; + CommitEntity(shape); + } + CommitEntity(wheel); + } + + { + auto wheel = CreateEntity(tank); + auto transform = AddComponent(wheel, "Transform"); + transform->Position = glm::vec3(-1.68f, -0.83f - wheelOffset, -2.6f); + transform->Orientation = glm::angleAxis(glm::pi(), glm::vec3(0, 1, 0)); + auto model = AddComponent(wheel, "Model"); + model->ModelFile = "Models/Tank/Fix/WheelPhysics.obj"; + auto Wheel = AddComponent(wheel, "Wheel"); + Wheel->Hardpoint = transform->Position + glm::vec3(0.f, springLength, 0.f); + Wheel->AxleID = 0; + Wheel->Mass = 2000; + Wheel->Radius = 0.6f; + Wheel->Steering = true; + Wheel->SuspensionStrength = suspensionStrength; + Wheel->Friction = 4.f; + Wheel->ConnectedToHandbrake = true; + Wheel->TorqueRatio = 0.125f; + Wheel->Width = 0.6f; + { + auto shape = CreateEntity(wheel); + auto shapetransform = AddComponent(shape, "Transform"); + shapetransform->Position = glm::vec3(0.f, 0.32f, 0.f) + transform->Position; + auto boxShape = AddComponent(shape, "BoxShape"); + boxShape->Width = 0.7f; + boxShape->Height = 0.34f; + boxShape->Depth = 0.7f; + CommitEntity(shape); + } + CommitEntity(wheel); + } + { + auto wheel = CreateEntity(tank); + auto transform = AddComponent(wheel, "Transform"); + transform->Position = glm::vec3(-1.68f, -0.83f - wheelOffset, -0.83f); + transform->Orientation = glm::angleAxis(glm::pi(), glm::vec3(0, 1, 0)); + auto model = AddComponent(wheel, "Model"); + model->ModelFile = "Models/Tank/Fix/WheelPhysics.obj"; + auto Wheel = AddComponent(wheel, "Wheel"); + Wheel->Hardpoint = transform->Position + glm::vec3(0.f, springLength, 0.f); + Wheel->AxleID = 0; + Wheel->Mass = 2000; + Wheel->Radius = 0.6f; + Wheel->Steering = false; + Wheel->SuspensionStrength = suspensionStrength; + Wheel->Friction = 4.f; + Wheel->ConnectedToHandbrake = true; + Wheel->TorqueRatio = 0.125f; + Wheel->Width = 0.6f; + { + auto shape = CreateEntity(wheel); + auto shapetransform = AddComponent(shape, "Transform"); + shapetransform->Position = glm::vec3(0.f, 0.32f, 0.f) + transform->Position; + auto boxShape = AddComponent(shape, "BoxShape"); + boxShape->Width = 0.7f; + boxShape->Height = 0.34f; + boxShape->Depth = 0.7f; + CommitEntity(shape); + } + CommitEntity(wheel); + } + + + //Back + { + auto wheel = CreateEntity(tank); + auto transform = AddComponent(wheel, "Transform"); + transform->Position = glm::vec3(1.68f, -0.83f - wheelOffset, 1.f); + auto model = AddComponent(wheel, "Model"); + model->ModelFile = "Models/Tank/Fix/WheelPhysics.obj"; + auto Wheel = AddComponent(wheel, "Wheel"); + Wheel->Hardpoint = transform->Position + glm::vec3(0.f, springLength, 0.f); + Wheel->AxleID = 1; + Wheel->Mass = 2000; + Wheel->Radius = 0.6f; + Wheel->Steering = false; + Wheel->SuspensionStrength = suspensionStrength; + Wheel->Friction = 4.f; + Wheel->ConnectedToHandbrake = true; + Wheel->TorqueRatio = 0.125f; + Wheel->Width = 0.6f; + { + auto shape = CreateEntity(wheel); + auto shapetransform = AddComponent(shape, "Transform"); + shapetransform->Position = glm::vec3(0.f, 0.32f, 0.f) + transform->Position; + auto boxShape = AddComponent(shape, "BoxShape"); + boxShape->Width = 0.7f; + boxShape->Height = 0.34f; + boxShape->Depth = 0.7f; + CommitEntity(shape); + } + CommitEntity(wheel); + } + { + auto wheel = CreateEntity(tank); + auto transform = AddComponent(wheel, "Transform"); + transform->Position = glm::vec3(1.68f, -0.83f - wheelOffset, 2.95f); + auto model = AddComponent(wheel, "Model"); + model->ModelFile = "Models/Tank/Fix/WheelPhysics.obj"; + auto Wheel = AddComponent(wheel, "Wheel"); + Wheel->Hardpoint = transform->Position + glm::vec3(0.f, springLength, 0.f); + Wheel->AxleID = 1; + Wheel->Mass = 2000; + Wheel->Radius = 0.6f; + Wheel->Steering = false; + Wheel->SuspensionStrength = suspensionStrength; + Wheel->Friction = 4.f; + Wheel->ConnectedToHandbrake = true; + Wheel->TorqueRatio = 0.125f; + Wheel->Width = 0.6f; + { + auto shape = CreateEntity(wheel); + auto shapetransform = AddComponent(shape, "Transform"); + shapetransform->Position = glm::vec3(0.f, 0.32f, 0.f) + transform->Position; + auto boxShape = AddComponent(shape, "BoxShape"); + boxShape->Width = 0.7f; + boxShape->Height = 0.34f; + boxShape->Depth = 0.7f; + CommitEntity(shape); + } + CommitEntity(wheel); + + auto entity = CreateEntity(tank); + auto transformComponent = AddComponent(entity, "Transform"); + transformComponent->Position = glm::vec3(2,-1.7,2.0); + transformComponent->Scale = glm::vec3(3,3,3); + transformComponent->Orientation = glm::angleAxis(glm::pi()/2, glm::vec3(1,0,0)); + auto emitterComponent = AddComponent(entity, "ParticleEmitter"); + emitterComponent->SpawnCount = 2; + emitterComponent->SpawnFrequency = 0.005; + emitterComponent->SpreadAngle = glm::pi(); + emitterComponent->UseGoalVelocity = false; + emitterComponent->LifeTime = 0.5; + //emitterComponent->AngularVelocitySpectrum.push_back(glm::pi() / 100); + emitterComponent->ScaleSpectrum.push_back(glm::vec3(0.05)); + CommitEntity(entity); + + auto particleEntity = CreateEntity(entity); + auto TEMP = AddComponent(particleEntity, "Transform"); + TEMP->Scale = glm::vec3(0); + auto spriteComponent = AddComponent(particleEntity, "Sprite"); + spriteComponent->SpriteFile = "Models/Textures/Sprites/Dust.png"; + emitterComponent->ParticleTemplate = particleEntity; + + CommitEntity(particleEntity); + } + + { + auto wheel = CreateEntity(tank); + auto transform = AddComponent(wheel, "Transform"); + transform->Position = glm::vec3(-1.68f, -0.83f - wheelOffset, 1.f); + transform->Orientation = glm::angleAxis(glm::pi(), glm::vec3(0, 1, 0)); + auto model = AddComponent(wheel, "Model"); + model->ModelFile = "Models/Tank/Fix/WheelPhysics.obj"; + auto Wheel = AddComponent(wheel, "Wheel"); + Wheel->Hardpoint = transform->Position + glm::vec3(0.f, springLength, 0.f); + Wheel->AxleID = 1; + Wheel->Mass = 2000; + Wheel->Radius = 0.6f; + Wheel->Steering = false; + Wheel->SuspensionStrength = suspensionStrength; + Wheel->Friction = 4.f; + Wheel->ConnectedToHandbrake = true; + Wheel->TorqueRatio = 0.125f; + Wheel->Width = 0.6f; + { + auto shape = CreateEntity(wheel); + auto shapetransform = AddComponent(shape, "Transform"); + shapetransform->Position = glm::vec3(0.f, 0.32f, 0.f) + transform->Position; + auto boxShape = AddComponent(shape, "BoxShape"); + boxShape->Width = 0.7f; + boxShape->Height = 0.34f; + boxShape->Depth = 0.7f; + CommitEntity(shape); + } + CommitEntity(wheel); + } + { + auto wheel = CreateEntity(tank); + auto transform = AddComponent(wheel, "Transform"); + transform->Position = glm::vec3(-1.68f, -0.83f - wheelOffset, 2.95f); + auto model = AddComponent(wheel, "Model"); + model->ModelFile = "Models/Tank/Fix/WheelPhysics.obj"; + auto Wheel = AddComponent(wheel, "Wheel"); + Wheel->Hardpoint = transform->Position + glm::vec3(0.f, springLength, 0.f); + Wheel->AxleID = 1; + Wheel->Mass = 2000; + Wheel->Radius = 0.6f; + Wheel->Steering = false; + Wheel->SuspensionStrength = suspensionStrength; + Wheel->Friction = 4.f; + Wheel->ConnectedToHandbrake = true; + Wheel->TorqueRatio = 0.125f; + Wheel->Width = 0.6f; + { + auto shape = CreateEntity(wheel); + auto shapetransform = AddComponent(shape, "Transform"); + shapetransform->Position = glm::vec3(0.f, 0.32f, 0.f) + transform->Position; + auto boxShape = AddComponent(shape, "BoxShape"); + boxShape->Width = 0.7f; + boxShape->Height = 0.34f; + boxShape->Depth = 0.7f; + CommitEntity(shape); + } + CommitEntity(wheel); + + auto entity = CreateEntity(tank); + auto transformComponent = AddComponent(entity, "Transform"); + transformComponent->Position = glm::vec3(-2,-1.7,2.0); + transformComponent->Scale = glm::vec3(3,3,3); + transformComponent->Orientation = glm::angleAxis(glm::pi()/2, glm::vec3(1,0,0)); + auto emitterComponent = AddComponent(entity, "ParticleEmitter"); + emitterComponent->SpawnCount = 2; + emitterComponent->SpawnFrequency = 0.005; + emitterComponent->SpreadAngle = glm::pi(); + emitterComponent->UseGoalVelocity = false; + emitterComponent->LifeTime = 0.5; + //emitterComponent->AngularVelocitySpectrum.push_back(glm::pi() / 100); + emitterComponent->ScaleSpectrum.push_back(glm::vec3(0.05)); + CommitEntity(entity); + + auto particleEntity = CreateEntity(entity); + auto TEMP = AddComponent(particleEntity, "Transform"); + TEMP->Scale = glm::vec3(0); + auto spriteComponent = AddComponent(particleEntity, "Sprite"); + spriteComponent->SpriteFile = "Models/Textures/Sprites/Dust.png"; + emitterComponent->ParticleTemplate = particleEntity; + + CommitEntity(particleEntity); + } + + CommitEntity(tank); + { + auto camera = CreateEntity(tank); + auto transform = AddComponent(camera, "Transform"); + transform->Position.z = 30.f; + transform->Position.y = 5.f; + //transform->Orientation = glm::quat(glm::vec3(-glm::pi() / 8.f, 0.f, 0.f)); + transform->Orientation = glm::angleAxis(glm::pi() / 100, glm::vec3(1,0,0)); + auto cameraComp = AddComponent(camera, "Camera"); + cameraComp->FarClip = 2000.f; + AddComponent(camera, "Input"); + auto freeSteering = AddComponent(camera, "FreeSteering"); + CommitEntity(camera); + } } -/* + - { - // Front Right Wheel - auto ent = CreateEntity(car); - auto transform = AddComponent(ent, "Transform"); - transform->Scale = glm::vec3(1)/glm::vec3(3, 1, 5); - transform->Position = glm::vec3(1.1f, -1.5f, -1.3f); - auto Wheel = AddComponent(ent, "Wheel"); - Wheel->Hardpoint = glm::vec3(1.1f, 0.f, -1.3f);// HACK: make into component - Wheel->AxleID = 0; - Wheel->Mass = 10; - Wheel->Radius = 0.5f; - Wheel->Steering = true; - Wheel->SuspensionStrength = 20.f; - auto model = AddComponent(ent, "Model"); - model->ModelFile = "Models/Placeholders/PhysicsTest/Cube2.obj"; - CommitEntity(ent); - } - { - // Front Left Wheel - auto ent = CreateEntity(car); - auto transform = AddComponent(ent, "Transform"); - transform->Scale = glm::vec3(1)/glm::vec3(3, 1, 5); - transform->Position = glm::vec3(-1.1f, -1.5f, -1.3f); - auto Wheel = AddComponent(ent, "Wheel"); - Wheel->Hardpoint = glm::vec3(-1.1f, 0.f, -1.3f); - Wheel->AxleID = 0; - Wheel->Mass = 10; - Wheel->Radius = 0.5f; - Wheel->Steering = true; - Wheel->SuspensionStrength = 20.f; - auto model = AddComponent(ent, "Model"); - model->ModelFile = "Models/Placeholders/PhysicsTest/Cube2.obj"; - CommitEntity(ent); - } - { - // Back Right Wheel - auto ent = CreateEntity(car); - auto transform = AddComponent(ent, "Transform"); - transform->Scale = glm::vec3(1)/glm::vec3(3, 1, 5); - transform->Position = glm::vec3(1.1f, -1.5f, 1.3f); - auto Wheel = AddComponent(ent, "Wheel"); - Wheel->Hardpoint = glm::vec3(1.1f, 0.f, 1.3f); - Wheel->AxleID = 1; - Wheel->Mass = 10; - Wheel->Radius = 0.5f; - Wheel->Steering = false; - Wheel->ConnectedToHandbrake = true; - Wheel->SuspensionStrength = 20.f; - auto model = AddComponent(ent, "Model"); - model->ModelFile = "Models/Placeholders/PhysicsTest/Cube2.obj"; - CommitEntity(ent); - } - { - // Back Left Wheel - auto ent = CreateEntity(car); - auto transform = AddComponent(ent, "Transform"); - transform->Scale = glm::vec3(1)/glm::vec3(3, 1, 5); - transform->Position = glm::vec3(-1.1f, -1.5f, 1.3f); - auto Wheel = AddComponent(ent, "Wheel"); - Wheel->Hardpoint = glm::vec3(-1.1f, 0.f, 1.3f); - Wheel->AxleID = 1; - Wheel->Mass = 10; - Wheel->Radius = 0.5f; - Wheel->Steering = false; - Wheel->ConnectedToHandbrake = true; - Wheel->SuspensionStrength = 20.f; - auto model = AddComponent(ent, "Model"); - model->ModelFile = "Models/Placeholders/PhysicsTest/Cube2.obj"; - CommitEntity(ent); - } - - CommitEntity(car); - } + /* + for(int i = 0; i < 10; i++) + { + auto entity = CreateEntity(); + auto transform = AddComponent(entity, "Transform"); + transform->Position = glm::vec3(30 + i*0.1f, 0 + i*0.1f, 10 + i*0.1f); + transform->Scale = glm::vec3(0); + transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); + + std::stringstream ss; + ss << "Models/Placeholders/ShatterTest/" << i+1 << ".obj"; + + auto model = AddComponent(entity, "Model"); + model->ModelFile = ss.str(); + + auto physics = AddComponent(entity, "Physics"); + physics->Mass = 100; + physics->Static = true; + auto meshShape = AddComponent(entity, "MeshShape"); + meshShape->ResourceName = ss.str(); + + CommitEntity(entity); + }*/ + + for(int i = 0; i < 1; i++) + { + for (int y = 0; y < 15; y++) + { + for (int x = -5; x < 5; x++) + { + auto brick = CreateEntity(); + auto transform = AddComponent(brick, "Transform"); + transform->Position = glm::vec3(x + 0.01f, y * 0.3f + 0.01f, -20); + transform->Position.x += (y % 2)*0.5f; + transform->Scale = glm::vec3(1, 0.3f, 0.4f); + transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); + auto model = AddComponent(brick, "Model"); + model->ModelFile = "Models/Placeholders/PhysicsTest/Cube2.obj"; + + auto physics = AddComponent(brick, "Physics"); + physics->Mass = 3; + + + + auto shape = CreateEntity(brick); + auto transformshape = AddComponent(shape, "Transform"); + auto box = AddComponent(shape, "BoxShape"); + box->Width = 0.5f; + box->Height = 0.15f; + box->Depth = 0.3f; + CommitEntity(shape); + CommitEntity(brick); + } + } + } + + /*for (int x = 0; x < 5; x++) + for (int y = 0; y < 5; y++) + { + auto cube = CreateEntity(); + auto transform = AddComponent(cube, "Transform"); + transform->Position = glm::vec3(3 * x + 0.1f + -20.f, 3 * y + 0.1f + 1.f, 0); + transform->Scale = glm::vec3(3); + transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); + auto model = AddComponent(cube, "Model"); + model->ModelFile = "Models/Placeholders/PhysicsTest/Cube2.obj"; + + auto physics = AddComponent(cube, "Physics"); + physics->Mass = 100; + auto box = AddComponent(cube, "BoxShape"); + box->Width = 1.5f; + box->Height = 1.5f; + box->Depth = 1.5f; + CommitEntity(cube); + } */ - for (int i = 0; i < 10; i++) - { - auto cube = CreateEntity(); - auto transform = AddComponent(cube, "Transform"); - transform->Position = glm::vec3(20, 10 + i * 2, 0); - transform->Scale = glm::vec3(1); - transform->Orientation = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); - auto model = AddComponent(cube, "Model"); - model->ModelFile = "Models/Placeholders/PhysicsTest/Cube2.obj"; - auto physics = AddComponent(cube, "Physics"); - physics->Mass = 100; - auto box = AddComponent(cube, "Box"); - box->Width = 0.5f; - box->Height = 0.5f; - box->Depth = 0.5f; - CommitEntity(cube); - } - - { + /*{ auto entity = CreateEntity(); AddComponent(entity, "Transform"); auto emitter = AddComponent(entity, "SoundEmitter"); emitter->Path = "Sounds/korvring.wav"; emitter->Loop = true; - //GetSystem("SoundSystem")->PlaySound(emitter); + GetSystem("SoundSystem")->PlaySound(emitter); CommitEntity(entity); - } + }*/ + } void GameWorld::Update(double dt) @@ -281,9 +759,10 @@ void GameWorld::RegisterSystems() m_SystemFactory.Register("InputSystem", [this]() { return new Systems::InputSystem(this, m_EventBroker); }); m_SystemFactory.Register("DebugSystem", [this]() { return new Systems::DebugSystem(this, m_EventBroker); }); //m_SystemFactory.Register("CollisionSystem", [this]() { return new Systems::CollisionSystem(this); }); - ////m_SystemFactory.Register("ParticleSystem", [this]() { return new Systems::ParticleSystem(this); }); + m_SystemFactory.Register("ParticleSystem", [this]() { return new Systems::ParticleSystem(this, m_EventBroker); }); //m_SystemFactory.Register("PlayerSystem", [this]() { return new Systems::PlayerSystem(this); }); m_SystemFactory.Register("FreeSteeringSystem", [this]() { return new Systems::FreeSteeringSystem(this, m_EventBroker); }); + m_SystemFactory.Register("TankSteeringSystem", [this]() { return new Systems::TankSteeringSystem(this, m_EventBroker); }); m_SystemFactory.Register("SoundSystem", [this]() { return new Systems::SoundSystem(this, m_EventBroker); }); m_SystemFactory.Register("PhysicsSystem", [this]() { return new Systems::PhysicsSystem(this, m_EventBroker); }); m_SystemFactory.Register("RenderSystem", [this]() { return new Systems::RenderSystem(this, m_EventBroker, m_Renderer); }); @@ -296,19 +775,21 @@ void GameWorld::AddSystems() AddSystem("InputSystem"); AddSystem("DebugSystem"); //AddSystem("CollisionSystem"); - ////AddSystem("ParticleSystem"); + AddSystem("ParticleSystem"); //AddSystem("PlayerSystem"); AddSystem("FreeSteeringSystem"); + AddSystem("TankSteeringSystem"); AddSystem("SoundSystem"); AddSystem("PhysicsSystem"); AddSystem("RenderSystem"); } -void GameWorld::BindKey(int keyCode, std::string command) +void GameWorld::BindKey(int keyCode, std::string command, float value) { Events::BindKey e; e.KeyCode = keyCode; e.Command = command; + e.Value = value; m_EventBroker->Publish(e); } @@ -319,3 +800,21 @@ void GameWorld::BindMouseButton(int button, std::string command) e.Command = command; m_EventBroker->Publish(e); } + +void GameWorld::BindGamepadAxis(Gamepad::Axis axis, std::string command, float value) +{ + Events::BindGamepadAxis e; + e.Axis = axis; + e.Command = command; + e.Value = value; + m_EventBroker->Publish(e); +} + +void GameWorld::BindGamepadButton(Gamepad::Button button, std::string command, float value) +{ + Events::BindGamepadButton e; + e.Button = button; + e.Command = command; + e.Value = value; + m_EventBroker->Publish(e); +} diff --git a/src/GameWorld.h b/src/GameWorld.h index 6a1d25b..5e990bb 100755 --- a/src/GameWorld.h +++ b/src/GameWorld.h @@ -9,9 +9,10 @@ #include "Systems/InputSystem.h" #include "Systems/DebugSystem.h" //#include "Systems/LevelGenerationSystem.h" -//#include "Systems/ParticleSystem.h" +#include "Systems/ParticleSystem.h" //#include "Systems/PlayerSystem.h" #include "Systems/FreeSteeringSystem.h" +#include "Systems/TankSteeringSystem.h" #include "Systems/RenderSystem.h" #include "Systems/SoundSystem.h" #include "Systems/PhysicsSystem.h" @@ -21,6 +22,7 @@ #include "Components/Input.h" #include "Components/Model.h" #include "Components/ParticleEmitter.h" +#include "Components/Particle.h" #include "Components/PointLight.h" #include "Components/SoundEmitter.h" #include "Components/Sprite.h" @@ -28,10 +30,14 @@ #include "Components/Transform.h" #include "Components/Physics.h" -#include "Components/Sphere.h" -#include "Components/Box.h" +#include "Components/SphereShape.h" +#include "Components/BoxShape.h" #include "Components/Vehicle.h" #include "Components/Wheel.h" +#include "Components/HingeConstraint.h" +#include "Components/TankSteering.h" +#include "Components/TowerSteering.h" +#include "Components/BarrelSteering.h" class GameWorld : public World { @@ -50,8 +56,10 @@ public: private: std::shared_ptr m_Renderer; - void BindKey(int keyCode, std::string command); + void BindKey(int keyCode, std::string command, float value); void BindMouseButton(int button, std::string command); + void BindGamepadAxis(Gamepad::Axis axis, std::string command, float value); + void BindGamepadButton(Gamepad::Button button, std::string command, float value); }; #endif // GameWorld_h__ diff --git a/src/InputManager.cpp b/src/InputManager.cpp index c5509c0..ea22d96 100644 --- a/src/InputManager.cpp +++ b/src/InputManager.cpp @@ -1,6 +1,12 @@ #include "PrecompiledHeader.h" #include "InputManager.h" +void InputManager::Initialize() +{ + m_LastGamepadAxisState = std::array(); + m_LastGamepadButtonState = std::array(); +} + void InputManager::Update(double dt) { m_LastKeyState = m_CurrentKeyState; @@ -19,13 +25,13 @@ void InputManager::Update(double dt) { Events::KeyDown e; e.KeyCode = i; - m_EventBroker->Publish(e); + m_EventBroker->Publish(e); } else { Events::KeyUp e; e.KeyCode = i; - m_EventBroker->Publish(e); + m_EventBroker->Publish(e); } } } @@ -45,7 +51,7 @@ void InputManager::Update(double dt) e.Button = i; e.X = x; e.Y = y; - m_EventBroker->Publish(e); + m_EventBroker->Publish(e); } else { @@ -53,12 +59,12 @@ void InputManager::Update(double dt) e.Button = i; e.X = x; e.Y = y; - m_EventBroker->Publish(e); + m_EventBroker->Publish(e); } } } - // Cursor position + // Mouse movement glfwGetCursorPos(m_GLFWWindow, &m_CurrentMouseX, &m_CurrentMouseY); m_CurrentMouseDeltaX = m_CurrentMouseX - m_LastMouseX; m_CurrentMouseDeltaY = m_CurrentMouseY - m_LastMouseY; @@ -70,7 +76,7 @@ void InputManager::Update(double dt) e.Y = m_CurrentMouseY; e.DeltaX = m_CurrentMouseDeltaX; e.DeltaY = m_CurrentMouseDeltaY; - m_EventBroker->Publish(e); + m_EventBroker->Publish(e); } // // Lock mouse while holding LMB @@ -89,4 +95,102 @@ void InputManager::Update(double dt) // { // glfwSetInputMode(m_GLFWWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL); // } + + // Xbox360 controller + using namespace Windows; + DWORD dwResult; + for (int i = 0; i < XUSER_MAX_COUNT; i++) + { + XINPUT_STATE state = { 0 }; + // Simply get the state of the controller from XInput. + dwResult = XInputGetState(i, &state); + if (dwResult == 0) + { + m_CurrentGamepadAxisState[i][static_cast(Gamepad::Axis::LeftX)] = state.Gamepad.sThumbLX / 32767.f; + m_CurrentGamepadAxisState[i][static_cast(Gamepad::Axis::LeftY)] = state.Gamepad.sThumbLY / 32767.f; + m_CurrentGamepadAxisState[i][static_cast(Gamepad::Axis::RightX)] = state.Gamepad.sThumbRX / 32767.f; + m_CurrentGamepadAxisState[i][static_cast(Gamepad::Axis::RightY)] = state.Gamepad.sThumbRY / 32767.f; + m_CurrentGamepadAxisState[i][static_cast(Gamepad::Axis::LeftTrigger)] = state.Gamepad.bLeftTrigger / 255.f; + m_CurrentGamepadAxisState[i][static_cast(Gamepad::Axis::RightTrigger)] = state.Gamepad.bRightTrigger / 255.f; + PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftX); + PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftY); + PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightX); + PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightY); + PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftTrigger); + PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightTrigger); + + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Up)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Down)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Left)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Right)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Start)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_START); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Back)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::LeftThumb)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::RightThumb)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::LeftShoulder)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::RightShoulder)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::A)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_A); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::B)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_B); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::X)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_X); + m_CurrentGamepadButtonState[i][static_cast(Gamepad::Button::Y)] = static_cast(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Up); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Down); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Left); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Right); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Start); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Back); + PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftThumb); + PublishGamepadButtonIfChanged(i, Gamepad::Button::RightThumb); + PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftShoulder); + PublishGamepadButtonIfChanged(i, Gamepad::Button::RightShoulder); + PublishGamepadButtonIfChanged(i, Gamepad::Button::A); + PublishGamepadButtonIfChanged(i, Gamepad::Button::B); + PublishGamepadButtonIfChanged(i, Gamepad::Button::X); + PublishGamepadButtonIfChanged(i, Gamepad::Button::Y); + } + } + + m_LastKeyState = m_CurrentKeyState; + m_LastMouseState = m_CurrentMouseState; + m_LastMouseX = m_CurrentMouseX; + m_LastMouseY = m_CurrentMouseY; + m_LastGamepadAxisState = m_CurrentGamepadAxisState; + m_LastGamepadButtonState = m_CurrentGamepadButtonState; +} + +void InputManager::PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis) +{ + float currentValue = m_CurrentGamepadAxisState[gamepadID][static_cast(axis)]; + float lastValue = m_LastGamepadAxisState[gamepadID][static_cast(axis)]; + if (currentValue != lastValue) + { + Events::GamepadAxis e; + e.GamepadID = gamepadID; + e.Axis = axis; + e.Value = currentValue; + m_EventBroker->Publish(e); + } +} + +void InputManager::PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button) +{ + bool currentState = m_CurrentGamepadButtonState[gamepadID][static_cast(button)]; + float lastState = m_LastGamepadButtonState[gamepadID][static_cast(button)]; + if (currentState != lastState) + { + if (currentState == true) + { + Events::GamepadButtonDown e; + e.GamepadID = gamepadID; + e.Button = button; + m_EventBroker->Publish(e); + } + else + { + Events::GamepadButtonUp e; + e.GamepadID = gamepadID; + e.Button = button; + m_EventBroker->Publish(e); + } + } } diff --git a/src/InputManager.h b/src/InputManager.h index 5acaaa2..189430f 100644 --- a/src/InputManager.h +++ b/src/InputManager.h @@ -3,12 +3,21 @@ #include +namespace Windows +{ +#include +#undef min +#undef max +} + #include "EventBroker.h" #include "Events/KeyDown.h" #include "Events/KeyUp.h" #include "Events/MousePress.h" #include "Events/MouseRelease.h" #include "Events/MouseMove.h" +#include "Events/GamepadAxis.h" +#include "Events/GamepadButton.h" class InputManager { @@ -22,7 +31,10 @@ public: , m_LastMouseState() , m_CurrentMouseX(0), m_CurrentMouseY(0) , m_LastMouseX(0), m_LastMouseY(0) - , m_CurrentMouseDeltaX(0), m_CurrentMouseDeltaY(0) { } + , m_CurrentMouseDeltaX(0), m_CurrentMouseDeltaY(0) + { Initialize(); } + + void Initialize(); void Update(double dt); @@ -34,9 +46,19 @@ private: std::array m_LastKeyState; std::array m_CurrentMouseState; std::array m_LastMouseState; + typedef std::array(Gamepad::Axis::LAST) + 1> GamepadAxisState; + std::array m_CurrentGamepadAxisState; + std::array m_LastGamepadAxisState; + typedef std::array(Gamepad::Button::LAST) + 1> GamepadButtonState; + std::array m_CurrentGamepadButtonState; + std::array m_LastGamepadButtonState; + double m_CurrentMouseX, m_CurrentMouseY; double m_LastMouseX, m_LastMouseY; double m_CurrentMouseDeltaX, m_CurrentMouseDeltaY; + + void PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis); + void PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button); }; #endif // InputManager_h__ diff --git a/src/Model.cpp b/src/Model.cpp index 547e940..753ec65 100755 --- a/src/Model.cpp +++ b/src/Model.cpp @@ -1,7 +1,7 @@ #include "PrecompiledHeader.h" #include "Model.h" -Model::Model(OBJ &obj, ResourceManager* rm) +Model::Model(ResourceManager* rm, OBJ &obj) { OBJ::MaterialInfo* currentMaterial = nullptr; TextureGroup* currentTexGroup = nullptr; diff --git a/src/Model.h b/src/Model.h index 8d94a7d..dcf41d9 100755 --- a/src/Model.h +++ b/src/Model.h @@ -17,7 +17,7 @@ class Model : public Resource { public: - Model(OBJ &obj, ResourceManager* rm); + Model(ResourceManager* rm, OBJ &obj); struct TextureGroup { diff --git a/src/OBJ.cpp b/src/OBJ.cpp index a8b9f03..d8f91bf 100755 --- a/src/OBJ.cpp +++ b/src/OBJ.cpp @@ -9,7 +9,7 @@ bool OBJ::LoadFromFile(std::string filename) std::ifstream file(m_Path.string()); if (!file.is_open()) { - LOG_ERROR("Failed to open .obj \"%s\"", m_Path.string().c_str()); + LOG_ERROR("Failed to open .obj \"%s\": %s", m_Path.string().c_str(), strerror(errno)); return false; } diff --git a/src/OBJ.h b/src/OBJ.h index 2ef10e0..8ae9a32 100755 --- a/src/OBJ.h +++ b/src/OBJ.h @@ -12,7 +12,9 @@ #include #include -class OBJ +#include "ResourceManager.h" + +class OBJ : public Resource { public: struct MaterialInfo diff --git a/src/Physics/VehicleSetup.cpp b/src/Physics/VehicleSetup.cpp index 1768b1e..90e65dc 100644 --- a/src/Physics/VehicleSetup.cpp +++ b/src/Physics/VehicleSetup.cpp @@ -48,7 +48,6 @@ void VehicleSetup::buildVehicle(World *world, const hkpWorld* physicsWorld, hkpV setupWheelCollide(physicsWorld, vehicle, *static_cast(vehicle.m_wheelCollide)); - // // Check that all components are present. // @@ -105,7 +104,7 @@ void VehicleSetup::setupVehicleData(const hkpWorld* world, hkpVehicleData& data data.m_torquePitchFactor = 0.5f; data.m_torqueYawFactor = 0.35f; - data.m_chassisUnitInertiaYaw = 1.0f; + data.m_chassisUnitInertiaYaw = 0.8f; data.m_chassisUnitInertiaRoll = 1.0f; data.m_chassisUnitInertiaPitch = 1.0f; @@ -165,7 +164,7 @@ void VehicleSetup::setupComponent(const hkpVehicleData& data, hkpVehicleDefaultS // [mph/h] The steering angle decreases linearly // based on your overall max speed of the vehicle. - steering.m_maxSpeedFullSteeringAngle = 70.0f * (1.605f / 3.6f); //MPH???! + steering.m_maxSpeedFullSteeringAngle = vehicleComponent.MaxSpeedFullSteeringAngle; // * (1.605f / 3.6f); //MPH???! for (int i = 0; i < m_Wheels.size(); i++) { @@ -198,20 +197,21 @@ void VehicleSetup::setupComponent(const hkpVehicleData& data, hkpVehicleDefaultT transmission.m_gearsRatio.setSize(numberOfGears); transmission.m_wheelsTorqueRatio.setSize(data.m_numWheels); - transmission.m_downshiftRPM = 3500.0f; - transmission.m_upshiftRPM = 6500.0f; + transmission.m_downshiftRPM = 3500.0f; //HACK: Should be in VehicleComponent + transmission.m_upshiftRPM = 7000.0f; transmission.m_clutchDelayTime = 0.0f; - transmission.m_reverseGearRatio = 1.0f; - transmission.m_gearsRatio[0] = 2.0f; - transmission.m_gearsRatio[1] = 1.5f; - transmission.m_gearsRatio[2] = 1.0f; - transmission.m_gearsRatio[3] = 0.75f; - transmission.m_wheelsTorqueRatio[0] = 0.2f; - transmission.m_wheelsTorqueRatio[1] = 0.2f; - transmission.m_wheelsTorqueRatio[2] = 0.3f; - transmission.m_wheelsTorqueRatio[3] = 0.3f; - + transmission.m_reverseGearRatio = 1.2f; + transmission.m_gearsRatio[0] = 3.0f; + transmission.m_gearsRatio[1] = 2.25f; + transmission.m_gearsRatio[2] = 1.5f; + transmission.m_gearsRatio[3] = 1.0f; + + for(int i = 0; i < m_Wheels.size(); i++) + { + // The wheels total TorqueRatio must be equal to 1 + transmission.m_wheelsTorqueRatio[i] = m_Wheels[i].WheelComponent->TorqueRatio; + } transmission.m_primaryTransmissionRatio = hkpVehicleDefaultTransmission::calculatePrimaryTransmissionRatio( vehicleComponent.TopSpeed, @@ -246,9 +246,8 @@ void VehicleSetup::setupComponent(const hkpVehicleData& data, hkpVehicleDefaultS suspension.m_wheelParams[i].m_length = suspensionLength; suspension.m_wheelSpringParams[i].m_strength = m_Wheels[i].WheelComponent->SuspensionStrength; - const float wd = 3.0f; - suspension.m_wheelSpringParams[i].m_dampingCompression = wd; - suspension.m_wheelSpringParams[i].m_dampingRelaxation = wd; + suspension.m_wheelSpringParams[i].m_dampingCompression = vehicleComponent.SpringDamping; + suspension.m_wheelSpringParams[i].m_dampingRelaxation = vehicleComponent.SpringDamping; suspension.m_wheelParams[i].m_hardpointChassisSpace.set(m_Wheels[i].WheelComponent->Hardpoint.x, m_Wheels[i].WheelComponent->Hardpoint.y, m_Wheels[i].WheelComponent->Hardpoint.z); @@ -267,7 +266,7 @@ void VehicleSetup::setupComponent(const hkpVehicleData& data, hkpVehicleDefaultA aerodynamics.m_liftCoefficient = -0.3f; // Extra gavity applies in world space (independent of m_chassisCoordinateSystem). - aerodynamics.m_extraGravityws.set(0.0f, -5.0f, 0.0f); + aerodynamics.m_extraGravityws.set(0.0f, -8.0f, 0.0f); // fuck this shit } void VehicleSetup::setupComponent(const hkpVehicleData& data, hkpVehicleDefaultVelocityDamper& velocityDamper, Components::Vehicle vehicleComponent) diff --git a/src/Physics/VehicleSetup.h b/src/Physics/VehicleSetup.h index b54adbd..7f78204 100644 --- a/src/Physics/VehicleSetup.h +++ b/src/Physics/VehicleSetup.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -42,8 +43,9 @@ public: { Components::Wheel* WheelComponent; Components::Transform* TransformComponent; - }; + }; + std::vector m_Wheels; virtual void setupVehicleData(const hkpWorld* world, hkpVehicleData& data); @@ -58,6 +60,7 @@ public: virtual void setupComponent(const hkpVehicleData& data, hkpVehicleDefaultVelocityDamper& velocityDamper, Components::Vehicle vehicleComponent); virtual void setupWheelCollide(const hkpWorld* world, const hkpVehicleInstance& vehicle, hkpVehicleRayCastWheelCollide& wheelCollide); + }; #endif // Physics_Vehicle_h__ diff --git a/src/Renderer.cpp b/src/Renderer.cpp index 3e30e30..3498e93 100755 --- a/src/Renderer.cpp +++ b/src/Renderer.cpp @@ -13,12 +13,15 @@ Renderer::Renderer() m_DrawWireframe = false; m_DrawBounds = false; #endif - - m_ShadowMapRes = 2048; + Gamma = 2.2f; + CAtt = 1.0f; + LAtt = 0.0f; + QAtt = 3.0f; + m_ShadowMapRes = 2048*8; m_SunPosition = glm::vec3(0, 3.5f, 10); m_SunTarget = glm::vec3(0, 0, 0); - m_SunProjection = glm::ortho(-100, 100, -100, 100, -100, 100); - Lights = 0; + m_SunProjection = glm::ortho(-200.f, 200.f, -200.f, 200.f, -100, 200); +/* Lights = 0;*/ } void Renderer::Initialize() @@ -76,7 +79,7 @@ void Renderer::Initialize() void Renderer::LoadContent() { - auto standardVS = std::shared_ptr(new VertexShader("Shaders/Vertex.glsl")); + /*auto standardVS = std::shared_ptr(new VertexShader("Shaders/Vertex.glsl")); auto standardFS = std::shared_ptr(new FragmentShader("Shaders/Fragment.glsl")); m_ShaderProgram.AddShader(standardVS); @@ -89,12 +92,7 @@ void Renderer::LoadContent() m_ShaderProgramNormals.AddShader(std::shared_ptr(new FragmentShader("Shaders/Normals.frag.glsl"))); m_ShaderProgramNormals.Compile(); m_ShaderProgramNormals.Link(); - - m_ShaderProgramShadows.AddShader(std::shared_ptr(new VertexShader("Shaders/ShadowMap.vert.glsl"))); - m_ShaderProgramShadows.AddShader(std::shared_ptr(new FragmentShader("Shaders/ShadowMap.frag.glsl"))); - m_ShaderProgramShadows.Compile(); - m_ShaderProgramShadows.Link(); - + m_ShaderProgramShadowsDrawDepth.AddShader(std::shared_ptr(new VertexShader("Shaders/VisualizeDepth.vert.glsl"))); m_ShaderProgramShadowsDrawDepth.AddShader(std::shared_ptr(new FragmentShader("Shaders/VisualizeDepth.frag.glsl"))); m_ShaderProgramShadowsDrawDepth.Compile(); @@ -108,13 +106,124 @@ void Renderer::LoadContent() m_ShaderProgramSkybox.AddShader(std::shared_ptr(new VertexShader("Shaders/Skybox.vert.glsl"))); m_ShaderProgramSkybox.AddShader(std::shared_ptr(new FragmentShader("Shaders/Skybox.frag.glsl"))); m_ShaderProgramSkybox.Compile(); - m_ShaderProgramSkybox.Link(); + m_ShaderProgramSkybox.Link();*/ - m_Skybox = std::make_shared("Textures/Skybox/Sunset", "jpg"); + m_ShaderProgramShadows.AddShader(std::shared_ptr(new VertexShader("Shaders/ShadowMap.vert.glsl"))); + m_ShaderProgramShadows.AddShader(std::shared_ptr(new FragmentShader("Shaders/ShadowMap.frag.glsl"))); + m_ShaderProgramShadows.Compile(); + m_ShaderProgramShadows.Link(); - m_DebugAABB = CreateAABB(); + m_FirstPassProgram.AddShader(std::shared_ptr(new VertexShader("Shaders/Vertex.glsl"))); + m_FirstPassProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/Fragment.glsl"))); + m_FirstPassProgram.Compile(); + + glBindFragDataLocation(m_FirstPassProgram.GetHandle(), 0, "frag_Diffuse"); + glBindFragDataLocation(m_FirstPassProgram.GetHandle(), 1, "frag_Position"); + glBindFragDataLocation(m_FirstPassProgram.GetHandle(), 2, "frag_Normal"); + m_FirstPassProgram.Link(); + + m_SecondPassProgram.AddShader(std::shared_ptr(new VertexShader("Shaders/Vertex2.glsl"))); + m_SecondPassProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/Fragment2.glsl"))); + m_SecondPassProgram.Compile(); + m_SecondPassProgram.Link(); + + m_SecondPassProgram_Debug.AddShader(std::shared_ptr(new VertexShader("Shaders/Vertex2.glsl"))); + m_SecondPassProgram_Debug.AddShader(std::shared_ptr(new FragmentShader("Shaders/Fragment2-Debug.glsl"))); + m_SecondPassProgram_Debug.Compile(); + m_SecondPassProgram_Debug.Link(); + + m_FinalPassProgram.AddShader(std::shared_ptr(new VertexShader("Shaders/FinalPass.vert.glsl"))); + m_FinalPassProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/FinalPass.frag.glsl"))); + m_FinalPassProgram.Compile(); + m_FinalPassProgram.Link(); m_ScreenQuad = CreateQuad(); CreateShadowMap(m_ShadowMapRes); + FrameBufferTextures(); +} + +void Renderer::Draw(double dt) +{ + if(glfwGetKey(m_Window, GLFW_KEY_F1)) + { + m_QuadView = false; + } + if(glfwGetKey(m_Window, GLFW_KEY_F2)) + { + m_QuadView = true; + } + + if(glfwGetKey(m_Window, GLFW_KEY_KP_1)) + { + Gamma -= 0.3f * dt; + LOG_INFO("Gamma_UP: %f", Gamma); + } + if(glfwGetKey(m_Window, GLFW_KEY_KP_4)) + { + Gamma += 0.3f * dt; + LOG_INFO("Gamma_DOWN: %f", Gamma); + } + + if(glfwGetKey(m_Window, GLFW_KEY_1)) + { + if(glfwGetKey(m_Window, GLFW_KEY_KP_ADD)) + { + CAtt += 0.5f * dt; + LOG_INFO("Const: %f", CAtt); + } + if(glfwGetKey(m_Window, GLFW_KEY_KP_SUBTRACT)) + { + CAtt -= 0.5f * dt; + LOG_INFO("Const: %f", CAtt); + } + } + if(glfwGetKey(m_Window, GLFW_KEY_2)) + { + if(glfwGetKey(m_Window, GLFW_KEY_KP_ADD)) + { + LAtt += 0.5f * dt; + LOG_INFO("Linear: %f", LAtt); + } + if(glfwGetKey(m_Window, GLFW_KEY_KP_SUBTRACT)) + { + LAtt -= 0.5f * dt; + LOG_INFO("Linear: %f", LAtt); + } + } + if(glfwGetKey(m_Window, GLFW_KEY_3)) + { + if(glfwGetKey(m_Window, GLFW_KEY_KP_ADD)) + { + QAtt += 0.5f * dt; + LOG_INFO("Quadratic: %f", QAtt); + } + if(glfwGetKey(m_Window, GLFW_KEY_KP_SUBTRACT)) + { + QAtt -= 0.5f * dt; + LOG_INFO("Quadratic: %f", QAtt); + } + } + + glDisable(GL_BLEND); + + DrawFBO(); + + ClearStuff(); + glfwSwapBuffers(m_Window); +} + +#pragma region TempRegion + +void Renderer::DrawSkybox() +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, m_Width, m_Height); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m_ShaderProgramSkybox.Bind(); + glm::mat4 cameraMatrix = m_Camera->ProjectionMatrix() * glm::toMat4(glm::inverse(m_Camera->Orientation())); + glUniformMatrix4fv(glGetUniformLocation(m_ShaderProgramSkybox.GetHandle(), "MVP"), 1, GL_FALSE, glm::value_ptr(cameraMatrix)); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + m_Skybox->Draw(); } void Renderer::CreateShadowMap(int resolution) @@ -137,169 +246,35 @@ void Renderer::CreateShadowMap(int resolution) glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_ShadowDepthTexture, 0); glDrawBuffer(GL_NONE); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - { + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { LOG_ERROR("Framebuffer incomplete!"); return; + } } -void Renderer::Draw(double dt) -{ - glDisable(GL_BLEND); - - DrawSkybox(); - DrawShadowMap(); - DrawScene(); - -#ifdef DEBUG - // Draw bounding boxes - if (m_DrawBounds) - { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); - m_ShaderProgramDebugAABB.Bind(); - for (auto tuple : AABBsToRender) - { - glm::mat4 modelMatrix; - bool colliding; - std::tie(modelMatrix, colliding) = tuple; - // Model matrix - glm::mat4 cameraMatrix = m_Camera->ProjectionMatrix() * m_Camera->ViewMatrix(); - glm::mat4 MVP = cameraMatrix * modelMatrix; - glUniformMatrix4fv(glGetUniformLocation(m_ShaderProgramDebugAABB.GetHandle(), "MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); - // Color - glm::vec4 color(1.f, 1.f, 1.f, 0.f); - if (colliding) - color = glm::vec4(1.f, 0.f, 0.f, 0.f); - glUniform4fv(glGetUniformLocation(m_ShaderProgramDebugAABB.GetHandle(), "Color"), 1, glm::value_ptr(color)); - glBindVertexArray(m_DebugAABB); - glDrawArrays(GL_LINES, 0, 24); - } - } - - DrawDebugShadowMap(); -#endif - - ClearStuff(); - glfwSwapBuffers(m_Window); -} - -void Renderer::DrawSkybox() -{ - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glViewport(0, 0, m_Width, m_Height); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - m_ShaderProgramSkybox.Bind(); - glm::mat4 cameraMatrix = m_Camera->ProjectionMatrix() * glm::toMat4(glm::inverse(m_Camera->Orientation())); - glUniformMatrix4fv(glGetUniformLocation(m_ShaderProgramSkybox.GetHandle(), "MVP"), 1, GL_FALSE, glm::value_ptr(cameraMatrix)); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - m_Skybox->Draw(); -} - -void Renderer::DrawScene() -{ - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glViewport(0, 0, m_Width, m_Height); - - glClear(GL_DEPTH_BUFFER_BIT); - //glClearColor(1.0f, 1.0f, 0.0f, 1.0f); - - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); -#ifdef DEBUG - glDisable(GL_CULL_FACE); - glPolygonMode(GL_BACK, GL_LINE); -#endif - - // Draw models - glm::mat4 depthViewMatrix = glm::lookAt(m_SunPosition, m_SunTarget, glm::vec3(0, 1, 0)) * glm::translate(-m_Camera->Position() * glm::vec3(1, 0, 0)); - glm::mat4 depthCamera = m_SunProjection * depthViewMatrix; - glm::mat4 biasMatrix( - 0.5, 0.0, 0.0, 0.0, - 0.0, 0.5, 0.0, 0.0, - 0.0, 0.0, 0.5, 0.0, - 0.5, 0.5, 0.5, 1.0 - ); - - m_ShaderProgram.Bind(); - glUniform1i(glGetUniformLocation(m_ShaderProgram.GetHandle(), "numberOfLights"), Lights); - glUniform3fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "position"), Lights, Light_position.data()); - glUniform3fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "specular"), Lights, Light_specular.data()); - glUniform3fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "diffuse"), Lights, Light_diffuse.data()); - glUniform1fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "constantAttenuation"), Lights, Light_constantAttenuation.data()); - glUniform1fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "linearAttenuation"), Lights, Light_linearAttenuation.data()); - glUniform1fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "quadraticAttenuation"), Lights, Light_quadraticAttenuation.data()); - glUniform1fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "spotExponent"), Lights, Light_spotExponent.data()); - if (m_DrawWireframe) - { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, m_ShadowDepthTexture); - //DrawModels(m_ShaderProgram); - glm::mat4 cameraMatrix = m_Camera->ProjectionMatrix() * m_Camera->ViewMatrix(); - glm::mat4 depthCameraMatrix = biasMatrix * depthCamera; - glm::mat4 MVP; - glm::mat4 depthMVP; - for (auto tuple : ModelsToRender) - { - Model* model; - glm::mat4 modelMatrix; - bool visible; - std::tie(model, modelMatrix, visible, std::ignore) = tuple; - if (!visible) - continue; - - MVP = cameraMatrix * modelMatrix; - depthMVP = depthCameraMatrix * modelMatrix; - glUniformMatrix4fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); - glUniformMatrix4fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "DepthMVP"), 1, GL_FALSE, glm::value_ptr(depthMVP)); - glUniformMatrix4fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "model"), 1, GL_FALSE, glm::value_ptr(modelMatrix)); - glUniformMatrix4fv(glGetUniformLocation(m_ShaderProgram.GetHandle(), "view"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); - glBindVertexArray(model->VAO); - for (auto texGroup : model->TextureGroups) - { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, *texGroup.Texture); - glDrawArrays(GL_TRIANGLES, texGroup.StartIndex, texGroup.EndIndex - texGroup.StartIndex + 1); - } - } - -#ifdef DEBUG - // Debug draw model normals - if (m_DrawNormals) - { - m_ShaderProgramNormals.Bind(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - DrawModels(m_ShaderProgramNormals); - } -#endif -} void Renderer::DrawShadowMap() { - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - glCullFace(GL_FRONT); + glEnable(GL_DEPTH_TEST);//Tests where objects are and display them correctly + glEnable(GL_CULL_FACE); //removes triangles on the wrong side of the object + glCullFace(GL_BACK); //Make it so that only the back faces are rendered + //Binds the FBO and sets the veiwport, witch in effect is how large the shadowmap is and what resolution it has. glBindFramebuffer(GL_FRAMEBUFFER, m_ShadowFrameBuffer); glViewport(0, 0, m_ShadowMapRes, m_ShadowMapRes); glClear(GL_DEPTH_BUFFER_BIT); //glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glm::mat4 depthViewMatrix = glm::lookAt(m_SunPosition, m_SunTarget, glm::vec3(0, 1, 0)) * glm::translate(-m_Camera->Position() * glm::vec3(1, 0, 0)); -// glm::mat4 depthViewMatrix = glm::lookAt(m_SunPosition, m_SunTarget, glm::vec3(0, 1, 0)); + //Creates the "camera" for the shadowmap from the direction of the sun. + glm::mat4 depthViewMatrix = glm::lookAt(m_SunPosition, m_SunTarget, glm::vec3(0, 1, 0)); glm::mat4 depthCamera = m_SunProjection * depthViewMatrix; - - //glm::mat4 cameraMatrix = depthProjectionMatrix * m_Camera->ViewMatrix(); - glm::mat4 MVP; m_ShaderProgramShadows.Bind(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //Draws filled polygons + + //For each model, render them to the shadowmap for (auto tuple : ModelsToRender) { Model* model; @@ -318,6 +293,8 @@ void Renderer::DrawShadowMap() glDrawArrays(GL_TRIANGLES, texGroup.StartIndex, texGroup.EndIndex - texGroup.StartIndex + 1); } } + + } void Renderer::DrawDebugShadowMap() @@ -376,30 +353,44 @@ void Renderer::AddModelToDraw(Model* model, glm::vec3 position, glm::quat orient ModelsToRender.push_back(std::make_tuple(model, modelMatrix, visible, shadowCaster)); } +void Renderer::AddTextureToDraw(Texture* texture, glm::vec3 position, glm::quat orientation, glm::vec3 scale) +{ + glm::mat4 modelMatrix = glm::translate(glm::mat4(), position) * glm::toMat4(orientation) * glm::scale(scale); + + glm::vec3 camToParticle = glm::normalize(m_Camera->Position() - position); + glm::vec3 up = glm::vec3(0,1,0); + glm::vec3 rightVec = glm::normalize(glm::cross(up, camToParticle)); + glm::vec3 up2 = glm::normalize(glm::cross(camToParticle, rightVec)); + + glm::mat4 billboardMatrix; + billboardMatrix[0] = glm::vec4(rightVec, 0); + billboardMatrix[1] = glm::vec4(up2, 0); + billboardMatrix[2] = glm::vec4(camToParticle, 0); + //billboardMatrix[3] = glm::vec4(position, 0); + + TexturesToRender.push_back(std::make_tuple(texture, modelMatrix, billboardMatrix)); +} + void Renderer::AddPointLightToDraw( glm::vec3 _position, glm::vec3 _specular, glm::vec3 _diffuse, - float _constantAttenuation, - float _linearAttenuation, - float _quadraticAttenuation, - float _spotExponent + float _specularExponent, + float _ConstantAttenuation, + float _LinearAttenuation, + float _QuadraticAttenuation ) { - Light_position.push_back(_position.x); - Light_position.push_back(_position.y); - Light_position.push_back(_position.z); - Light_specular.push_back(_specular.x); - Light_specular.push_back(_specular.y); - Light_specular.push_back(_specular.z); - Light_diffuse.push_back(_diffuse.x); - Light_diffuse.push_back(_diffuse.y); - Light_diffuse.push_back(_diffuse.z); - Light_constantAttenuation.push_back(_constantAttenuation); - Light_linearAttenuation.push_back(_linearAttenuation); - Light_quadraticAttenuation.push_back(_quadraticAttenuation); - Light_spotExponent.push_back(_spotExponent); - Lights = Light_constantAttenuation.size(); + Light light; + light.Position = _position; + light.Diffuse = _diffuse; + light.Specular = _specular; + light.SpecularExponent = _specularExponent; + light.ConstantAttenuation = _ConstantAttenuation; + light.LinearAttenuation = _LinearAttenuation; + light.QuadraticAttenuation = _QuadraticAttenuation; + light.SphereModelMatrix = CreateLightMatrix(light); + Lights.push_back(light); } void Renderer::AddAABBToDraw(glm::vec3 origin, glm::vec3 volumeVector, bool colliding) @@ -532,16 +523,306 @@ GLuint Renderer::CreateSkybox() return vao; } + void Renderer::ClearStuff() { AABBsToRender.clear(); ModelsToRender.clear(); - Light_position.clear(); - Light_specular.clear(); - Light_diffuse.clear(); - Light_constantAttenuation.clear(); - Light_linearAttenuation.clear(); - Light_quadraticAttenuation.clear(); - Light_spotExponent.clear(); - Lights = 0; -} \ No newline at end of file + TexturesToRender.clear(); + Lights.clear(); +} + +#pragma endregion + +void Renderer::FrameBufferTextures() +{ + m_fbBasePass = 0; + m_fDepthBuffer = 0; + + glGenFramebuffers(1, &m_fbBasePass); + glGenRenderbuffers(1, &m_fDepthBuffer); + + glBindRenderbuffer(GL_RENDERBUFFER, m_fDepthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Width, m_Height); + + //Generate and bind diffuse texture + glGenTextures(1, &m_fDiffuseTexture); + glBindTexture(GL_TEXTURE_2D, m_fDiffuseTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_Width, m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + //Generate and bind position texture + glGenTextures(1, &m_fPositionTexture); + glBindTexture(GL_TEXTURE_2D, m_fPositionTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_Width, m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + //Generate and bind normal texture + glGenTextures(1, &m_fNormalsTexture); + glBindTexture(GL_TEXTURE_2D, m_fNormalsTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, m_Width, m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + /*glGenTextures(1, &m_fShadowTexture); + glBindTexture(GL_TEXTURE_2D, m_fShadowTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, m_Width, m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);*/ + + //Bind fb + glBindFramebuffer(GL_FRAMEBUFFER, m_fbBasePass); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_fDepthBuffer); + + //Attach textures to the FB + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_fDiffuseTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_fPositionTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, m_fNormalsTexture, 0); + //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, m_fShadowTexture, 0); + + GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if(fbStatus != GL_FRAMEBUFFER_COMPLETE) + { + LOG_ERROR("DeferredLighting:Init: m_fbBasePass incomplete: 0x%x\n", fbStatus); + //exit(1); + } + + m_fbLightingPass = 0; + glGenFramebuffers(1, &m_fbLightingPass); + + glGenTextures(1, &m_fLightingTexture); + glBindTexture(GL_TEXTURE_2D, m_fLightingTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_Width, m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glBindFramebuffer(GL_FRAMEBUFFER, m_fbLightingPass); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_fLightingTexture, 0); + + fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if(fbStatus != GL_FRAMEBUFFER_COMPLETE) + { + LOG_ERROR("DeferredLighting:Init: m_fbLightingPass incomplete: 0x%x\n", fbStatus); + //exit(1); + } + + + +} + +void Renderer::DrawFBO() +{ + DrawShadowMap(); + + /* + Base pass + */ + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbBasePass); + + // Clear G-buffer + GLenum windowBuffClear[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; + glDrawBuffers(3, windowBuffClear); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Execute the first render stage which will fill out the internal buffers with data(??) + m_FirstPassProgram.Bind(); + GLenum windowBuffOpaque[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; + glDrawBuffers(3, windowBuffOpaque); + + glCullFace(GL_BACK); + + glViewport(0, 0, m_Width, m_Height); + DrawFBOScene(); + + /* + Lighting pass + */ + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbLightingPass); + GLenum lightingPassAttachments[] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, lightingPassAttachments); + + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + + m_SecondPassProgram.Bind(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_fPositionTexture); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, m_fNormalsTexture); + + glCullFace(GL_FRONT); + DrawLightScene(); + + /* + Final pass + */ + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + m_FinalPassProgram.Bind(); + + // Ambient light + glUniform3fv(glGetUniformLocation(m_FinalPassProgram.GetHandle(), "La"), 1, glm::value_ptr(glm::vec3(0.1f, 0.1f, 0.1f))); + glUniform1f(glGetUniformLocation(m_FinalPassProgram.GetHandle(), "Gamma"), Gamma); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_fDiffuseTexture); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, m_fLightingTexture); + + glCullFace(GL_BACK); + glBindVertexArray(m_ScreenQuad); + glEnableVertexAttribArray(0); + glDrawArrays(GL_TRIANGLES, 0, 6); +} + +void Renderer::DrawFBOScene() +{ +// glEnable(GL_DEPTH_TEST);//Tests where objects are and display them correctly +// glEnable(GL_CULL_FACE); //removes triangles on the wrong side of the object +// glCullFace(GL_BACK); //Make it so that only the back faces are rendered + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //Draws filled polygons + + glm::mat4 cameraMatrix = m_Camera->ProjectionMatrix() * m_Camera->ViewMatrix(); + glm::mat4 MVP; + glm::mat4 biasMatrix( + 0.5, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.5, 0.5, 0.5, 1.0 + ); + + glm::mat4 depthViewMatrix = glm::lookAt(m_SunPosition, m_SunTarget, glm::vec3(0, 1, 0)); + glm::mat4 depthCamera = m_SunProjection * depthViewMatrix; + glm::mat4 depthCameraMatrix = biasMatrix * depthCamera; + glm::mat4 depthMVP; + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, m_ShadowDepthTexture); + + for (auto tuple : ModelsToRender) + { + Model* model; + glm::mat4 modelMatrix; + bool visible; + std::tie(model, modelMatrix, visible, std::ignore) = tuple; + if (!visible) + continue; + + MVP = cameraMatrix * modelMatrix; + depthMVP = depthCameraMatrix * modelMatrix; + glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); + glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "DepthMVP"), 1, GL_FALSE, glm::value_ptr(depthMVP)); + glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix)); + glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix())); + glBindVertexArray(model->VAO); + for (auto texGroup : model->TextureGroups) + { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, *texGroup.Texture); + glDrawArrays(GL_TRIANGLES, texGroup.StartIndex, texGroup.EndIndex - texGroup.StartIndex + 1); + } + } + + for (auto tuple : TexturesToRender) + { + Texture* texture; + glm::mat4 modelMatrix; + glm::mat4 billboardMatrix; + std::tie(texture, modelMatrix, billboardMatrix) = tuple; + + //MVP = cameraMatrix * glm::inverse(glm::toMat4(m_Camera->Orientation()) * modelMatrix ); + MVP = cameraMatrix * modelMatrix * billboardMatrix; + + depthMVP = depthCameraMatrix * modelMatrix; + glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); + glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "DepthMVP"), 1, GL_FALSE, glm::value_ptr(depthMVP)); + glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix)); + glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(m_FirstPassProgram.GetHandle(), "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix())); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, *texture); + glBindVertexArray(m_ScreenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + } +} + + + +void Renderer::DrawLightScene() +{ + glEnable(GL_BLEND); + glBlendEquation (GL_FUNC_ADD); + glBlendFunc(GL_ONE,GL_ONE); + + glDisable (GL_DEPTH_TEST); + glDepthMask (GL_FALSE); + glBindVertexArray(m_sphereModel->VAO); + + glm::mat4 cameraMatrix = m_Camera->ProjectionMatrix() * m_Camera->ViewMatrix(); + glm::mat4 MVP; + + for (auto &light : Lights) + { + MVP = cameraMatrix * light.SphereModelMatrix; + + glUniform2fv(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "ViewportSize"), 1,glm::value_ptr(glm::vec2(m_Width, m_Height))); + glUniformMatrix4fv(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); + glUniformMatrix4fv(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix())); + glUniformMatrix4fv(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "M"), 1, GL_FALSE, glm::value_ptr(light.SphereModelMatrix)); + glUniform3fv(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "ls"), 1, glm::value_ptr(light.Specular)); + glUniform3fv(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "ld"), 1, glm::value_ptr(light.Diffuse)); + glUniform3fv(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "lp"), 1, glm::value_ptr(light.Position)); + glUniform3f(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "CameraPosition"), m_Camera->Position().x, m_Camera->Position().y, m_Camera->Position().z); + glUniform1f(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "specularExponent"), light.SpecularExponent); +// glUniform1f(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "ConstantAttenuation"), light.ConstantAttenuation); +// glUniform1f(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "LinearAttenuation"), light.LinearAttenuation); +// glUniform1f(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "QuadraticAttenuation"), light.QuadraticAttenuation); + glUniform1f(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "ConstantAttenuation"), CAtt); + glUniform1f(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "LinearAttenuation"), LAtt); + glUniform1f(glGetUniformLocation(m_SecondPassProgram.GetHandle(), "QuadraticAttenuation"), QAtt); + + glDrawArrays(GL_TRIANGLES, 0, m_sphereModel->Vertices.size()); + }; + glEnable (GL_DEPTH_TEST); + glDepthMask (GL_TRUE); + glDisable (GL_BLEND); +} + +void Renderer::SetSphereModel( Model* _model ) +{ + m_sphereModel = _model; +} + +glm::mat4 Renderer::CreateLightMatrix(Light &_light) +{ +// float c = _light.ConstantAttenuation; +// float l = _light.LinearAttenuation; +// float q = _light.QuadraticAttenuation; + float c = CAtt; + float l = LAtt; + float q = QAtt; + float cutOffRadius = abs(sqrt((-4*c*q) + pow(l, 2) + (1024*q) - l) / (2*q)); + + glm::mat4 model; + model *= glm::translate(_light.Position); + model *= glm::scale(glm::vec3(cutOffRadius)); + return model; +} + diff --git a/src/Renderer.h b/src/Renderer.h index 3c2d957..f462a09 100755 --- a/src/Renderer.h +++ b/src/Renderer.h @@ -12,6 +12,7 @@ #include "Model.h" #include "Components/PointLight.h" #include "Skybox.h" +#include "ResourceManager.h" class Renderer { @@ -25,14 +26,7 @@ public: int Height() const { return m_Height; } std::list> ModelsToRender; - int Lights; - std::vector Light_position; - std::vector Light_specular; - std::vector Light_diffuse; - std::vector Light_constantAttenuation; - std::vector Light_linearAttenuation; - std::vector Light_quadraticAttenuation; - std::vector Light_spotExponent; + std::list> TexturesToRender; std::list> AABBsToRender; Renderer(); @@ -42,15 +36,16 @@ public: void DrawText(); void AddModelToDraw(Model* model, glm::vec3 position, glm::quat orientation, glm::vec3 scale, bool visible, bool shadowCaster); + void AddTextureToDraw(Texture* texture, glm::vec3 position, glm::quat orientation, glm::vec3 scale); void AddTextToDraw(); void AddPointLightToDraw( glm::vec3 _position, glm::vec3 _specular, glm::vec3 _diffuse, - float _constantAttenuation, - float _linearAttenuation, - float _quadraticAttenuation, - float _spotExponent + float _specularExponent, + float _ConstantAttenuation, + float _LinearAttenuation, + float _QuadraticAttenuation ); void AddAABBToDraw(glm::vec3 origin, glm::vec3 volumeVector, bool colliding); @@ -67,8 +62,25 @@ public: void DrawBounds(bool val) { m_DrawBounds = val; } void DrawSkybox(); + void SetSphereModel(Model* _model); + private: int m_Width, m_Height; + + struct Light + { + glm::vec3 Position; + glm::vec3 Specular; + glm::vec3 Diffuse; + float SpecularExponent; + glm::mat4 SphereModelMatrix; + float ConstantAttenuation, LinearAttenuation, QuadraticAttenuation; + }; + + float Gamma; + + std::list Lights; + GLFWwindow* m_Window; GLint m_glVersion[2]; GLchar* m_glVendor; @@ -76,6 +88,7 @@ private: bool m_DrawNormals; bool m_DrawWireframe; bool m_DrawBounds; + float CAtt, LAtt, QAtt; std::shared_ptr m_Skybox; @@ -85,24 +98,53 @@ private: glm::mat4 m_SunProjection; GLuint m_DebugAABB; - GLuint m_ScreenQuad; GLuint m_ShadowFrameBuffer; GLuint m_ShadowDepthTexture; + GLuint m_fbBasePass; + GLuint m_fDiffuseTexture; + GLuint m_fPositionTexture; + GLuint m_fNormalsTexture; + GLuint m_fBlendTexture; + GLuint m_fbLightingPass; + GLuint m_fLightingTexture; + GLuint m_fShadowTexture; + + GLuint m_fDepthBuffer; + GLenum draw_bufs[2]; + GLuint m_ScreenQuad; + Model* m_sphereModel; + + bool m_QuadView; + std::shared_ptr m_Camera; ShaderProgram m_ShaderProgram; + ShaderProgram m_FirstPassProgram; + ShaderProgram m_SecondPassProgram; + ShaderProgram m_SecondPassProgram_Debug; + ShaderProgram m_FinalPassProgram; + ShaderProgram m_ShaderProgramNormals; ShaderProgram m_ShaderProgramShadows; ShaderProgram m_ShaderProgramShadowsDrawDepth; ShaderProgram m_ShaderProgramDebugAABB; ShaderProgram m_ShaderProgramSkybox; + + void ClearStuff(); void DrawScene(); void DrawModels(ShaderProgram &shader); void DrawShadowMap(); void CreateShadowMap(int resolution); + void FrameBufferTextures(); + void DrawFBO(); + void DrawFBOScene(); + void DrawLightScene(); + void BindFragDataLocation(); + glm::mat4 CreateLightMatrix(Light &_light); + GLuint CreateQuad(); void DrawDebugShadowMap(); GLuint CreateAABB(); diff --git a/src/ResourceManager.cpp b/src/ResourceManager.cpp index 1361c11..b4ff9bd 100644 --- a/src/ResourceManager.cpp +++ b/src/ResourceManager.cpp @@ -16,7 +16,7 @@ Resource* ResourceManager::CreateResource(std::string resourceType, std::string resource->TypeID = GetTypeID(resourceType); resource->ResourceID = GetNewResourceID(resource->TypeID); // Cache - m_ResourceCache[resourceName] = resource; + m_ResourceCache[std::make_pair(resourceType, resourceName)] = resource; return resource; } @@ -28,7 +28,7 @@ void ResourceManager::RegisterType(std::string resourceType, std::function #include +#include "Util/UnorderedMapPair.h" #include "Factory.h" class Resource @@ -28,7 +29,7 @@ public: void Preload(std::string resourceType, std::string resourceName); // Checks if a resource is in cache - bool IsResourceLoaded(std::string resourceName); + bool IsResourceLoaded(std::string resourceType, std::string resourceName); template // Hot-loads a resource and caches it for future use @@ -40,7 +41,7 @@ public: private: std::unordered_map> m_FactoryFunctions; // type -> factory function - std::unordered_map m_ResourceCache; // name -> resource + std::unordered_map, Resource*> m_ResourceCache; // (type, name) -> resource // TODO: Getters for IDs unsigned int m_CurrentResourceTypeID; @@ -60,7 +61,7 @@ private: template T* ResourceManager::Load(std::string resourceType, std::string resourceName) { - auto it = m_ResourceCache.find(resourceName); + auto it = m_ResourceCache.find(std::make_pair(resourceType, resourceName)); if (it != m_ResourceCache.end()) return static_cast(it->second); @@ -79,7 +80,7 @@ T* ResourceManager::Load(std::string resourceType, std::string resourceName) template T* ResourceManager::Fetch(std::string resourceName) const { - auto it = m_ResourceCache.find(resourceName); + auto it = m_ResourceCache.find(std::make_pair(resourceType, resourceName)); if (it == m_ResourceCache.end()) { LOG_ERROR("Failed to fetch resource \"%s\": Resource not loaded!", resourceName.c_str()); diff --git a/src/ShaderProgram.cpp b/src/ShaderProgram.cpp index e9bd864..bd67e90 100755 --- a/src/ShaderProgram.cpp +++ b/src/ShaderProgram.cpp @@ -103,6 +103,11 @@ void ShaderProgram::AddShader(std::shared_ptr shader) void ShaderProgram::Compile() { + if (m_ShaderProgramHandle == 0) + { + m_ShaderProgramHandle = glCreateProgram(); + } + for (auto &shader : m_Shaders) { if (!shader->IsCompiled()) @@ -121,7 +126,7 @@ GLuint ShaderProgram::Link() } LOG_INFO("Linking shader program"); - m_ShaderProgramHandle = glCreateProgram(); + for (auto &shader : m_Shaders) { glAttachShader(m_ShaderProgramHandle, shader->GetHandle()); diff --git a/src/ShaderProgram.h b/src/ShaderProgram.h index 07dbf9b..a27300c 100755 --- a/src/ShaderProgram.h +++ b/src/ShaderProgram.h @@ -61,7 +61,7 @@ class ShaderProgram { public: ShaderProgram() - : m_ShaderProgramHandle(0) { } + : m_ShaderProgramHandle(0) { } ~ShaderProgram(); void AddShader(std::shared_ptr shader); diff --git a/src/Shaders/FinalPass.frag.glsl b/src/Shaders/FinalPass.frag.glsl new file mode 100644 index 0000000..2a6cf4c --- /dev/null +++ b/src/Shaders/FinalPass.frag.glsl @@ -0,0 +1,29 @@ +#version 430 + +uniform vec3 La; +uniform float Gamma; + +layout (binding=0) uniform sampler2D DiffuseTexture; +layout (binding=1) uniform sampler2D LightingTexture; +layout (binding=2) uniform sampler2D ShadowTexture; + +in VertexData +{ + vec3 Position; + vec2 TextureCoord; +} Input; + +out vec4 FragmentColor; + +void main() +{ + vec4 DiffuseTexel = texture(DiffuseTexture, Input.TextureCoord); + vec4 LightingTexel = texture(LightingTexture, Input.TextureCoord); + vec4 ShadowTexel = texture(ShadowTexture, Input.TextureCoord); + + + vec4 _FragmentColor = DiffuseTexel * vec4(La, 1.0) + LightingTexel; + FragmentColor = vec4(pow(_FragmentColor.rgb, vec3(1.0 / Gamma)), _FragmentColor.a); + //FragmentColor = ShadowTexel; + +} \ No newline at end of file diff --git a/src/Shaders/FinalPass.vert.glsl b/src/Shaders/FinalPass.vert.glsl new file mode 100644 index 0000000..05deece --- /dev/null +++ b/src/Shaders/FinalPass.vert.glsl @@ -0,0 +1,16 @@ +#version 430 + +layout(location = 0) in vec3 Position; + +out VertexData +{ + vec3 Position; + vec2 TextureCoord; +} Output; + +void main() +{ + gl_Position = vec4(Position, 1.0); + Output.Position = Position; + Output.TextureCoord = (vec2(Position) + 1) / 2; +} \ No newline at end of file diff --git a/src/Shaders/Fragment.glsl b/src/Shaders/Fragment.glsl index 1909e84..cc5370f 100755 --- a/src/Shaders/Fragment.glsl +++ b/src/Shaders/Fragment.glsl @@ -1,113 +1,43 @@ #version 430 -uniform mat4 model; -uniform mat4 view; - -layout(binding=0) uniform sampler2D texture0; -layout(binding=1) uniform sampler2D shadowMap; - -const int maxNumberOfLights = 82; -uniform int numberOfLights; -uniform vec3 position[maxNumberOfLights]; -uniform vec3 specular[maxNumberOfLights]; -uniform vec3 diffuse[maxNumberOfLights]; -uniform float constantAttenuation[maxNumberOfLights]; -uniform float linearAttenuation[maxNumberOfLights]; -uniform float quadraticAttenuation[maxNumberOfLights]; -uniform float spotExponent[maxNumberOfLights]; +layout (binding=0) uniform sampler2D DiffuseTexture; +layout (binding=1) uniform sampler2D ShadowTexture; in VertexData { vec3 Position; vec3 Normal; vec2 TextureCoord; - vec3 ShadowCoord; + vec4 ShadowCoord; } Input; -vec3 scene_ambient = vec3(0.5, 0.5, 0.5); +out vec4 frag_Diffuse; +out vec4 frag_Position; +out vec4 frag_Normal; -out vec4 fragmentColor; +float Shadow(vec4 ShadowCoord) +{ + //float cosTheta = clamp(dot(Input.Normal, 1.0), 0.0, 1.0); + float bias = 0.0005; // cosTheta is dot( n,l ), clamped between 0 and 1 + bias = clamp(bias, 0.0, 0.01); + if( texture(ShadowTexture, Input.ShadowCoord.xy).z < ShadowCoord.z - bias) + { + return 0.3; + } + else + { + return 1.0; + } +} void main() { + // Diffuse Texture + frag_Diffuse = texture(DiffuseTexture, Input.TextureCoord) * Shadow(Input.ShadowCoord); - // Texture - vec4 texel = texture2D(texture0, Input.TextureCoord); - //vec4 texel = (blend.x * texel0) + (blend.y * texel1) + (blend.z * texel2); + // G-buffer Position + frag_Position = vec4(Input.Position.xyz, 1.0); - // - // Phong shading - // - - // Ambient light - vec3 La = scene_ambient; // Ambient light - vec3 Ks = vec3(0.3, 0.3, 0.3); // Specular reflectance - vec3 Kd = vec3(1.0, 1.0, 1.0); // Diffuse reflectance - vec3 Ka = vec3(1.0, 1.0, 1.0); // Ambient reflectance - vec3 Is; - vec3 Id; - - // Shadows - //float cosTheta = clamp(dot(Input.Normal, vec3(0, 1, 0)), 0.0, 1.0); - //float bias = 0.001 * tan(acos(cosTheta)); // cosTheta is dot( n,l ), clamped between 0 and 1 - //bias = clamp(bias, 0.0, 0.01); - float visibility = 1.0; - /*if (Input.ShadowCoord.x >= 0.0 && Input.ShadowCoord.x <= 1.0 && Input.ShadowCoord.y >= 0.0 && Input.ShadowCoord.y <= 1.0) - { - float bias = 0.00005; - vec4 shadowMapValue = texture(shadowMap, Input.ShadowCoord.xy); - if (shadowMapValue.z < clamp(Input.ShadowCoord.z - bias, 0, 1)) - { - visibility = 0.3; - } - }*/ - - vec3 totalLighting = La * Ka * visibility; - - float attenuation; - - for(int i = 0; i < numberOfLights && i < maxNumberOfLights; i++) - { - // Light - //vec3 lightPosition = vec3(0, 0, 2); - vec3 Ls = specular[i]; // Specular light - vec3 Ld = diffuse[i]; // Diffuse light - - vec3 lightPosView = vec3(view * vec4(position[i], 1.0)); - vec3 surfacePosition = vec3(model * vec4(Input.Position, 1.0)); - vec3 surfacePosView = vec3(view * vec4(surfacePosition, 1.0)); - vec3 surfaceToLight = normalize(lightPosView - surfacePosView); - mat3 normalMatrix = transpose(inverse(mat3(view * model))); - vec3 surfaceNormal = normalize(normalMatrix * Input.Normal); - - float dist = length(position[i] - surfacePosition); - - attenuation = 1.0 / (constantAttenuation[i] - + linearAttenuation[i] * dist - + quadraticAttenuation[i] * pow(dist, 2.0)); - //attenuation = attenuation * pow(clampedCosine, spotExponent[i]); - - // Diffuse light - float dotProd = dot(surfaceToLight, surfaceNormal); - dotProd = max(dotProd, 0.0); - - Id = Ld * Kd * abs(dotProd) * attenuation; - - // Specular light - vec3 reflection = reflect(-surfaceToLight, surfaceNormal); - float dotSpecular = dot(reflection, normalize(-surfacePosView)); - dotSpecular = max(dotSpecular, 0.0); - float specularFactor = pow(dotSpecular, 30.0); // Specular factor - - Is = attenuation * Ls * Ks * specularFactor; - - totalLighting = totalLighting + Id + Is; - } - - fragmentColor = vec4(totalLighting, 1.0) * texel; - - - //fragmentColor = vec4(Id, 1.0) * texel; - - //fragmentColor = texel; + // G-buffer Normal + frag_Normal = vec4(Input.Normal, 0.0); } \ No newline at end of file diff --git a/src/Shaders/Fragment2-Debug.glsl b/src/Shaders/Fragment2-Debug.glsl new file mode 100644 index 0000000..db35d6e --- /dev/null +++ b/src/Shaders/Fragment2-Debug.glsl @@ -0,0 +1,38 @@ +#version 430 + +layout (binding=0) uniform sampler2D DiffuseTexture; +layout (binding=1) uniform sampler2D PositionTexture; +layout (binding=2) uniform sampler2D NormalTexture; + +in VertexData +{ + vec3 Position; + vec3 Normal; + vec2 TextureCoord; +} Input; + +out vec4 FragColor; + +void DrawQuadrant(vec4 texel, vec2 quadrant) +{ + if (-quadrant.x * Input.Position.x < 0 && -quadrant.y * Input.Position.y < 0) + { + FragColor = texel; + } +} + +void main() +{ + vec4 DiffuseTexel = texture2D(DiffuseTexture, Input.TextureCoord); + vec4 PositionTexel = texture2D(PositionTexture, Input.TextureCoord); + vec4 NormalTexel = texture2D(NormalTexture, Input.TextureCoord); + + //FragColor = texture2D(DiffuseTexture, Input.TextureCoord * 2 + vec2(0, -1)); + DrawQuadrant(texture2D(DiffuseTexture, Input.TextureCoord * 2), vec2(-1, 1)); + DrawQuadrant(texture2D(PositionTexture, Input.TextureCoord * 2), vec2(1, 1)); + DrawQuadrant(texture2D(NormalTexture, Input.TextureCoord * 2), vec2(-1, -1)); + + vec4 AllTexel = texture2D(DiffuseTexture, Input.TextureCoord*2)*texture2D(PositionTexture, Input.TextureCoord*2)*texture2D(NormalTexture, Input.TextureCoord*2); + DrawQuadrant(AllTexel, vec2(1, -1)); +} + diff --git a/src/Shaders/Fragment2.glsl b/src/Shaders/Fragment2.glsl new file mode 100644 index 0000000..f531f76 --- /dev/null +++ b/src/Shaders/Fragment2.glsl @@ -0,0 +1,84 @@ +#version 430 + +layout (binding=0) uniform sampler2D PositionTexture; +layout (binding=1) uniform sampler2D NormalsTexture; + +uniform vec2 ViewportSize; +uniform mat4 MVP; +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; +uniform vec3 la; +uniform vec3 ls; +uniform vec3 ld; +uniform vec3 lp; +uniform float specularExponent; +uniform vec3 CameraPosition; +uniform float ConstantAttenuation; +uniform float LinearAttenuation; +uniform float QuadraticAttenuation; + +const vec3 ks = vec3(1.0, 1.0, 1.0); +const vec3 kd = vec3(1.0, 1.0, 1.0); +const vec3 ka = vec3(1.0, 1.0, 1.0); +const float kshine = 1.0; + +in VertexData +{ + vec3 Position; + vec2 TextureCoord; +} Input; + +out vec4 FragColor; + +vec4 phong(vec3 position, vec3 normal) +{ + // Diffuse + vec3 lightPos = vec3(V * vec4(lp, 1.0)); + vec3 distanceToLight = lightPos - position; + vec3 directionToLight = normalize(distanceToLight); + float dotProd = dot(directionToLight, normal); + dotProd = max(dotProd, 0.0); + vec3 Id = kd * ld * dotProd; + + // Specular + //vec3 reflection = reflect(-directionToLight, normal); + vec3 surfaceToViewer = normalize(-position); + vec3 halfWay = normalize(surfaceToViewer + directionToLight); + float dotSpecular = max(dot(halfWay, normal), 0.0); + float specularFactor = pow(dotSpecular, specularExponent * 2.0); + vec3 Is = ks * ls * specularFactor; + + //Attenuation + float dist = distance(lightPos, position); + //float attenuation = -log(min(1.0, dist / LightRadius)); + + float attenuation = 1.0 / (ConstantAttenuation + (LinearAttenuation * dist) + (QuadraticAttenuation * dist * dist)); + + //float attenuation = 1.0 / (1.0 - 0.0001 * pow(dist, 2)); + + //float attenuation = clamp(0.0, 1.0, 1.0 / (0.001 + (0.001 * dist) + (0.001 * dist * dist))); + + //float attenuation = 1.0 / dot(directionToLight, directionToLight); + + //float att_s = 5; + //float attenuation = pow(dist, 2) / pow(5.0, 2); + //attenuation = 1.0 / (1.0 + attenuation * att_s); + //att_s = 1.0 / (1.0 + att_s); + //attenuation = attenuation / (1.0 - att_s); + + //float radius = 5.0; + //float alpha = dist / radius; + //float dampingFactor = 1.0 - pow(alpha, 3); + + return vec4((Id + Is) * attenuation, 1.0); +} + +void main() +{ + vec2 TextureCoord = gl_FragCoord.xy / ViewportSize; + vec4 PositionTexel = texture(PositionTexture, TextureCoord); + vec4 NormalTexel = texture(NormalsTexture, TextureCoord); + + FragColor = phong(vec3(PositionTexel), vec3(NormalTexel)); +} \ No newline at end of file diff --git a/src/Shaders/Vertex.glsl b/src/Shaders/Vertex.glsl index 295d523..2f799ef 100755 --- a/src/Shaders/Vertex.glsl +++ b/src/Shaders/Vertex.glsl @@ -1,26 +1,29 @@ #version 430 uniform mat4 MVP; +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; uniform mat4 DepthMVP; -layout(location = 0) in vec3 Position; -layout(location = 1) in vec3 Normal; -layout(location = 2) in vec2 TextureCoord; +layout (location = 0) in vec3 Position; +layout (location = 1) in vec3 Normal; +layout (location = 2) in vec2 TextureCoord; out VertexData { vec3 Position; vec3 Normal; vec2 TextureCoord; - vec3 ShadowCoord; + vec4 ShadowCoord; } Output; void main() { gl_Position = MVP * vec4(Position, 1.0); - Output.Position = Position; - Output.Normal = Normal; + Output.Position = vec3(V * M * vec4(Position, 1.0)); + Output.Normal = normalize(vec3(inverse(transpose(V * M)) * vec4(Normal, 0.0))); Output.TextureCoord = TextureCoord; - Output.ShadowCoord = vec3(DepthMVP * vec4(Position, 1.0)); + Output.ShadowCoord = DepthMVP * vec4(Position, 1.0); } \ No newline at end of file diff --git a/src/Shaders/Vertex2.glsl b/src/Shaders/Vertex2.glsl new file mode 100644 index 0000000..e617846 --- /dev/null +++ b/src/Shaders/Vertex2.glsl @@ -0,0 +1,22 @@ +#version 430 + +uniform mat4 MVP; + +layout (location = 0) in vec3 Position; +layout (location = 2) in vec2 TextureCoord; + +uniform mat4 depthBiasMVP; + +out VertexData +{ + vec3 Position; + vec2 TextureCoord; +} Output; + +void main() +{ + gl_Position = MVP * vec4(Position, 1.0); + Output.Position = Position; + Output.TextureCoord = (vec2(Position) + 1.0) / 2.0; + +} \ No newline at end of file diff --git a/src/Shaders/geometry_pass.frag.glsl b/src/Shaders/geometry_pass.frag.glsl deleted file mode 100644 index 4fe34ba..0000000 --- a/src/Shaders/geometry_pass.frag.glsl +++ /dev/null @@ -1,20 +0,0 @@ -#version 430 - -in vec2 TexCoord0; -in vec3 Normal0; -in vec3 WorldPos0; - -layout (location = 0) out vec3 WorldPosOut; -layout (location = 1) out vec3 DiffuseOut; -layout (location = 2) out vec3 NormalOut; -layout (location = 3) out vec3 TexCoordOut; - -uniform sampler2D gColorMap; - -void main() -{ - WorldPosOut = WorldPos0; - DiffuseOut = texture(gColorMap, TexCoord0).xyz; - NormalOut = normalize(Normal0); - TexCoordOut = vec3(TexCoord0, 0.0); -} \ No newline at end of file diff --git a/src/Shaders/geometry_pass.vert.glsl b/src/Shaders/geometry_pass.vert.glsl deleted file mode 100644 index c431ba9..0000000 --- a/src/Shaders/geometry_pass.vert.glsl +++ /dev/null @@ -1,20 +0,0 @@ -#version 430 - -layout (location = 0) in vec3 Position; -layout (location = 1) in vec2 TexCoord; -layout (location = 2) in vec3 Normal; - -uniform mat4 gWVP; -uniform mat4 gWorld; - -out vec2 TexCoord0; -out vec3 Normal0; -out vec3 WorldPos0; - -void main() -{ - gl_Position = gWVP * vec4(Position, 1.0); - TexCoord0 = TexCoord; - Normal0 = (gWorld * vec4(Normal, 0.0)).xyz; - WorldPos0 = (gWorld * vec4(Position, 1.0)).xyz; -} \ No newline at end of file diff --git a/src/Systems/FreeSteeringSystem.cpp b/src/Systems/FreeSteeringSystem.cpp index b382b23..d59b475 100755 --- a/src/Systems/FreeSteeringSystem.cpp +++ b/src/Systems/FreeSteeringSystem.cpp @@ -38,38 +38,38 @@ void Systems::FreeSteeringSystem::UpdateEntity(double dt, EntityID entity, Entit bool Systems::FreeSteeringSystem::FreeSteeringInputController::OnCommand(const Events::InputCommand &event) { // Movement - if (event.Command == "+forward") + if (event.Command == "+cam_forward") { Movement.z += -1.f; } - else if (event.Command == "-forward") + else if (event.Command == "-cam_forward") { Movement.z -= -1.f; } - else if (event.Command == "+backward") + else if (event.Command == "+cam_backward") { Movement.z += 1.f; } - else if (event.Command == "-backward") + else if (event.Command == "-cam_backward") { Movement.z -= 1.f; } - else if (event.Command == "+right") - { - Movement.x += 1.f; - } - else if (event.Command == "-right") + else if (event.Command == "+cam_right") { Movement.x -= 1.f; } - else if (event.Command == "+left") + else if (event.Command == "-cam_right") { - Movement.x += -1.f; + Movement.x += 1.f; } - else if (event.Command == "-left") + else if (event.Command == "+cam_left") { Movement.x -= -1.f; } + else if (event.Command == "-cam_left") + { + Movement.x += -1.f; + } else if (event.Command == "+up") { Movement.y += 1.f; diff --git a/src/Systems/InputSystem.cpp b/src/Systems/InputSystem.cpp index 3c9fdfd..7c4cde7 100755 --- a/src/Systems/InputSystem.cpp +++ b/src/Systems/InputSystem.cpp @@ -10,12 +10,17 @@ void Systems::InputSystem::RegisterComponents(ComponentFactory* cf) void Systems::InputSystem::Initialize() { // Subscribe to events - EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &Systems::InputSystem::OnKeyDown) - EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &Systems::InputSystem::OnKeyUp) - EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &Systems::InputSystem::OnMousePress) - EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &Systems::InputSystem::OnMouseRelease) - EVENT_SUBSCRIBE_MEMBER(m_EBindKey, &Systems::InputSystem::OnBindKey) - EVENT_SUBSCRIBE_MEMBER(m_EBindMouseButton, &Systems::InputSystem::OnBindMouseButton) + EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &Systems::InputSystem::OnKeyDown); + EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &Systems::InputSystem::OnKeyUp); + EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &Systems::InputSystem::OnMousePress); + EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &Systems::InputSystem::OnMouseRelease); + EVENT_SUBSCRIBE_MEMBER(m_EGamepadAxis, &Systems::InputSystem::OnGamepadAxis); + EVENT_SUBSCRIBE_MEMBER(m_EGamepadButtonDown, &Systems::InputSystem::OnGamepadButtonDown); + EVENT_SUBSCRIBE_MEMBER(m_EGamepadButtonUp, &Systems::InputSystem::OnGamepadButtonUp); + EVENT_SUBSCRIBE_MEMBER(m_EBindKey, &Systems::InputSystem::OnBindKey); + EVENT_SUBSCRIBE_MEMBER(m_EBindMouseButton, &Systems::InputSystem::OnBindMouseButton); + EVENT_SUBSCRIBE_MEMBER(m_EBindGamepadAxis, &Systems::InputSystem::OnBindGamepadAxis); + EVENT_SUBSCRIBE_MEMBER(m_EBindGamepadButton, &Systems::InputSystem::OnBindGamepadButton); } void Systems::InputSystem::Update(double dt) @@ -44,7 +49,11 @@ bool Systems::InputSystem::OnKeyDown(const Events::KeyDown &event) auto bindingIt = m_KeyBindings.find(event.KeyCode); if (bindingIt != m_KeyBindings.end()) { - PublishCommand(0, bindingIt->second, false); + std::string command; + float value; + std::tie(command, value) = bindingIt->second; + m_CommandValues[command] += value; + PublishCommand(0, command, std::max(-1.f, std::min(m_CommandValues[command], 1.f))); } return true; @@ -55,7 +64,11 @@ bool Systems::InputSystem::OnKeyUp(const Events::KeyUp &event) auto bindingIt = m_KeyBindings.find(event.KeyCode); if (bindingIt != m_KeyBindings.end()) { - PublishCommand(0, bindingIt->second, true); + std::string command; + float value; + std::tie(command, value) = bindingIt->second; + m_CommandValues[command] -= value; + PublishCommand(0, command, std::max(-1.f, std::min(m_CommandValues[command], 1.f))); } return true; @@ -66,7 +79,7 @@ bool Systems::InputSystem::OnMousePress(const Events::MousePress &event) auto bindingIt = m_MouseButtonBindings.find(event.Button); if (bindingIt != m_MouseButtonBindings.end()) { - PublishCommand(0, bindingIt->second, false); + PublishCommand(0, bindingIt->second, 1.f); } return true; @@ -77,12 +90,57 @@ bool Systems::InputSystem::OnMouseRelease(const Events::MouseRelease &event) auto bindingIt = m_MouseButtonBindings.find(event.Button); if (bindingIt != m_MouseButtonBindings.end()) { - PublishCommand(0, bindingIt->second, true); + PublishCommand(0, bindingIt->second, 1.f); } return true; } +bool Systems::InputSystem::OnGamepadAxis(const Events::GamepadAxis &event) +{ + auto bindingIt = m_GamepadAxisBindings.find(event.Axis); + if (bindingIt != m_GamepadAxisBindings.end()) + { + std::string command; + float value; + std::tie(command, value) = bindingIt->second; + PublishCommand(event.GamepadID + 1, command, event.Value * value); + } + + return true; +} + +bool Systems::InputSystem::OnGamepadButtonDown(const Events::GamepadButtonDown &event) +{ + auto bindingIt = m_GamepadButtonBindings.find(event.Button); + if (bindingIt != m_GamepadButtonBindings.end()) + { + std::string command; + float value; + std::tie(command, value) = bindingIt->second; + m_CommandValues[command] += value; + PublishCommand(event.GamepadID + 1, command, std::max(-1.f, std::min(m_CommandValues[command], 1.f))); + } + + return true; +} + +bool Systems::InputSystem::OnGamepadButtonUp(const Events::GamepadButtonUp &event) +{ + auto bindingIt = m_GamepadButtonBindings.find(event.Button); + if (bindingIt != m_GamepadButtonBindings.end()) + { + std::string command; + float value; + std::tie(command, value) = bindingIt->second; + m_CommandValues[command] -= value; + PublishCommand(event.GamepadID + 1, command, std::max(-1.f, std::min(m_CommandValues[command], 1.f))); + } + + return true; +} + + bool Systems::InputSystem::OnBindKey(const Events::BindKey &event) { if (event.Command.empty()) @@ -91,7 +149,7 @@ bool Systems::InputSystem::OnBindKey(const Events::BindKey &event) } else { - m_KeyBindings[event.KeyCode] = event.Command; + m_KeyBindings[event.KeyCode] = std::make_tuple(event.Command, event.Value); LOG_DEBUG("Input: Bound key %c to %s", (char)event.KeyCode, event.Command.c_str()); } @@ -113,17 +171,45 @@ bool Systems::InputSystem::OnBindMouseButton(const Events::BindMouseButton &even return true; } -void Systems::InputSystem::PublishCommand(int playerID, std::string command, bool release /*= false*/) +bool Systems::InputSystem::OnBindGamepadAxis(const Events::BindGamepadAxis &event) { - if (release && command.at(0) == '+') + if (event.Command.empty()) { - command[0] = '-'; + m_GamepadAxisBindings.erase(event.Axis); + } + else + { + m_GamepadAxisBindings[event.Axis] = std::make_tuple(event.Command, event.Value); + LOG_DEBUG("Input: Bound gamepad axis %i to %s", event.Axis, event.Command.c_str()); } + return true; +} + +bool Systems::InputSystem::OnBindGamepadButton(const Events::BindGamepadButton &event) +{ + if (event.Command.empty()) + { + m_GamepadButtonBindings.erase(event.Button); + } + else + { + m_GamepadButtonBindings[event.Button] = std::make_tuple(event.Command, event.Value); + LOG_DEBUG("Input: Bound gamepad axis %i to %s", event.Button, event.Command.c_str()); + } + + return true; +} + +void Systems::InputSystem::PublishCommand(int playerID, std::string command, float value) +{ Events::InputCommand e; e.PlayerID = playerID; e.Command = command; + e.Value = value; EventBroker->Publish(e); - LOG_DEBUG("Input: Published command %s for player %i", e.Command.c_str(), playerID); + LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, playerID); } + + diff --git a/src/Systems/InputSystem.h b/src/Systems/InputSystem.h index c56cccf..ce9a7f3 100755 --- a/src/Systems/InputSystem.h +++ b/src/Systems/InputSystem.h @@ -3,6 +3,7 @@ #include #include +#include #include "System.h" #include "Components/Input.h" @@ -10,8 +11,12 @@ #include "Events/KeyDown.h" #include "Events/MousePress.h" #include "Events/MouseRelease.h" +#include "Events/GamepadAxis.h" +#include "Events/GamepadButton.h" #include "Events/BindKey.h" #include "Events/BindMouseButton.h" +#include "Events/BindGamepadAxis.h" +#include "Events/BindGamepadButton.h" #include "Events/InputCommand.h" namespace Systems @@ -29,9 +34,12 @@ public: void Update(double dt) override; private: + std::unordered_map m_CommandValues; // command string -> command current value // Input binding tables - std::unordered_map m_KeyBindings; // GLFW_KEY... -> command string + std::unordered_map> m_KeyBindings; // GLFW_KEY... -> command string & value std::unordered_map m_MouseButtonBindings; // GLFW_MOUSE_BUTTON... -> command string + std::unordered_map> m_GamepadAxisBindings; // Gamepad::Axis -> command string & value + std::unordered_map> m_GamepadButtonBindings; // Gamepad::Button -> command string // Input events EventRelay m_EKeyDown; @@ -42,13 +50,23 @@ private: bool OnMousePress(const Events::MousePress &event); EventRelay m_EMouseRelease; bool OnMouseRelease(const Events::MouseRelease &event); + EventRelay m_EGamepadAxis; + bool OnGamepadAxis(const Events::GamepadAxis &event); + EventRelay m_EGamepadButtonDown; + bool OnGamepadButtonDown(const Events::GamepadButtonDown &event); + EventRelay m_EGamepadButtonUp; + bool OnGamepadButtonUp(const Events::GamepadButtonUp &event); // Input binding events EventRelay m_EBindKey; bool OnBindKey(const Events::BindKey &event); EventRelay m_EBindMouseButton; bool OnBindMouseButton(const Events::BindMouseButton &event); + EventRelay m_EBindGamepadAxis; + bool OnBindGamepadAxis(const Events::BindGamepadAxis &event); + EventRelay m_EBindGamepadButton; + bool OnBindGamepadButton(const Events::BindGamepadButton &event); - void PublishCommand(int playerID, std::string command, bool release = false); + void PublishCommand(int playerID, std::string command, float value); }; } diff --git a/src/Systems/ParticleSystem.cpp b/src/Systems/ParticleSystem.cpp new file mode 100644 index 0000000..0882f9d --- /dev/null +++ b/src/Systems/ParticleSystem.cpp @@ -0,0 +1,208 @@ +#include "PrecompiledHeader.h" +#include "ParticleSystem.h" + + +#include "World.h" + +void Systems::ParticleSystem::Initialize() +{ + m_TransformSystem = m_World->GetSystem("TransformSystem"); +} + +void Systems::ParticleSystem::Update(double dt) +{ + +} + +void Systems::ParticleSystem::UpdateEntity(double dt, EntityID entity, EntityID parent) +{ + auto transformComponent = m_World->GetComponent(entity, "Transform"); + if(!transformComponent) + return; + + auto emitterComponent = m_World->GetComponent(entity, "ParticleEmitter"); + if(emitterComponent) + { + emitterComponent->TimeSinceLastSpawn += dt; + auto emitterTransformComponent = m_World->GetComponent(entity, "Transform"); + if(emitterComponent->TimeSinceLastSpawn > emitterComponent->SpawnFrequency) + { + SpawnParticles(entity); + emitterComponent->TimeSinceLastSpawn = 0; + } + + std::list::iterator it; + for(it = m_ParticleEmitter[entity].begin(); it != m_ParticleEmitter[entity].end();) + { + EntityID particleID = (it)->ParticleID; + auto transformComponent = m_World->GetComponent(particleID, "Transform"); + auto particleComponent = m_World->GetComponent(particleID, "Particle"); + + double timeLived = glfwGetTime() - it->SpawnTime; + if(timeLived > particleComponent->LifeTime) + { + m_World->RemoveEntity(particleID); + it = m_ParticleEmitter[entity].erase(it); + } + else + { + // FIX: calculate once + float timeProgress = timeLived / particleComponent->LifeTime; + // ColorInterpolation(timeProgress, particleComponent->ColorSpectrum, color); + // Scale interpolation + if(particleComponent->ScaleSpectrum.size() > 1) + VectorInterpolation(timeProgress, particleComponent->ScaleSpectrum, transformComponent->Scale); + // Velocity interpolation + if(particleComponent->VelocitySpectrum.size() > 1) + VectorInterpolation(timeProgress, particleComponent->VelocitySpectrum, transformComponent->Velocity); + + // Angular velocity interpolation + if (particleComponent->AngularVelocitySpectrum.size() != 0) + { + if(particleComponent->AngularVelocitySpectrum.size() > 1) + { + ScalarInterpolation(timeProgress, particleComponent->AngularVelocitySpectrum, it->AngularVelocity); + transformComponent->Orientation = glm::angleAxis(it->AngularVelocity, it->Orientation); + } + else + { + transformComponent->Orientation *= glm::angleAxis(it->AngularVelocity, it->Orientation); + //it->Orientation = glm::angleAxis(it->AngularVelocity, it->Orientation); + } + } + + //Angular velocity interpolation + if(particleComponent->OrientationSpectrum.size() > 1) + { + VectorInterpolation(timeProgress, particleComponent->OrientationSpectrum, it->Orientation); + glm::vec3 v1 = (particleComponent->OrientationSpectrum[0]); + glm::vec3 v2 = (it->Orientation); + glm::vec3 v3 = glm::normalize(glm::cross(v1,v2)); + float angle = glm::acos(glm::dot(v1, v2) / (glm::length(v1) * glm::length(v2))); + + transformComponent->Orientation = glm::angleAxis(angle, v3); + } + + + transformComponent->Position += transformComponent->Velocity * (float)dt; + + it++; + } + } + } +} + +void Systems::ParticleSystem::RegisterComponents(ComponentFactory* cf) +{ + cf->Register("ParticleEmitter", []() { return new Components::ParticleEmitter(); }); + cf->Register("Particle", []() { return new Components::Particle(); }); +} + + +void Systems::ParticleSystem::SpawnParticles(EntityID emitterID) +{ + auto emitterComponent = m_World->GetComponent(emitterID, "ParticleEmitter"); + auto emitterTransform = m_World->GetComponent(emitterID, "Transform"); + glm::vec3 emitterPos = m_TransformSystem->AbsolutePosition(emitterID); + glm::quat emitterOrientation = emitterTransform->Orientation; + + float tempSpeed = 4; + glm::vec3 speed = glm::vec3(tempSpeed); + + for(int i = 0; i < emitterComponent->SpawnCount; i++) + { + auto ent = m_World->CloneEntity(emitterComponent->ParticleTemplate); + + auto particleTransform = m_World->GetComponent(ent, "Transform"); + particleTransform->Position = emitterPos; + + particleTransform->Orientation = emitterOrientation; + //The emitter's orientation as "start value" times the default direction for emitter. Times the speed, and then rotate on x and y axis with the randomized spread angle. + float spreadAngle = emitterComponent->SpreadAngle; + particleTransform->Velocity = emitterOrientation * glm::vec3(0, 0, -1) * speed * + glm::normalize(glm::angleAxis(RandomizeAngle(spreadAngle), glm::vec3(1, 0, 0))) * + glm::normalize(glm::angleAxis(RandomizeAngle(spreadAngle), glm::vec3(0, 1, 0))) * + glm::normalize(glm::angleAxis(RandomizeAngle(spreadAngle), glm::vec3(0, 0, 1))); + + auto particle = m_World->AddComponent(ent, "Particle"); + particle->LifeTime = emitterComponent->LifeTime; + particle->ScaleSpectrum = emitterComponent->ScaleSpectrum; + particle->VelocitySpectrum.push_back(particleTransform->Velocity); + + if (emitterComponent->ScaleSpectrum.size() > 0) + { + if (emitterComponent->ScaleSpectrum.size() > 1) + { + particle->ScaleSpectrum = emitterComponent->ScaleSpectrum; + } + else + { + particleTransform->Scale = emitterComponent->ScaleSpectrum[0]; + } + } + else + { + particleTransform->Scale = glm::vec3(1, 1, 1); + } + + if(emitterComponent->UseGoalVelocity) + particle->VelocitySpectrum.push_back(emitterComponent->GoalVelocity); + particle->OrientationSpectrum = emitterComponent->OrientationSpectrum; + if(particle->OrientationSpectrum.size() != 0) + particleTransform->Orientation = glm::angleAxis(0.f, particle->OrientationSpectrum[0]); + particle->AngularVelocitySpectrum = emitterComponent->AngularVelocitySpectrum; + + + ParticleData data; + data.ParticleID = ent; + data.SpawnTime = glfwGetTime(); + if (particle->AngularVelocitySpectrum.size() != 0) + data.AngularVelocity = particle->AngularVelocitySpectrum[0]; + if (particle->OrientationSpectrum.size() != 0) + data.Orientation = particle->OrientationSpectrum[0]; + else data.Orientation = emitterOrientation * glm::vec3(0,0,-1); + + m_ParticleEmitter[emitterID].push_back(data); + } +} + +//Randomizes between -spreadAngle/2 and spreadAngle/2 +float Systems::ParticleSystem::RandomizeAngle(float spreadAngle) +{ + return ((float)rand() / ((float)RAND_MAX + 1) * spreadAngle) - spreadAngle/2; +} + +//Interpolates the velocity of the particle +void Systems::ParticleSystem::VectorInterpolation(double timeProgress, std::vector spectrum, glm::vec3 &v) +{ + float dAxisValue = glm::abs(spectrum[0].x - spectrum[1].x); + if(spectrum[0].x > spectrum[1].x) + dAxisValue *= -1; + v.x = spectrum[0].x + dAxisValue * timeProgress; + dAxisValue = glm::abs(spectrum[0].y - spectrum[1].y); + if (spectrum[0].y > spectrum[1].y) + dAxisValue *= -1; + v.y = spectrum[0].y + dAxisValue * timeProgress; + dAxisValue = glm::abs(spectrum[0].z - spectrum[1].z); + if(spectrum[0].z > spectrum[1].z) + dAxisValue *= -1; + v.z = spectrum[0].z + dAxisValue * timeProgress; +} + +// void Systems::ParticleSystem::ColorInterpolation(double timeProgress, std::vector spectrum, Color &c) +// { +// float dColor = glm::abs(spectrum[0].r - spectrum[1].r); +// c.r = spectrum[0].r + dColor * timeProgress; +// dColor = glm::abs(spectrum[0].g - spectrum[1].g); +// c.g = spectrum[0].g + dColor * timeProgress; +// dColor = glm::abs(spectrum[0].b - spectrum[1].b); +// c.b = spectrum[0].b + dColor * timeProgress; +// } + +void Systems::ParticleSystem::ScalarInterpolation(double timeProgress, std::vector spectrum, float &alpha) +{ + float dAlpha = glm::abs(spectrum[0] - spectrum[1]); + if(spectrum[0] > spectrum[1]) + dAlpha *= -1; + alpha = spectrum[0] + dAlpha * timeProgress; +} \ No newline at end of file diff --git a/src/Systems/ParticleSystem.h b/src/Systems/ParticleSystem.h new file mode 100644 index 0000000..06cbe63 --- /dev/null +++ b/src/Systems/ParticleSystem.h @@ -0,0 +1,54 @@ +#ifndef ParticleSystem_h__ +#define ParticleSystem_h__ + +#include "System.h" +#include "Systems/TransformSystem.h" +#include "Components/Transform.h" +#include "Components/ParticleEmitter.h" +#include "Components/Particle.h" +#include "Components/Model.h" +#include "Components/PointLight.h" +#include "Color.h" +#include + +namespace Systems +{ + + struct ParticleData + { + EntityID ParticleID; + double SpawnTime; + float AngularVelocity; + glm::vec3 Orientation; + Color color; + }; + +class ParticleSystem : public System +{ +public: + ParticleSystem(World* world, std::shared_ptr<::EventBroker> eventBroker) + : System(world, eventBroker) { } + + void RegisterComponents(ComponentFactory* cf) override; + void Update(double dt) override; + void UpdateEntity(double dt, EntityID entity, EntityID parent) override; + void Initialize() override; +private: + void SpawnParticles(EntityID emitterID); + float RandomizeAngle(float spreadAngle); + //void ScaleInterpolation(double timeProgress, std::vector spectrum, glm::vec3 &scale); + void VectorInterpolation(double timeProgress, std::vector spectrum, glm::vec3 &velocity); + //void ColorInterpolation(double timeProgress, std::vector spectrum, Color &color); + void ScalarInterpolation(double timeProgress, std::vector spectrum, float &alpha); + void Billboard(); + std::map> m_ParticleEmitter; + std::map m_TimeSinceLastSpawn; + std::shared_ptr m_TransformSystem; + + +}; + +} + + +#endif // !ParticleSystem_h__ \ No newline at end of file diff --git a/src/Systems/PhysicsSystem.cpp b/src/Systems/PhysicsSystem.cpp index dfb7a8b..8efa4bb 100644 --- a/src/Systems/PhysicsSystem.cpp +++ b/src/Systems/PhysicsSystem.cpp @@ -28,45 +28,94 @@ void Systems::PhysicsSystem::Initialize() { m_Accumulator = 0; + + // Events + EVENT_SUBSCRIBE_MEMBER(m_ETankSteer, &Systems::PhysicsSystem::OnTankSteer); + EVENT_SUBSCRIBE_MEMBER(m_ESetVelocity, &Systems::PhysicsSystem::OnSetVelocity); + + hkMemorySystem::FrameInfo finfo(6000 * 1024); // Allocate 6MB of Physics solver buffer + hkMemoryRouter* memoryRouter = hkMemoryInitUtil::initDefault(hkMallocAllocator::m_defaultMallocAllocator, finfo); + hkBaseSystem::init(memoryRouter, HavokErrorReport); + + + // Get the number of physical threads available on the system + hkHardwareInfo hwInfo; + hkGetHardwareInfo(hwInfo); + m_TotalNumThreadsUsed = hwInfo.m_numThreads; + + // We use one less than this for our thread pool, because we must also use this thread for our simulation + hkCpuJobThreadPoolCinfo threadPoolCinfo; + threadPoolCinfo.m_numThreads = m_TotalNumThreadsUsed - 1; + + // This line enables timers collection, by allocating 200 Kb per thread. If you leave this at its default (0), + // timer collection will not be enabled. + threadPoolCinfo.m_timerBufferPerThreadAllocation = 200000; + m_ThreadPool = new hkCpuJobThreadPool(threadPoolCinfo); + + hkJobQueueCinfo info; + info.m_jobQueueHwSetup.m_numCpuThreads = m_TotalNumThreadsUsed; + m_JobQueue = new hkJobQueue(info); + + // + // Enable monitors for this thread. + // + + // Monitors have been enabled for thread pool threads already (see above comment). + hkMonitorStream::getInstance().resize(200000); + { - hkMemorySystem::FrameInfo finfo(500 * 1024); // Allocate 500KB of Physics solver buffer - hkMemoryRouter* memoryRouter = hkMemoryInitUtil::initDefault(hkMallocAllocator::m_defaultMallocAllocator, finfo); - hkBaseSystem::init(memoryRouter, HavokErrorReport); - - hkpWorldCinfo worldInfo; + + // Set the simulation type of the world to multi-threaded. + worldInfo.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_MULTITHREADED; + worldInfo.setupSolverInfo(hkpWorldCinfo::SOLVER_TYPE_4ITERS_MEDIUM); - worldInfo.m_gravity = hkVector4(0.0f, -9.8f, 0.0f); + worldInfo.m_gravity = hkVector4(0.0f, -9.82f, 0.0f); worldInfo.m_broadPhaseBorderBehaviour = hkpWorldCinfo::BROADPHASE_BORDER_FIX_ENTITY; // just fix the entity if the object falls off too far // You must specify the size of the broad phase - objects should not be simulated outside this region worldInfo.setBroadPhaseWorldSize(1000.0f); m_PhysicsWorld = new hkpWorld(worldInfo); - } - // Register all collision agents, even though only box - box will be used in this particular example. - // It's important to register collision agents before adding any entities to the world. - hkpAgentRegisterUtil::registerAllAgents(m_PhysicsWorld->getCollisionDispatcher()); - - // - // Initialize the visual debugger so we can connect remotely to the simulation - // The context must exist beyond the use of the VDB instance, and you can make - // whatever contexts you like for your own viewer types. - // - hkpPhysicsContext* context = new hkpPhysicsContext; - hkpPhysicsContext::registerAllPhysicsProcesses(); // all the physics viewers - context->addWorld(m_PhysicsWorld); // add the physics world so the viewers can see it - SetupVisualDebugger(context); - //SetupPhysics(m_PhysicsWorld); + // When the simulation type is SIMULATION_TYPE_MULTITHREADED, in the debug build, the sdk performs checks + // to make sure only one thread is modifying the world at once to prevent multithreaded bugs. Each thread + // must call markForRead / markForWrite before it modifies the world to enable these checks. + m_PhysicsWorld->markForWrite(); + + // Register all collision agents, even though only box - box will be used in this particular example. + // It's important to register collision agents before adding any entities to the world. + hkpAgentRegisterUtil::registerAllAgents(m_PhysicsWorld->getCollisionDispatcher()); + + // We need to register all modules we will be running multi-threaded with the job queue + m_PhysicsWorld->registerWithJobQueue(m_JobQueue); + + + // + // Initialize the visual debugger so we can connect remotely to the simulation + // The context must exist beyond the use of the VDB instance, and you can make + // whatever contexts you like for your own viewer types. + // + m_Context = new hkpPhysicsContext; + hkpPhysicsContext::registerAllPhysicsProcesses(); // all the physics viewers + m_Context->addWorld(m_PhysicsWorld); // add the physics world so the viewers can see it + + SetupVisualDebugger(m_Context); + + m_PhysicsWorld->unmarkForWrite(); + } + } void Systems::PhysicsSystem::RegisterComponents(ComponentFactory* cf) { cf->Register("Physics", []() { return new Components::Physics(); }); - cf->Register("Box", []() { return new Components::Box(); }); - cf->Register("Sphere", []() { return new Components::Sphere(); }); + cf->Register("BoxShape", []() { return new Components::BoxShape(); }); + cf->Register("SphereShape", []() { return new Components::SphereShape(); }); cf->Register("Vehicle", []() { return new Components::Vehicle(); }); cf->Register("Wheel", []() { return new Components::Wheel(); }); + cf->Register("MeshShape", []() { return new Components::MeshShape(); }); + cf->Register("HingeConstraint", []() { return new Components::HingeConstraint(); }); + cf->Register("WheelPair", []() { return new Components::WheelPair(); }); } void Systems::PhysicsSystem::Update(double dt) @@ -74,6 +123,7 @@ void Systems::PhysicsSystem::Update(double dt) for (auto pair : *m_World->GetEntities()) { EntityID entity = pair.first; + EntityID parent = pair.second; if (m_RigidBodies.find(entity) == m_RigidBodies.end()) continue; @@ -82,29 +132,50 @@ void Systems::PhysicsSystem::Update(double dt) if (!transformComponent) continue; - if(m_RigidBodies[entity]->isActive()) { - hkVector4 position(transformComponent->Position.x, transformComponent->Position.y, transformComponent->Position.z); - hkQuaternion rotation(transformComponent->Orientation.x, transformComponent->Orientation.y, transformComponent->Orientation.z, transformComponent->Orientation.w); + hkVector4 position; + hkQuaternion rotation; + + if (parent) + { + auto absoluteTransform = m_World->GetSystem("TransformSystem")->AbsoluteTransform(entity); + position = ConvertPosition(absoluteTransform.Position); + rotation = ConvertRotation(absoluteTransform.Orientation); + } + else + { + position = ConvertPosition(transformComponent->Position); + rotation = ConvertRotation(transformComponent->Orientation); + } + m_PhysicsWorld->markForWrite(); m_RigidBodies[entity]->setPositionAndRotation(position, rotation); + m_PhysicsWorld->unmarkForWrite(); + } } - - - - static const double timestep = 1 / 30.0; + static const double timestep = 1 / 60.0; m_Accumulator += dt; while (m_Accumulator >= timestep) { - m_PhysicsWorld->stepDeltaTime(timestep); - m_Accumulator -= timestep; - } + m_PhysicsWorld->stepMultithreaded(m_JobQueue, m_ThreadPool, timestep); + //m_PhysicsWorld->stepDeltaTime(timestep); - // Step the visual debugger - StepVisualDebugger(); + m_Accumulator -= timestep; + + m_Context->syncTimers(m_ThreadPool); + // Step the visual debugger + StepVisualDebugger(); + + // Clear accumulated timer data in this thread and all slave threads + hkMonitorStream::getInstance().reset(); + m_ThreadPool->clearTimerData(); + } + + + } void Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, EntityID parent) @@ -119,6 +190,7 @@ void Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, EntityID p EntityID car = m_World->GetEntityParent(entity); if(m_Vehicles.find(car) != m_Vehicles.end()) { + m_PhysicsWorld->markForWrite(); m_Vehicles[car]->getChassis()->activate(); hkVector4 hardPoint = m_Vehicles[car]->m_suspension->m_wheelParams[wheelComponent->ID].m_hardpointChassisSpace; @@ -129,40 +201,28 @@ void Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, EntityID p hkQuaternion steeringOrientation = m_Vehicles[car]->m_wheelsInfo[wheelComponent->ID].m_steeringOrientationChassisSpace; hkReal spinAngle = -m_Vehicles[car]->m_wheelsInfo[wheelComponent->ID].m_spinAngle; - glm::quat orientation = glm::quat(steeringOrientation(3), steeringOrientation(0), steeringOrientation(1), steeringOrientation(2)) * glm::angleAxis(spinAngle, glm::vec3(1, 0, 0)); + glm::quat orientation = ConvertRotation(steeringOrientation) * glm::angleAxis(spinAngle, glm::vec3(1, 0, 0)); transformComponent->Orientation = orientation * wheelComponent->OriginalOrientation; + m_PhysicsWorld->unmarkForWrite(); } } - else if(m_Vehicles.find(entity) != m_Vehicles.end()) - { - hkVector4 position = m_RigidBodies[entity]->getPosition(); - transformComponent->Position = glm::vec3(position(0), position(1), position(2)); - hkQuaternion orientation = m_RigidBodies[entity]->getRotation(); - transformComponent->Orientation = glm::quat(orientation(3),orientation(0), orientation(1), orientation(2)); - - } else if(m_RigidBodies.find(entity) != m_RigidBodies.end()) { - if(m_RigidBodies[entity]->isActive()) + auto transformComponentParent = m_World->GetComponent(parent, "Transform"); + + transformComponent->Position = ConvertPosition(m_RigidBodies[entity]->getPosition()); + transformComponent->Orientation = ConvertRotation(m_RigidBodies[entity]->getRotation()); + // TODO: No support for Scale, MIGHT be possible + + if (transformComponentParent) { - hkVector4 position = m_RigidBodies[entity]->getPosition(); - transformComponent->Position = glm::vec3(position(0), position(1), position(2)); - hkQuaternion orientation = m_RigidBodies[entity]->getRotation(); - transformComponent->Orientation = glm::quat(orientation(3),orientation(0), orientation(1), orientation(2)); + transformComponent->Position -= transformComponentParent->Position; + transformComponent->Position = transformComponent->Position * transformComponentParent->Orientation; + transformComponent->Orientation = transformComponent->Orientation * glm::inverse(transformComponentParent->Orientation); } } - - // HACK: Vehicle test-controls - auto vehicleComponent = m_World->GetComponent(entity, "Vehicle"); - auto inputComponent = m_World->GetComponent(entity, "Input"); - if (vehicleComponent && inputComponent) - { - hkpVehicleDriverInputAnalogStatus* deviceStatus = (hkpVehicleDriverInputAnalogStatus*)m_Vehicles[entity]->m_deviceStatus; - deviceStatus->m_positionY = inputComponent->KeyState[GLFW_KEY_UP] * -1 + inputComponent->KeyState[GLFW_KEY_DOWN] * 1; - deviceStatus->m_positionX = inputComponent->KeyState[GLFW_KEY_LEFT] * -1 + inputComponent->KeyState[GLFW_KEY_RIGHT] * 1; - deviceStatus->m_handbrakeButtonPressed = inputComponent->KeyState[GLFW_KEY_RIGHT_CONTROL]; - } + } void Systems::PhysicsSystem::OnEntityCommit( EntityID entity ) @@ -171,7 +231,6 @@ void Systems::PhysicsSystem::OnEntityCommit( EntityID entity ) if (!transformComponent) return; - auto wheelComponent = m_World->GetComponent(entity, "Wheel"); if (wheelComponent) { @@ -180,201 +239,250 @@ void Systems::PhysicsSystem::OnEntityCommit( EntityID entity ) m_Wheels.push_back(entity); } + EntityID entityParent = m_World->GetEntityBaseParent(entity); + + auto sphereComponent = m_World->GetComponent(entity, "SphereShape"); + auto boxComponent = m_World->GetComponent(entity, "BoxShape"); + auto meshShapeComponent = m_World->GetComponent(entity, "MeshShape"); + + if(entityParent == entity && (sphereComponent || boxComponent || meshShapeComponent)) + { + LOG_ERROR("Entity: %i , Only the children can have a shapeComponent", entity); + return; + } + auto physicsComponent = m_World->GetComponent(entity, "Physics"); - if (!physicsComponent) - return; - - auto sphereComponent = m_World->GetComponent(entity, "Sphere"); - auto boxComponent = m_World->GetComponent(entity, "Box"); - - - hkpConvexShape* shape; - hkpRigidBodyCinfo rigidBodyInfo; - hkMassProperties massProperties; - - if (sphereComponent) + if (physicsComponent) { - shape = new hkpSphereShape(sphereComponent->Radius); - rigidBodyInfo.m_shape = shape; - - if (physicsComponent->Static) + hkpShape* shape; + if(entityParent != entity) { - rigidBodyInfo.m_motionType = hkpMotion::MOTION_FIXED; - } - else - { - rigidBodyInfo.m_motionType = hkpMotion::MOTION_SPHERE_INERTIA; + LOG_ERROR("Entity: %i , Only the baseparent can have a PhysicsComponent", entity); + return; } - hkpInertiaTensorComputer::computeSphereVolumeMassProperties(sphereComponent->Radius, physicsComponent->Mass, massProperties); - - } - else if (boxComponent) - { - hkReal thickness = 0.05; - shape = new hkpBoxShape(hkVector4(boxComponent->Width - thickness, boxComponent->Height - thickness, boxComponent->Depth - thickness)); - rigidBodyInfo.m_shape = shape; - if (physicsComponent->Static) + if(! physicsComponent->Static) // Not static { - rigidBodyInfo.m_motionType = hkpMotion::MOTION_FIXED; - } - else - { - rigidBodyInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA; - } - hkpInertiaTensorComputer::computeBoxSurfaceMassProperties(hkVector4(boxComponent->Width - thickness, boxComponent->Height - thickness, boxComponent->Depth - thickness), physicsComponent->Mass, thickness, massProperties); - } - else - { - return; - } - - rigidBodyInfo.m_position.set(transformComponent->Position.x, transformComponent->Position.y, transformComponent->Position.z); - rigidBodyInfo.m_inertiaTensor = massProperties.m_inertiaTensor; - rigidBodyInfo.m_centerOfMass = massProperties.m_centerOfMass; - rigidBodyInfo.m_mass = massProperties.m_mass; - - // Create RigidBody - hkpRigidBody* rigidBody = new hkpRigidBody(rigidBodyInfo); - - - auto vehicleComponent = m_World->GetComponent(entity, "Vehicle"); - if (vehicleComponent && m_Vehicles.find(entity) == m_Vehicles.end()) - { - for (int i = 0; i < m_Wheels.size(); i++) - { - if(m_World->GetEntityParent(m_Wheels[i]) != entity) + hkArray shapeArray; + for (auto &shapeData : m_Shapes[entity]) { - m_Wheels.erase(m_Wheels.begin() + i); - i--; + shapeArray.pushBack(shapeData.Shape); + } + + + // Create a hkpListShape* of all the childEntities collected in m_ShapeArrays + hkpListShape* listShape = new hkpListShape(shapeArray.begin(), shapeArray.getSize(), hkpShapeContainer::REFERENCE_POLICY_INCREMENT); + // Save the listShape for further use + m_ListShapes[entity] = listShape; + shape = listShape; + + ////////////////////////////////// + //******************************// + // Add a hkpBvShape // + //******************************// + ////////////////////////////////// + + // Clean up for less memory usage + m_Shapes.erase(entity); + + hkMassProperties massProperties; + hkpInertiaTensorComputer::computeShapeVolumeMassProperties(shape, physicsComponent->Mass, massProperties); + + hkpRigidBodyCinfo rigidBodyInfo; + { + rigidBodyInfo.m_shape = shape; + rigidBodyInfo.m_motionType = hkpMotion::MOTION_DYNAMIC; + auto absoluteTransform = m_World->GetSystem("TransformSystem")->AbsoluteTransform(entity); + hkVector4 position = ConvertPosition(absoluteTransform.Position); + hkQuaternion rotation = ConvertRotation(absoluteTransform.Orientation); + rigidBodyInfo.m_position.set(position(0), position(1), position(2), position(3)); + rigidBodyInfo.m_rotation.set(rotation(0), rotation(1), rotation(2), rotation(3)); + + rigidBodyInfo.m_inertiaTensor = massProperties.m_inertiaTensor; + //rigidBodyInfo.m_centerOfMass = massProperties.m_centerOfMass; //HACK: CENTER OF MASS ALWAYS IN THE CENTER + rigidBodyInfo.m_mass = massProperties.m_mass; + } + // Create RigidBody + hkpRigidBody* rigidBody = new hkpRigidBody(rigidBodyInfo); + + auto vehicleComponent = m_World->GetComponent(entity, "Vehicle"); + if (vehicleComponent && m_Vehicles.find(entity) == m_Vehicles.end()) + { + for (int i = 0; i < m_Wheels.size(); i++) + { + if(m_World->GetEntityParent(m_Wheels[i]) != entity) + { + m_Wheels.erase(m_Wheels.begin() + i); + i--; + } + } + + + VehicleSetup vehicleSetup; + // Create the basic vehicle. + m_Vehicles[entity] = new hkpVehicleInstance(rigidBody); + m_PhysicsWorld->markForWrite(); + vehicleSetup.buildVehicle(m_World, m_PhysicsWorld, *m_Vehicles[entity], entity, m_Wheels); + // Add the vehicle's entities and phantoms to the world + m_Vehicles[entity]->addToWorld(m_PhysicsWorld); + + m_RigidBodies[entity] = rigidBody; + + // The vehicle is an action + m_PhysicsWorld->addAction(m_Vehicles[entity]); + m_PhysicsWorld->unmarkForWrite(); + + //m_Vehicles[entity]->m_rpm = 0.0f; // Not sure why this one should be here + m_Wheels.clear(); + shape->removeReference(); + rigidBody->removeReference(); + } + else + { + m_PhysicsWorld->markForWrite(); + m_PhysicsWorld->addEntity(rigidBody); + m_RigidBodies[entity] = rigidBody; + m_PhysicsWorld->unmarkForWrite(); + + shape->removeReference(); + rigidBody->removeReference(); } } - VehicleSetup vehicleSetup; - - // Create the basic vehicle. - m_Vehicles[entity] = new hkpVehicleInstance(rigidBody); - vehicleSetup.buildVehicle(m_World, m_PhysicsWorld, *m_Vehicles[entity], entity, m_Wheels); - // Add the vehicle's entities and phantoms to the world - m_Vehicles[entity]->addToWorld(m_PhysicsWorld); - - m_RigidBodies[entity] = rigidBody; - - // The vehicle is an action - m_PhysicsWorld->addAction(m_Vehicles[entity]); - - //m_Vehicles[entity]->m_rpm = 0.0f; // Not sure why this one should be here - m_Wheels.clear(); - shape->removeReference(); - rigidBody->removeReference(); - } - else - { - m_PhysicsWorld->addEntity(rigidBody); - m_RigidBodies[entity] = rigidBody; - shape->removeReference(); - rigidBody->removeReference(); - } -} -/* - -void Systems::PhysicsSystem::SetUpPhysicsState(EntityID entity, EntityID parent) -{ - auto transformComponent = m_World->GetComponent(entity, "Transform"); - if (!transformComponent) - return; - - auto physicsComponent = m_World->GetComponent(entity, "Physics"); - if (!physicsComponent) - return; - - auto sphereComponent = m_World->GetComponent(entity, "Sphere"); - auto boxComponent = m_World->GetComponent(entity, "Box"); - - - hkpConvexShape* shape; - hkpRigidBodyCinfo rigidBodyInfo; - hkMassProperties massProperties; - - - if (sphereComponent) - { - shape = new hkpSphereShape(sphereComponent->Radius); - rigidBodyInfo.m_shape = shape; - - if (physicsComponent->Static) + else // Static { - rigidBodyInfo.m_motionType = hkpMotion::MOTION_FIXED; - } - else - { - rigidBodyInfo.m_motionType = hkpMotion::MOTION_SPHERE_INERTIA; - } - - hkpInertiaTensorComputer::computeSphereVolumeMassProperties(sphereComponent->Radius, physicsComponent->Mass, massProperties); - - } - else if (boxComponent) - { - hkReal thickness = 0.05; - shape = new hkpBoxShape(hkVector4(boxComponent->Width - thickness, boxComponent->Height - thickness, boxComponent->Depth - thickness)); - rigidBodyInfo.m_shape = shape; - if (physicsComponent->Static) - { - rigidBodyInfo.m_motionType = hkpMotion::MOTION_FIXED; - } - else - { - rigidBodyInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA; - } - hkpInertiaTensorComputer::computeBoxSurfaceMassProperties(hkVector4(boxComponent->Width - thickness, boxComponent->Height - thickness, boxComponent->Depth - thickness), physicsComponent->Mass, thickness, massProperties); - } - else - { - return; - } - - rigidBodyInfo.m_position.set(transformComponent->Position.x, transformComponent->Position.y, transformComponent->Position.z); - rigidBodyInfo.m_inertiaTensor = massProperties.m_inertiaTensor; - rigidBodyInfo.m_centerOfMass = massProperties.m_centerOfMass; - rigidBodyInfo.m_mass = massProperties.m_mass; + // Create the hkpStaticCompoundShape and add the instances. + // "meshShape" should not be modified by the user in any way after adding it as an instance. + hkpStaticCompoundShape* staticCompoundShape = new hkpStaticCompoundShape(); - // Create RigidBody - hkpRigidBody* rigidBody = new hkpRigidBody(rigidBodyInfo); - + for (auto &shapeData : m_Shapes[entity]) + { + + auto childTransformComponent = m_World->GetComponent(shapeData.Entity, "Transform"); - auto vehicleComponent = m_World->GetComponent(entity, "Vehicle"); - if (vehicleComponent && m_Vehicles.find(entity) == m_Vehicles.end()) - { - VehicleSetup vehicleSetup; + hkVector4 position = ConvertPosition(childTransformComponent->Position); + hkQuaternion rotation = ConvertRotation(childTransformComponent->Orientation); + hkVector4 scale = ConvertScale(childTransformComponent->Scale); + hkQsTransform transform(position, rotation, scale); - // Create the basic vehicle. - m_Vehicles[entity] = new hkpVehicleInstance(rigidBody); - vehicleSetup.buildVehicle(m_PhysicsWorld, *m_Vehicles[entity]); - // Add the vehicle's entities and phantoms to the world - m_Vehicles[entity]->addToWorld(m_PhysicsWorld); - - m_RigidBodies[entity] = rigidBody; + staticCompoundShape->addInstance(shapeData.Shape, transform); + } - // The vehicle is an action - m_PhysicsWorld->addAction(m_Vehicles[entity]); + // This must be called after adding the instances and before using the shape. + staticCompoundShape->bake(); + shape = staticCompoundShape; + m_Shapes.erase(entity); + hkMassProperties massProperties; + hkpInertiaTensorComputer::computeShapeVolumeMassProperties(shape, physicsComponent->Mass, massProperties); - //m_Vehicles[entity]->m_rpm = 0.0f; // Not sure why this one should be here + hkpRigidBodyCinfo rigidBodyInfo; + { + rigidBodyInfo.m_shape = shape; + rigidBodyInfo.m_motionType = hkpMotion::MOTION_FIXED; + auto absoluteTransform = m_World->GetSystem("TransformSystem")->AbsoluteTransform(entity); + hkVector4 position = ConvertPosition(absoluteTransform.Position); + hkQuaternion rotation = ConvertRotation(absoluteTransform.Orientation); + rigidBodyInfo.m_position.set(position(0), position(1), position(2), position(3)); + rigidBodyInfo.m_rotation.set(rotation(0), rotation(1), rotation(2), rotation(3)); + + rigidBodyInfo.m_inertiaTensor = massProperties.m_inertiaTensor; + //rigidBodyInfo.m_centerOfMass = massProperties.m_centerOfMass; //HACK: CENTER OF MASS ALWAYS IN THE CENTER + rigidBodyInfo.m_mass = massProperties.m_mass; + } + // Create RigidBody + hkpRigidBody* rigidBody = new hkpRigidBody(rigidBodyInfo); + + m_PhysicsWorld->markForWrite(); + m_PhysicsWorld->addEntity(rigidBody); + m_RigidBodies[entity] = rigidBody; + m_PhysicsWorld->unmarkForWrite(); shape->removeReference(); rigidBody->removeReference(); + + + } + } else { - m_PhysicsWorld->addEntity(rigidBody); - m_RigidBodies[entity] = rigidBody; - shape->removeReference(); - rigidBody->removeReference(); + + //TODO: COMMENT THIS SECTION + if(sphereComponent) + { + hkpSphereShape* sphereShape = new hkpSphereShape(sphereComponent->Radius); + + hkQsTransform transform( ConvertPosition(transformComponent->Position), ConvertRotation(transformComponent->Orientation), ConvertScale(transformComponent->Scale)); + hkpConvexTransformShape* transformedSphereShape = new hkpConvexTransformShape( sphereShape, transform ); + + m_Shapes[entityParent].push_back(ShapeArrayData(entity, transformedSphereShape)); + + sphereShape->removeReference(); + } + //TODO: COMMENT THIS SECTION + else if(boxComponent) + { + hkReal thickness = 0.05; + hkpBoxShape* boxShape = new hkpBoxShape(hkVector4(boxComponent->Width- thickness, boxComponent->Height -thickness, boxComponent->Depth - thickness), thickness); + + hkQsTransform transform( ConvertPosition(transformComponent->Position), ConvertRotation(transformComponent->Orientation), ConvertScale(transformComponent->Scale)); + hkpConvexTransformShape* transformedBoxShape = new hkpConvexTransformShape( boxShape, transform ); + m_Shapes[entityParent].push_back(ShapeArrayData(entity, transformedBoxShape)); + boxShape->removeReference(); + } + else if(meshShapeComponent) + { + std::vector* vertices = new std::vector; + std::vector* vertexIndices = new std::vector; + auto meshShape = m_World->GetResourceManager()->Load("OBJ", meshShapeComponent->ResourceName); + + for (auto &vertex : meshShape->Vertices) + { + hkReal x, y, z; + std::tie(x, y, z) = vertex; + vertices->push_back(x); + vertices->push_back(y); + vertices->push_back(z); + } + + int i = 0; + for (auto &face : meshShape->Faces) + { + for (auto &faceDef : face.Definitions) + { + vertexIndices->push_back(faceDef.VertexIndex - 1); + } + } + + hkpExtendedMeshShape* mesh = new hkpExtendedMeshShape(); + hkReal thickness = 0.05f; // HACK: Convex radius should be 0 for static shapes and 0.05 for dynamic shapes. + mesh->setRadius(thickness); + { + hkpExtendedMeshShape::TrianglesSubpart part; + part.m_numTriangleShapes = meshShape->Faces.size(); + part.m_indexBase = vertexIndices->data(); + part.m_indexStriding = sizeof(hkUint16) * 3; + + part.m_numVertices = vertices->size() / 3; + part.m_vertexBase = vertices->data(); + part.m_vertexStriding = sizeof(hkReal) * 3; + + part.m_stridingType = hkpExtendedMeshShape::INDICES_INT16; + + mesh->addTrianglesSubpart(part); + } + hkpMoppCompilerInput mci; + hkpMoppCode* code = hkpMoppUtility::buildCode( mesh, mci ); + hkpMoppBvTreeShape* moppShape = new hkpMoppBvTreeShape(mesh, code); + + m_ExtendedMeshShapes[entity].Code = code; + m_ExtendedMeshShapes[entity].MoppShape = moppShape; + m_Shapes[entityParent].push_back(ShapeArrayData(entity, moppShape)); //HACK: Should maybe have transform, not sure yet + } } + + + } -*/ - - - void Systems::PhysicsSystem::TearDownPhysicsState(EntityID entity, EntityID parent) { @@ -396,8 +504,9 @@ void Systems::PhysicsSystem::SetupVisualDebugger(hkpPhysicsContext* worlds) { // Setup the visual debugger hkArray contexts; + contexts.pushBack(worlds); - + m_VisualDebugger = new hkVisualDebugger(contexts); m_VisualDebugger->serve(); @@ -423,3 +532,59 @@ void HK_CALL Systems::PhysicsSystem::HavokErrorReport(const char* msg, void*) LOG_INFO("%s", msg); } + +glm::vec3 Systems::PhysicsSystem::ConvertPosition(const hkVector4 &hkPosition) +{ + return glm::vec3(hkPosition(0), hkPosition(1), hkPosition(2)); +} + +const hkVector4& Systems::PhysicsSystem::ConvertPosition(glm::vec3 glmPosition) +{ + return hkVector4( glmPosition.x, glmPosition.y, glmPosition.z); +} + +glm::quat Systems::PhysicsSystem::ConvertRotation(const hkQuaternion &hkRotation) +{ + return glm::quat(hkRotation(3), hkRotation(0), hkRotation(1), hkRotation(2)); +} + +const hkQuaternion& Systems::PhysicsSystem::ConvertRotation(glm::quat glmRotation) +{ + hkQuaternion quat = hkQuaternion(glmRotation.x, glmRotation.y, glmRotation.z, glmRotation.w); + quat.normalize(); + return quat; +} + +glm::vec3 Systems::PhysicsSystem::ConvertScale(const hkVector4 &hkScale) +{ + return glm::vec3(hkScale(0), hkScale(1), hkScale(2)); +} + +const hkVector4& Systems::PhysicsSystem::ConvertScale(glm::vec3 glmScale) +{ + return hkVector4(glmScale.x, glmScale.y, glmScale.z); +} + +bool Systems::PhysicsSystem::OnTankSteer(const Events::TankSteer &event) +{ + auto vehicleComponent = m_World->GetComponent(event.Entity, "Vehicle"); + if (vehicleComponent && m_Vehicles.find(event.Entity) != m_Vehicles.end() && m_RigidBodies.find(event.Entity) != m_RigidBodies.end()) + { + m_PhysicsWorld->markForWrite(); + hkpVehicleDriverInputAnalogStatus* deviceStatus = (hkpVehicleDriverInputAnalogStatus*)m_Vehicles[event.Entity]->m_deviceStatus; + deviceStatus->m_positionX = event.PositionX; + deviceStatus->m_positionY = event.PositionY; + deviceStatus->m_handbrakeButtonPressed = event.Handbrake; + m_PhysicsWorld->unmarkForWrite(); + } + + return true; +} + +bool Systems::PhysicsSystem::OnSetVelocity( const Events::SetVelocity &event ) +{ + m_PhysicsWorld->markForWrite(); + m_RigidBodies[event.Entity]->setLinearVelocity(ConvertPosition(event.Velocity)); + m_PhysicsWorld->unmarkForWrite(); + return true; +} diff --git a/src/Systems/PhysicsSystem.h b/src/Systems/PhysicsSystem.h index c6ebe4a..7b2d259 100644 --- a/src/Systems/PhysicsSystem.h +++ b/src/Systems/PhysicsSystem.h @@ -2,12 +2,20 @@ #define PhysicsSystem_h__ #include "System.h" +#include "Systems/TransformSystem.h" #include "Components/Transform.h" #include "Components/Physics.h" -#include "Components/Sphere.h" -#include "Components/Box.h" +#include "Components/BoxShape.h" +#include "Components/SphereShape.h" #include "Components/Vehicle.h" #include "Components/Input.h" +#include "Components/MeshShape.h" +#include "Components/HingeConstraint.h" +#include "Components/WheelPair.h" +#include "Components/TowerSteering.h" +#include "Events/TankSteer.h" +#include "Events/SetVelocity.h" +#include "OBJ.h" // Math and base include #include @@ -34,6 +42,21 @@ #include #include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + #include "Physics/VehicleSetup.h" #include @@ -59,6 +82,13 @@ private: double m_Accumulator; hkpWorld* m_PhysicsWorld; + // Events + EventRelay m_ETankSteer; + bool OnTankSteer(const Events::TankSteer &event); + + EventRelay m_ESetVelocity; + bool OnSetVelocity(const Events::SetVelocity &event); + void SetUpPhysicsState(EntityID entity, EntityID parent); void TearDownPhysicsState(EntityID entity, EntityID parent); @@ -67,12 +97,54 @@ private: void StepVisualDebugger(); static void HK_CALL HavokErrorReport(const char* msg, void*); void SetupPhysics(hkpWorld* physicsWorld); + + // Converterfunctions + glm::vec3 ConvertPosition(const hkVector4 &hkPosition); + const hkVector4& ConvertPosition(glm::vec3 glmPosition); + + glm::quat ConvertRotation(const hkQuaternion &hkRotation); + const hkQuaternion& ConvertRotation(glm::quat glmRotation); + + glm::vec3 ConvertScale(const hkVector4 &hkScale); + const hkVector4&ConvertScale(glm::vec3 glmScale); std::unordered_map m_RigidBodies; + + hkJobThreadPool* m_ThreadPool; + hkJobQueue* m_JobQueue; + int m_TotalNumThreadsUsed; + hkpPhysicsContext* m_Context; + std::unordered_map m_Vehicles; std::vector m_Wheels; hkpVehicleInstance* Systems::PhysicsSystem::createVehicle(VehicleSetup& vehicleSetup, hkpRigidBody* chassis); + + + struct ShapeArrayData + { + ShapeArrayData(EntityID entity, hkpShape* shape) + { + Entity = entity; + Shape = shape; + } + EntityID Entity; + hkpShape* Shape; + }; + std::unordered_map> m_Shapes; + std::unordered_map m_ListShapes; + + + + struct ExtendedShapeData + { + hkpExtendedMeshShape* ExtendedMeshShape; + std::vector* Vertices; + std::vector* VertexIndices; + hkpMoppCode* Code; + hkpMoppBvTreeShape* MoppShape; + }; + std::unordered_map m_ExtendedMeshShapes; }; } diff --git a/src/Systems/RenderSystem.cpp b/src/Systems/RenderSystem.cpp index fe254f4..4f0e727 100755 --- a/src/Systems/RenderSystem.cpp +++ b/src/Systems/RenderSystem.cpp @@ -23,10 +23,11 @@ void Systems::RenderSystem::UpdateEntity(double dt, EntityID entity, EntityID pa auto model = m_World->GetResourceManager()->Load("Model", modelComponent->ModelFile); if (model != nullptr) { - glm::vec3 position = m_TransformSystem->AbsolutePosition(entity); + /*glm::vec3 position = m_TransformSystem->AbsolutePosition(entity); glm::quat orientation = m_TransformSystem->AbsoluteOrientation(entity); - glm::vec3 scale = m_TransformSystem->AbsoluteScale(entity); - m_Renderer->AddModelToDraw(model, position, orientation, scale, modelComponent->Visible, modelComponent->ShadowCaster); + glm::vec3 scale = m_TransformSystem->AbsoluteScale(entity);*/ + Components::Transform absoluteTransform = m_TransformSystem->AbsoluteTransform(entity); + m_Renderer->AddModelToDraw(model, absoluteTransform.Position, absoluteTransform.Orientation, absoluteTransform.Scale, modelComponent->Visible, modelComponent->ShadowCaster); } } @@ -38,10 +39,11 @@ void Systems::RenderSystem::UpdateEntity(double dt, EntityID entity, EntityID pa position, pointLightComponent->Specular, pointLightComponent->Diffuse, - pointLightComponent->constantAttenuation, - pointLightComponent->linearAttenuation, - pointLightComponent->quadraticAttenuation, - pointLightComponent->spotExponent); + pointLightComponent->specularExponent, + pointLightComponent->ConstantAttenuation, + pointLightComponent->LinearAttenuation, + pointLightComponent->QuadraticAttenuation + ); } auto cameraComponent = m_World->GetComponent(entity, "Camera"); @@ -54,11 +56,24 @@ void Systems::RenderSystem::UpdateEntity(double dt, EntityID entity, EntityID pa m_Renderer->GetCamera()->NearClip(cameraComponent->NearClip); m_Renderer->GetCamera()->FarClip(cameraComponent->FarClip); } + + auto spriteComponent = m_World->GetComponent(entity, "Sprite"); + if(spriteComponent != nullptr) + { + //TEMP + Texture* texture = m_World->GetResourceManager()->Load("Texture", spriteComponent->SpriteFile); + //glBindTexture(GL_TEXTURE_2D, texture); + auto transform = m_World->GetComponent(spriteComponent->Entity, "Transform"); + glm::quat orientation2D = glm::angleAxis(glm::eulerAngles(transform->Orientation).z, glm::vec3(0, 0, -1)); + m_Renderer->AddTextureToDraw(texture, transform->Position, orientation2D, transform->Scale); + } } void Systems::RenderSystem::Initialize() { m_TransformSystem = m_World->GetSystem("TransformSystem"); + + m_Renderer->SetSphereModel(m_World->GetResourceManager()->Load("Model", "Models/Placeholders/PhysicsTest/Sphere.obj")); } void Systems::RenderSystem::RegisterComponents(ComponentFactory* cf) @@ -72,7 +87,8 @@ void Systems::RenderSystem::RegisterComponents(ComponentFactory* cf) void Systems::RenderSystem::RegisterResourceTypes(ResourceManager* rm) { - rm->RegisterType("Model", [rm](std::string resourceName) { return new Model(OBJ(resourceName), rm); }); + rm->RegisterType("Model", [rm](std::string resourceName) { return new Model(rm, *rm->Load("OBJ", resourceName)); }); + rm->RegisterType("OBJ", [](std::string resourceName) { return new OBJ(resourceName); }); rm->RegisterType("Texture", [](std::string resourceName) { return new Texture(resourceName); }); } diff --git a/src/Systems/TankSteeringSystem.cpp b/src/Systems/TankSteeringSystem.cpp new file mode 100644 index 0000000..6ecbfb9 --- /dev/null +++ b/src/Systems/TankSteeringSystem.cpp @@ -0,0 +1,135 @@ +#include "PrecompiledHeader.h" +#include "TankSteeringSystem.h" +#include "World.h" + +void Systems::TankSteeringSystem::RegisterComponents( ComponentFactory* cf ) +{ + cf->Register("TankSteering", []() { return new Components::TankSteering(); }); + cf->Register("TowerSteering", []() { return new Components::TowerSteering(); }); + cf->Register("BarrelSteering", []() { return new Components::BarrelSteering(); }); +} + +void Systems::TankSteeringSystem::Initialize() +{ + m_TankInputController = std::unique_ptr(new TankSteeringInputController(EventBroker)); + m_TowerInputController = std::unique_ptr(new TowerSteeringInputController(EventBroker)); +} + +void Systems::TankSteeringSystem::Update(double dt) +{ + m_TankInputController->Update(dt); + m_TowerInputController->Update(dt); +} + +void Systems::TankSteeringSystem::UpdateEntity(double dt, EntityID entity, EntityID parent) +{ + auto tankSteeringComponent = m_World->GetComponent(entity, "TankSteering"); + if(tankSteeringComponent) + { + Events::TankSteer e; + e.Entity = entity; + e.PositionX = m_TankInputController->PositionX; + e.PositionY = m_TankInputController->PositionY; + e.Handbrake = m_TankInputController->Handbrake; + EventBroker->Publish(e); + } + + auto towerSteeringComponent = m_World->GetComponent(entity, "TowerSteering"); + if(towerSteeringComponent) + { + auto transformComponent = m_World->GetComponent(entity, "Transform"); + glm::quat orientation = glm::angleAxis(towerSteeringComponent->TurnSpeed * m_TowerInputController->TowerDirection * (float)dt, towerSteeringComponent->Axis); + transformComponent->Orientation *= orientation; + } + + auto barrelSteeringComponent = m_World->GetComponent(entity, "BarrelSteering"); + if(barrelSteeringComponent) + { + auto transformComponent = m_World->GetComponent(entity, "Transform"); + auto absoluteTransform = m_World->GetSystem("TransformSystem")->AbsoluteTransform(entity); + glm::quat orientation = glm::angleAxis(barrelSteeringComponent->TurnSpeed * m_TowerInputController->BarrelDirection * (float)dt, barrelSteeringComponent->Axis); + transformComponent->Orientation *= orientation; + + if(m_TowerInputController->Shoot && m_TimeSinceLastShot[entity] > 1.0) + { + EntityID clone = m_World->CloneEntity(barrelSteeringComponent->ShotTemplate); + auto templateAbsoluteTransform = m_World->GetSystem("TransformSystem")->AbsoluteTransform(barrelSteeringComponent->ShotTemplate); + auto cloneTransform = m_World->GetComponent(clone, "Transform"); + cloneTransform->Position = templateAbsoluteTransform.Position; + cloneTransform->Orientation = absoluteTransform.Orientation * cloneTransform->Orientation; + Events::SetVelocity e; + e.Entity = clone; + e.Velocity = absoluteTransform.Orientation * (glm::vec3(0.f, 0.f, -1.f) * barrelSteeringComponent->ShotSpeed); + EventBroker->Publish(e); + m_TimeSinceLastShot[entity] = 0; + } + + m_TimeSinceLastShot[entity] += dt; + } +} + +void Systems::TankSteeringSystem::TankSteeringInputController::Update( double dt ) +{ + PositionX = m_Horizontal; + PositionY = m_Vertical; +} + +void Systems::TankSteeringSystem::TowerSteeringInputController::Update( double dt ) +{ + TowerDirection = m_TowerDirection; + BarrelDirection = m_BarrelDirection; + Shoot = m_Shoot; +} + +bool Systems::TankSteeringSystem::TankSteeringInputController::OnCommand(const Events::InputCommand &event) +{ + float val = event.Value; + if (event.Command == "horizontal") + { + m_Horizontal = val; + } + else if (event.Command == "vertical") + { + m_Vertical = -val; + } + + else if (event.Command == "handbrake") + { + Handbrake = val > 0; + } + + return true; +} + +bool Systems::TankSteeringSystem::TowerSteeringInputController::OnCommand( const Events::InputCommand &event ) +{ + float val = event.Value; + if(event.Command == "tower_rotation") + { + m_TowerDirection = -val; + } + else if(event.Command == "barrel_rotation") + { + m_BarrelDirection = val; + } + + else if (event.Command == "shoot") + { + m_Shoot = val > 0; + } + return true; +} + +bool Systems::TankSteeringSystem::TowerSteeringInputController::OnMouseMove( const Events::MouseMove &event ) +{ + return false; +} + +bool Systems::TankSteeringSystem::TankSteeringInputController::OnMouseMove( const Events::MouseMove &event ) +{ + return false; +} + + + + diff --git a/src/Systems/TankSteeringSystem.h b/src/Systems/TankSteeringSystem.h new file mode 100644 index 0000000..d264325 --- /dev/null +++ b/src/Systems/TankSteeringSystem.h @@ -0,0 +1,92 @@ +#include + +#include "System.h" +#include "Events/TankSteer.h" +#include "Events/SetVelocity.h" +#include "Components/Transform.h" +#include "Components/TankSteering.h" +#include "Components/TowerSteering.h" +#include "Components/BarrelSteering.h" +#include "Components/Vehicle.h" +#include "Systems/TransformSystem.h" +#include "InputController.h" + +namespace Systems +{ + + class TankSteeringSystem : public System + { + public: + TankSteeringSystem(World* world, std::shared_ptr<::EventBroker> eventBroker) + : System(world, eventBroker) { } + + void RegisterComponents(ComponentFactory* cf) override; + void Initialize() override; + + void Update(double dt) override; + void UpdateEntity(double dt, EntityID entity, EntityID parent) override; + + private: + class TankSteeringInputController; + std::unique_ptr m_TankInputController; + class TowerSteeringInputController; + std::unique_ptr m_TowerInputController; + + std::map m_TimeSinceLastShot; + }; + + class TankSteeringSystem::TankSteeringInputController : InputController + { + public: + TankSteeringInputController(std::shared_ptr<::EventBroker> eventBroker) + : InputController(eventBroker) + { + m_Horizontal = 0.f; + m_Vertical = 0.f; + PositionX = 0; + PositionY = 0; + Handbrake = false; + } + + float PositionY; + float PositionX; + bool Handbrake; + void Update(double dt); + protected: + virtual bool OnCommand(const Events::InputCommand &event); + virtual bool OnMouseMove(const Events::MouseMove &event); + + private: + float m_Horizontal; + float m_Vertical; + }; + + class TankSteeringSystem::TowerSteeringInputController : InputController + { + public: + TowerSteeringInputController(std::shared_ptr<::EventBroker> eventBroker) + : InputController(eventBroker) + { + m_TowerDirection = 0.f; + m_BarrelDirection = 0.f; + TowerDirection = 0.f; + BarrelDirection = 0.f; + + m_Shoot = false; + } + + float TowerDirection; + float BarrelDirection; + bool Shoot; + void Update(double dt); + protected: + virtual bool OnCommand(const Events::InputCommand &event); + virtual bool OnMouseMove(const Events::MouseMove &event); + + private: + float m_TowerDirection; + float m_BarrelDirection; + bool m_Shoot; + }; + +} \ No newline at end of file diff --git a/src/Systems/TransformSystem.cpp b/src/Systems/TransformSystem.cpp index 494acd0..3eccc26 100755 --- a/src/Systems/TransformSystem.cpp +++ b/src/Systems/TransformSystem.cpp @@ -24,10 +24,10 @@ glm::vec3 Systems::TransformSystem::AbsolutePosition(EntityID entity) //absPosition += transform->Position; entity = m_World->GetEntityParent(entity); auto transform2 = m_World->GetComponent(entity, "Transform"); - if (entity != 0) - absPosition += transform2->Orientation * transform->Position; - else + if (entity == 0) absPosition += transform->Position; + else + absPosition = transform2->Orientation * (absPosition + transform->Position); } while (entity != 0); return absPosition * accumulativeOrientation; @@ -60,3 +60,34 @@ glm::vec3 Systems::TransformSystem::AbsoluteScale(EntityID entity) return absScale; } + +Components::Transform Systems::TransformSystem::AbsoluteTransform(EntityID entity) +{ + glm::vec3 absPosition; + glm::quat absOrientation; + glm::vec3 absScale(1); + + do + { + auto transform = m_World->GetComponent(entity, "Transform"); + entity = m_World->GetEntityParent(entity); + auto transform2 = m_World->GetComponent(entity, "Transform"); + + // Position + if (entity == 0) + absPosition += transform->Position; + else + absPosition = transform2->Orientation * (absPosition + transform->Position); + // Orientation + absOrientation = transform->Orientation * absOrientation; + // Scale + absScale *= transform->Scale; + } while (entity != 0); + + Components::Transform transform; + transform.Position = absPosition; + transform.Orientation = absOrientation; + transform.Scale = absScale; + + return transform; +} diff --git a/src/Systems/TransformSystem.h b/src/Systems/TransformSystem.h index f4e6f48..7852628 100755 --- a/src/Systems/TransformSystem.h +++ b/src/Systems/TransformSystem.h @@ -14,7 +14,8 @@ public: : System(world, eventBroker) { } //void Update(double dt) override; //void UpdateEntity(double dt, EntityID entity, EntityID parent) override; - + + Components::Transform AbsoluteTransform(EntityID entity); glm::vec3 AbsolutePosition(EntityID entity); glm::quat AbsoluteOrientation(EntityID entity); glm::vec3 AbsoluteScale(EntityID entity); diff --git a/src/Texture.cpp b/src/Texture.cpp index 49256da..373db0d 100755 --- a/src/Texture.cpp +++ b/src/Texture.cpp @@ -15,6 +15,9 @@ void Texture::Load(std::string path) } m_Texture = m_TextureCache[path]; + glBindTexture(GL_TEXTURE_2D, m_Texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } void Texture::Bind() diff --git a/src/Util/Rectangle.h b/src/Util/Rectangle.h index 0d0db32..e55e268 100644 --- a/src/Util/Rectangle.h +++ b/src/Util/Rectangle.h @@ -1,95 +1,95 @@ -#ifndef Util_Rectangle_h__ -#define Util_Rectangle_h__ - -#include - -struct Rectangle -{ - Rectangle() - : X(0), Y(0), Width(0), Height(0) { } - - Rectangle(int x, int y, int width = 0, int height = 0) - : X(x), Y(y), Width(width), Height(height) { } - - /*Rectangle(const Rectangle &rect) - : X(rect.X), Y(rect.Y), Width(rect.Width), Height(rect.Height) { }*/ - - int X; - int Y; - int Width; - int Height; - - const int& GetLeft() const { return X; } - void SetLeft(int left) - { - Width += X - left; - X = left; - } - int GetRight() const { return X + Width; } - void SetRight(int right) - { - Width = right - X; - } - const int& GetTop() const { return Y; } - void SetTop(int top) - { - Height += Y - top; - Y = top; - } - int GetBottom() const { return Y + Height; } - int SetBottom(int bottom) - { - Height = bottom - Y; - } - - Rectangle& operator+=(const Rectangle &rhs) - { - SetLeft(std::min(GetLeft(), rhs.GetLeft())); - SetRight(std::max(GetRight(), rhs.GetRight())); - SetTop(std::min(GetTop(), rhs.GetTop())); - SetBottom(std::max(GetBottom(), rhs.GetBottom())); - } - - static bool Intersects(const Rectangle &r1, const Rectangle &r2) - { - return !(r2.GetLeft() > r1.GetRight() || r2.GetRight() < r1.GetLeft() || r2.GetTop() > r1.GetBottom() || r2.GetBottom() < r1.GetTop()); - } -}; - -inline bool operator==(const Rectangle &r1, const Rectangle &r2) -{ - return (r1.X == r2.X) && (r1.Y == r2.Y) && (r1.Width == r2.Width) && (r1.Height == r2.Height); -} - -inline bool operator!=(const Rectangle &lhs, const Rectangle &rhs) -{ - return !(lhs == rhs); -} - -inline bool operator<(const Rectangle &lhs, const Rectangle &rhs) -{ - return (lhs.Width < rhs.Width) && (lhs.Height < rhs.Height); -} - -inline bool operator>(const Rectangle &lhs, const Rectangle &rhs) -{ - return rhs < lhs; -} - -inline bool operator<=(const Rectangle &lhs, const Rectangle &rhs) -{ - return !(lhs > rhs); -} - -inline bool operator>=(const Rectangle &lhs, const Rectangle &rhs) -{ - return !(lhs < rhs); -} - -inline Rectangle operator+(Rectangle lhs, const Rectangle &rhs) -{ - lhs += rhs; - return lhs; -} - -#endif // Util_Rectangle_h__ +//#ifndef Util_Rectangle_h__ +//#define Util_Rectangle_h__ +// +//#include +// +//struct Rectangle +//{ +// Rectangle() +// : X(0), Y(0), Width(0), Height(0) { } +// +// Rectangle(int x, int y, int width = 0, int height = 0) +// : X(x), Y(y), Width(width), Height(height) { } +// +// /*Rectangle(const Rectangle &rect) +// : X(rect.X), Y(rect.Y), Width(rect.Width), Height(rect.Height) { }*/ +// +// int X; +// int Y; +// int Width; +// int Height; +// +// const int& GetLeft() const { return X; } +// void SetLeft(int left) +// { +// Width += X - left; +// X = left; +// } +// int GetRight() const { return X + Width; } +// void SetRight(int right) +// { +// Width = right - X; +// } +// const int& GetTop() const { return Y; } +// void SetTop(int top) +// { +// Height += Y - top; +// Y = top; +// } +// int GetBottom() const { return Y + Height; } +// int SetBottom(int bottom) +// { +// Height = bottom - Y; +// } +// +// Rectangle& operator+=(const Rectangle &rhs) +// { +// SetLeft(std::min(GetLeft(), rhs.GetLeft())); +// SetRight(std::max(GetRight(), rhs.GetRight())); +// SetTop(std::min(GetTop(), rhs.GetTop())); +// SetBottom(std::max(GetBottom(), rhs.GetBottom())); +// } +// +// static bool Intersects(const Rectangle &r1, const Rectangle &r2) +// { +// return !(r2.GetLeft() > r1.GetRight() || r2.GetRight() < r1.GetLeft() || r2.GetTop() > r1.GetBottom() || r2.GetBottom() < r1.GetTop()); +// } +//}; +// +//inline bool operator==(const Rectangle &r1, const Rectangle &r2) +//{ +// return (r1.X == r2.X) && (r1.Y == r2.Y) && (r1.Width == r2.Width) && (r1.Height == r2.Height); +//} +// +//inline bool operator!=(const Rectangle &lhs, const Rectangle &rhs) +//{ +// return !(lhs == rhs); +//} +// +//inline bool operator<(const Rectangle &lhs, const Rectangle &rhs) +//{ +// return (lhs.Width < rhs.Width) && (lhs.Height < rhs.Height); +//} +// +//inline bool operator>(const Rectangle &lhs, const Rectangle &rhs) +//{ +// return rhs < lhs; +//} +// +//inline bool operator<=(const Rectangle &lhs, const Rectangle &rhs) +//{ +// return !(lhs > rhs); +//} +// +//inline bool operator>=(const Rectangle &lhs, const Rectangle &rhs) +//{ +// return !(lhs < rhs); +//} +// +//inline Rectangle operator+(Rectangle lhs, const Rectangle &rhs) +//{ +// lhs += rhs; +// return lhs; +//} +// +//#endif // Util_Rectangle_h__ diff --git a/src/Util/UnorderedMapPair.h b/src/Util/UnorderedMapPair.h new file mode 100644 index 0000000..68d2355 --- /dev/null +++ b/src/Util/UnorderedMapPair.h @@ -0,0 +1,20 @@ +#ifndef Util_UnorderedMapPair_h__ +#define Util_UnorderedMapPair_h__ + +#include + +namespace std +{ + template struct hash> + { + inline size_t operator()(const pair & v) const + { + size_t seed = 0; + boost::hash_combine(seed, v.first); + boost::hash_combine(seed, v.second); + return seed; + } + }; +} + +#endif // Util_UnorderedMapPair_h__ \ No newline at end of file diff --git a/src/Util/defferedUtil.h b/src/Util/defferedUtil.h new file mode 100644 index 0000000..d362fac --- /dev/null +++ b/src/Util/defferedUtil.h @@ -0,0 +1,28 @@ +#ifndef UTIL_H +#define UTIL_H + +#include +#include +#include + +#define ZERO_MEM(a) memset(a, 0, sizeof(a)) + +#define ARRAY_SIZE_IN_ELEMENTS(a) (sizeof(a)/sizeof(a[0])) + +#define INVALID_OGL_VALUE 0xFFFFFFFF + +#define SAFE_DELETE(p) if (p) { delete p; p = NULL; } + +#define GLExitIfError() \ +{ \ + GLenum Error = glGetError(); \ + \ + if (Error != GL_NO_ERROR) { \ + printf("OpenGL error in %s:%d: 0x%x\n", __FILE__, __LINE__, Error); \ + exit(0); \ + } \ +} + +#define GLCheckError() (glGetError() == GL_NO_ERROR) + +#endif /* UTIL_H */ diff --git a/src/World.cpp b/src/World.cpp index 44bc45e..c84a2bd 100755 --- a/src/World.cpp +++ b/src/World.cpp @@ -22,16 +22,13 @@ EntityID World::GenerateEntityID() void World::RecursiveUpdate(std::shared_ptr system, double dt, EntityID parentEntity) { - for (auto pair : m_EntityParents) + for (auto &pair : m_EntityParents) { EntityID child = pair.first; EntityID parent = pair.second; - if (parent == parentEntity) - { - system->UpdateEntity(dt, child, parent); - RecursiveUpdate(system, dt, child); - } + system->UpdateEntity(dt, child, parent); + //RecursiveUpdate(system, dt, child); } } @@ -93,6 +90,7 @@ void World::ProcessEntityRemovals() for (auto entity : m_EntitiesToRemove) { m_EntityParents.erase(entity); + m_EntityChildren.erase(entity); // Remove components for (auto pair : m_EntityComponents[entity]) { @@ -116,7 +114,8 @@ void World::ProcessEntityRemovals() EntityID World::CreateEntity(EntityID parent /*= 0*/) { EntityID newEntity = GenerateEntityID(); - m_EntityParents.insert(std::pair(newEntity, parent)); + m_EntityParents[newEntity] = parent; + m_EntityChildren[parent].push_back(newEntity); return newEntity; } @@ -147,7 +146,62 @@ void World::CommitEntity(EntityID entity) } } +void World::AddComponent(EntityID entity, std::string componentType, std::shared_ptr component) +{ + component->Entity = entity; + m_ComponentsOfType[componentType].push_back(component); + m_EntityComponents[entity][componentType] = component; + for (auto pair : m_Systems) + { + auto system = pair.second; + system->OnComponentCreated(componentType, component); + } +} + void World::AddSystem(std::string systemType) { m_Systems[systemType] = std::shared_ptr(m_SystemFactory.Create(systemType)); } + +EntityID World::CloneEntity(EntityID entity, EntityID parent /* = 0 */) +{ + int clone = CreateEntity(parent); + + for (auto pair : m_EntityComponents[entity]) + { + auto type = pair.first; + if (type == "Template") + continue; + auto component = std::shared_ptr(pair.second->Clone()); + if (component != nullptr) + { + AddComponent(clone, type, component); + } + } + + auto itChildren = m_EntityChildren.find(entity); + if (itChildren != m_EntityChildren.end()) + { + for (EntityID child : itChildren->second) + { + CloneEntity(child, clone); + } + } + + CommitEntity(clone); + + return clone; +} + +std::list World::GetEntityChildren(EntityID entity) +{ + auto it = m_EntityChildren.find(entity); + if (it == m_EntityChildren.end()) + { + return std::list(); + } + else + { + return it->second; + } +} diff --git a/src/World.h b/src/World.h index 3581be1..0c4d76e 100755 --- a/src/World.h +++ b/src/World.h @@ -37,6 +37,7 @@ public: std::shared_ptr GetSystem(std::string systemType); EntityID CreateEntity(EntityID parent = 0); + EntityID CloneEntity(EntityID entity, EntityID parent = 0); void RemoveEntity(EntityID entity); @@ -44,6 +45,7 @@ public: EntityID GetEntityParent(EntityID entity); EntityID GetEntityBaseParent(EntityID entity); + std::list GetEntityChildren(EntityID entity); template T GetProperty(EntityID entity, std::string property) @@ -61,6 +63,11 @@ public: m_EntityProperties[entity][property] = value; } + void SetProperty(EntityID entity, std::string property, char* value) + { + m_EntityProperties[entity][property] = std::string(value); + } + template std::shared_ptr AddComponent(EntityID entity, std::string componentType); std::shared_ptr AddComponent(EntityID entity, std::string componentType); @@ -90,13 +97,16 @@ protected: EntityID m_LastEntityID; std::stack m_RecycledEntityIDs; - // A bottom to top tree. A map of child entities to parent entities. - std::unordered_map m_EntityParents; - std::unordered_map> m_EntityProperties; + std::unordered_map m_EntityParents; // child -> parent + std::unordered_map> m_EntityChildren; // parent -> child + std::unordered_map> m_EntityProperties; std::unordered_map>> m_ComponentsOfType; std::unordered_map>> m_EntityComponents; + // Internal: Add a component to an entity + void AddComponent(EntityID entity, std::string componentType, std::shared_ptr component); + std::list m_EntitiesToRemove; void ProcessEntityRemovals(); @@ -128,14 +138,8 @@ std::shared_ptr World::AddComponent(EntityID entity, std::string componentTyp return nullptr; } - component->Entity = entity; - m_ComponentsOfType[componentType].push_back(component); - m_EntityComponents[entity][componentType] = component; - for (auto pair : m_Systems) - { - auto system = pair.second; - system->OnComponentCreated(componentType, component); - } + AddComponent(entity, componentType, component); + return component; } @@ -143,7 +147,14 @@ std::shared_ptr World::AddComponent(EntityID entity, std::string componentTyp template T* World::GetComponent(EntityID entity, std::string componentType) { + + /*auto it0 = m_EntityComponents.find(entity); + + if (it0 == m_EntityComponents.end()) + return nullptr;*/ + auto components = m_EntityComponents[entity]; + auto it = components.find(componentType); if (it != components.end()) { diff --git a/src/gBuffer.cpp b/src/gBuffer.cpp deleted file mode 100644 index 5acf690..0000000 --- a/src/gBuffer.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "PrecompiledHeader.h" -#include "gBuffer.h" - -bool GBuffer::Init(unsigned int WindowWidth, unsigned int WindowHeight) -{ - // Create the FBO - glGenFramebuffers(1, &m_fbo); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo); - - // Create the gbuffer textures - glGenTextures(ARRAY_SIZE_IN_ELEMENTS(m_textures), m_textures); - glGenTextures(1, &m_depthTexture); - - for (unsigned int i = 0 ; i < ARRAY_SIZE_IN_ELEMENTS(m_textures) ; i++) { - glBindTexture(GL_TEXTURE_2D, m_textures[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, WindowWidth, WindowHeight, 0, GL_RGB, GL_FLOAT, NULL); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, m_textures[i], 0); - } - - // depth - glBindTexture(GL_TEXTURE_2D, m_depthTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, WindowWidth, WindowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, - NULL); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture, 0); - - GLenum DrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; - glDrawBuffers(ARRAY_SIZE_IN_ELEMENTS(DrawBuffers), DrawBuffers); - - GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - if (Status != GL_FRAMEBUFFER_COMPLETE) { - printf("FB error, status: 0x%x\n", Status); - return false; - } - - // restore default FBO - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - - return true; -} \ No newline at end of file diff --git a/src/gBuffer.h b/src/gBuffer.h deleted file mode 100644 index 721eb15..0000000 --- a/src/gBuffer.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef gBuffer_h__ -#define gBuffer_h__ - -#include - -class GBuffer -{ -public: - - enum GBUFFER_TEXTURE_TYPE { - GBUFFER_TEXTURE_TYPE_POSITION, - GBUFFER_TEXTURE_TYPE_DIFFUSE, - GBUFFER_TEXTURE_TYPE_NORMAL, - GBUFFER_TEXTURE_TYPE_TEXCOORD, - GBUFFER_NUM_TEXTURES - }; - - GBuffer(); - - ~GBuffer(); - - bool Init(unsigned int WindowWidth, unsigned int WindowHeight); - - void BindForWriting(); - - void BindForReading(); - -private: - - GLuint m_fbo; - GLuint m_textures[GBUFFER_NUM_TEXTURES]; - GLuint m_depthTexture; -}; - -#endif //gBuffer_h__ \ No newline at end of file diff --git a/vs11/Returngeance.psess b/vs11/Returngeance.psess new file mode 100644 index 0000000..1912c4c --- /dev/null +++ b/vs11/Returngeance.psess @@ -0,0 +1,83 @@ + + + + Returngeance.sln + Sampling + None + true + true + Timestamp + Cycles + 10000000 + 10 + 10 + + false + + + + false + 500 + + \Memory\Pages/sec + \PhysicalDisk(_Total)\Avg. Disk Queue Length + \Processor(_Total)\% Processor Time + + + + true + false + false + + false + + + false + + + + bin\Debug\Returngeance.exe + 01/01/0001 00:00:00 + true + true + false + false + false + false + false + true + false + Executable + bin\Debug\Returngeance.exe + ..\bin\Debug + + + IIS + InternetExplorer + true + false + + false + + + false + + {E8B4A2A2-882B-402A-98A7-8B4F7233C8B3}|Returngeance\Returngeance.vcxproj + Returngeance\Returngeance.vcxproj + Returngeance + + + + + Returngeance140427.vsp + + + Returngeance140427(1).vsp + + + + + :PB:{E8B4A2A2-882B-402A-98A7-8B4F7233C8B3}|Returngeance\Returngeance.vcxproj + + + \ No newline at end of file diff --git a/vs11/Returngeance/Returngeance.vcxproj b/vs11/Returngeance/Returngeance.vcxproj index 1de7fd5..5226852 100755 --- a/vs11/Returngeance/Returngeance.vcxproj +++ b/vs11/Returngeance/Returngeance.vcxproj @@ -39,33 +39,33 @@ - $(HAVOK_2013_1_0_r1_ROOT)\Source;$(BOOST_1_55_0_ROOT);$(SolutionDir)\..\src;$(SolutionDir)\..\libs;$(SolutionDir)\..\libs\glew-1.10.0\include;$(SolutionDir)\..\libs\glfw-3.0.4\include;$(SolutionDir)\..\libs\glm-0.9.5.3;$(SolutionDir)\..\libs\openal-soft-1.15.1\include;$(SolutionDir)\..\libs\bullet-2.82-r2704\src;$(SolutionDir)\..\libs\SOIL\src;$(IncludePath) - $(HAVOK_2013_1_0_r1_ROOT)\Lib\win32_vs2012_win7\debug_dll;$(BOOST_1_55_0_ROOT)\lib32-msvc-11.0;$(SolutionDir)\..\libs\glew-1.10.0\lib\Debug\Win32;$(SolutionDir)\..\libs\glfw-3.0.4\lib\Debug;$(SolutionDir)\..\libs\openal-soft-1.15.1\lib\Win32\Debug;$(SolutionDir)\..\libs\bullet-2.82-r2704\lib\Debug;$(SolutionDir)\..\libs\SOIL\lib\Debug;$(LibraryPath) + $(HAVOK_2013_1_0_r1_ROOT)\Source;$(BOOST_1_55_0_ROOT);$(SolutionDir)\..\src;$(SolutionDir)\..\libs;$(SolutionDir)\..\libs\glew-1.10.0\include;$(SolutionDir)\..\libs\glfw-3.0.4\include;$(SolutionDir)\..\libs\glm-0.9.5.3;$(SolutionDir)\..\libs\openal-soft-1.15.1\include;$(SolutionDir)\..\libs\bullet-2.82-r2704\src;$(SolutionDir)\..\libs\SOIL\src;$(DXSDK_DIR)\Include;$(IncludePath) + $(HAVOK_2013_1_0_r1_ROOT)\Lib\win32_vs2012_win7\debug_dll;$(BOOST_1_55_0_ROOT)\lib32-msvc-11.0;$(SolutionDir)\..\libs\glew-1.10.0\lib\Debug\Win32;$(SolutionDir)\..\libs\glfw-3.0.4\lib\Debug;$(SolutionDir)\..\libs\openal-soft-1.15.1\lib\Win32\Debug;$(SolutionDir)\..\libs\bullet-2.82-r2704\lib\Debug;$(SolutionDir)\..\libs\SOIL\lib\Debug;$(LibraryPath);$(DXSDK_DIR)\Lib\x86 $(SolutionDir)\..\bin\$(Configuration)\ $(SolutionDir)\..\obj\$(Configuration)\ - $(HAVOK_2013_1_0_r1_ROOT)\Source;$(BOOST_1_55_0_ROOT);$(SolutionDir)\..\src;$(SolutionDir)\..\libs;$(SolutionDir)\..\libs\glew-1.10.0\include;$(SolutionDir)\..\libs\glfw-3.0.4\include;$(SolutionDir)\..\libs\glm-0.9.5.3;$(SolutionDir)\..\libs\openal-soft-1.15.1\include;$(SolutionDir)\..\libs\bullet-2.82-r2704\src;$(SolutionDir)\..\libs\SOIL\src;$(IncludePath) - $(HAVOK_2013_1_0_r1_ROOT)\Lib\win32_vs2012_win7\release_dll;$(BOOST_1_55_0_ROOT)\lib32-msvc-11.0;$(SolutionDir)\..\libs\glfw-3.0.4\lib\Release;$(SolutionDir)\..\libs\glew-1.10.0\lib\Release\Win32;$(SolutionDir)\..\libs\openal-soft-1.15.1\lib\Win32\Release;$(SolutionDir)\..\libs\bullet-2.82-r2704\lib\Release;$(SolutionDir)\..\libs\SOIL\lib\Release;$(LibraryPath) + $(HAVOK_2013_1_0_r1_ROOT)\Source;$(BOOST_1_55_0_ROOT);$(SolutionDir)\..\src;$(SolutionDir)\..\libs;$(SolutionDir)\..\libs\glew-1.10.0\include;$(SolutionDir)\..\libs\glfw-3.0.4\include;$(SolutionDir)\..\libs\glm-0.9.5.3;$(SolutionDir)\..\libs\openal-soft-1.15.1\include;$(SolutionDir)\..\libs\bullet-2.82-r2704\src;$(SolutionDir)\..\libs\SOIL\src;$(DXSDK_DIR)\Include;$(IncludePath) + $(HAVOK_2013_1_0_r1_ROOT)\Lib\win32_vs2012_win7\release_dll;$(BOOST_1_55_0_ROOT)\lib32-msvc-11.0;$(SolutionDir)\..\libs\glfw-3.0.4\lib\Release;$(SolutionDir)\..\libs\glew-1.10.0\lib\Release\Win32;$(SolutionDir)\..\libs\openal-soft-1.15.1\lib\Win32\Release;$(SolutionDir)\..\libs\bullet-2.82-r2704\lib\Release;$(SolutionDir)\..\libs\SOIL\lib\Release;$(LibraryPath);$(DXSDK_DIR)\Lib\x86 $(SolutionDir)\..\bin\$(Configuration)\ $(SolutionDir)\..\obj\$(Configuration)\ Level3 - Disabled - true - _WINDOWS;WIN32;_WIN32;_DEBUG;HK_DEBUG;HK_DEBUG_SLOW;_XT_STATICLINK;_CONSOLE;_ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH;HK_CONFIG_SIMD=1;DEBUG;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions) + _X86_;_WINDOWS;WIN32;_WIN32;_DEBUG;HK_DEBUG;HK_DEBUG_SLOW;_XT_STATICLINK;_CONSOLE;_ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH;HK_CONFIG_SIMD=1;DEBUG;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions) Create PrecompiledHeader.h - true MultiThreadedDebugDLL - StreamingSIMDExtensions2 false + Default + ProgramDatabase + MaxSpeed + true true - OpenAL32.lib;opengl32.lib;glu32.lib;SOIL.lib;glew32d.lib;glfw3.lib;hkBase.lib;hkVisualize.lib;hkInternal.lib;hkSerialize.lib;hkGeometryUtilities.lib;hkcdInternal.lib;hkcdCollide.lib;hkpCollide.lib;hkpConstraint.lib;hkpConstraintSolver.lib;hkpDynamics.lib;hkpInternal.lib;hkpUtilities.lib;hkSceneData.lib;hkpVehicle.lib;%(AdditionalDependencies) + OpenAL32.lib;opengl32.lib;glu32.lib;SOIL.lib;XInput9_1_0.lib;glew32d.lib;glfw3.lib;hkBase.lib;hkVisualize.lib;hkInternal.lib;hkSerialize.lib;hkGeometryUtilities.lib;hkcdInternal.lib;hkcdCollide.lib;hkpCollide.lib;hkpConstraint.lib;hkpConstraintSolver.lib;hkpDynamics.lib;hkpInternal.lib;hkpUtilities.lib;hkSceneData.lib;hkpVehicle.lib;%(AdditionalDependencies) /ignore:4221 @@ -80,7 +80,7 @@ true true true - _CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions) + _X86_;_CRT_SECURE_NO_WARNINGS;_MBCS;HK_CONFIG_SIMD=1;%(PreprocessorDefinitions) Create PrecompiledHeader.h StreamingSIMDExtensions2 @@ -89,7 +89,7 @@ true true true - OpenAL32.lib;opengl32.lib;glu32.lib;SOIL.lib;glew32.lib;glfw3.lib;hkBase.lib;hkVisualize.lib;hkInternal.lib;hkSerialize.lib;hkGeometryUtilities.lib;hkcdInternal.lib;hkcdCollide.lib;hkpCollide.lib;hkpConstraint.lib;hkpConstraintSolver.lib;hkpDynamics.lib;hkpInternal.lib;hkpUtilities.lib;hkSceneData.lib;hkpVehicle.lib;%(AdditionalDependencies) + OpenAL32.lib;opengl32.lib;glu32.lib;SOIL.lib;XInput9_1_0.lib;glew32.lib;glfw3.lib;hkBase.lib;hkVisualize.lib;hkInternal.lib;hkSerialize.lib;hkGeometryUtilities.lib;hkcdInternal.lib;hkcdCollide.lib;hkpCollide.lib;hkpConstraint.lib;hkpConstraintSolver.lib;hkpDynamics.lib;hkpInternal.lib;hkpUtilities.lib;hkSceneData.lib;hkpVehicle.lib;%(AdditionalDependencies) @@ -112,9 +112,11 @@ + + @@ -123,27 +125,39 @@ - + + + + + + - + + + + + + + + @@ -151,6 +165,8 @@ + + @@ -172,19 +188,27 @@ + + + + + + + + @@ -192,6 +216,7 @@ + diff --git a/vs11/Returngeance/Returngeance.vcxproj.filters b/vs11/Returngeance/Returngeance.vcxproj.filters index 51e5aa8..f0252d5 100755 --- a/vs11/Returngeance/Returngeance.vcxproj.filters +++ b/vs11/Returngeance/Returngeance.vcxproj.filters @@ -50,11 +50,19 @@ + + Particle System\Systems + - + + Physics + Input + + Physics\Systems + @@ -126,6 +134,9 @@ {ee125b77-b275-4841-abc9-374957a89916} + + {42ae084f-ade8-402c-87ba-f03f6b846bc8} + @@ -226,19 +237,42 @@ Audio - - - Physics\Components - - - Physics\Components - Physics\Components Physics\Components + + Physics + + + Physics\Components + + + Physics\Components + + + Physics\Components + + + Util + + + Physics\Components + + + Physics\Components + + + Physics\Components + + + Particle System\Systems + + + Particle System\Components + GUI @@ -285,12 +319,43 @@ GUI + + Physics + + + Physics\Components + + + Physics\Events + + + Physics\Systems + + + Physics\Components + + + Physics\Components + + + Physics\Events + + + Input\Events + + + Input\Events + + + Input\Events + + + Input\Events + + - - Shaders - - + Shaders @@ -314,11 +379,29 @@ Shaders + + Shaders + Shaders Shaders + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + \ No newline at end of file