Merge branch 'master' into gui
Conflicts: src/GUI/Frame.h src/InputManager.cpp
This commit is contained in:
@@ -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;
|
||||
|
||||
+101
-15
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <boost/any.hpp>
|
||||
|
||||
#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<std::string, float> m_CommandValues; // command string -> command current value
|
||||
// Input binding tables
|
||||
std::unordered_map<int, std::string> m_KeyBindings; // GLFW_KEY... -> command string
|
||||
std::unordered_map<int, std::tuple<std::string, float>> m_KeyBindings; // GLFW_KEY... -> command string & value
|
||||
std::unordered_map<int, std::string> m_MouseButtonBindings; // GLFW_MOUSE_BUTTON... -> command string
|
||||
std::unordered_map<Gamepad::Axis, std::tuple<std::string, float>> m_GamepadAxisBindings; // Gamepad::Axis -> command string & value
|
||||
std::unordered_map<Gamepad::Button, std::tuple<std::string, float>> m_GamepadButtonBindings; // Gamepad::Button -> command string
|
||||
|
||||
// Input events
|
||||
EventRelay<Events::KeyDown> m_EKeyDown;
|
||||
@@ -42,13 +50,23 @@ private:
|
||||
bool OnMousePress(const Events::MousePress &event);
|
||||
EventRelay<Events::MouseRelease> m_EMouseRelease;
|
||||
bool OnMouseRelease(const Events::MouseRelease &event);
|
||||
EventRelay<Events::GamepadAxis> m_EGamepadAxis;
|
||||
bool OnGamepadAxis(const Events::GamepadAxis &event);
|
||||
EventRelay<Events::GamepadButtonDown> m_EGamepadButtonDown;
|
||||
bool OnGamepadButtonDown(const Events::GamepadButtonDown &event);
|
||||
EventRelay<Events::GamepadButtonUp> m_EGamepadButtonUp;
|
||||
bool OnGamepadButtonUp(const Events::GamepadButtonUp &event);
|
||||
// Input binding events
|
||||
EventRelay<Events::BindKey> m_EBindKey;
|
||||
bool OnBindKey(const Events::BindKey &event);
|
||||
EventRelay<Events::BindMouseButton> m_EBindMouseButton;
|
||||
bool OnBindMouseButton(const Events::BindMouseButton &event);
|
||||
EventRelay<Events::BindGamepadAxis> m_EBindGamepadAxis;
|
||||
bool OnBindGamepadAxis(const Events::BindGamepadAxis &event);
|
||||
EventRelay<Events::BindGamepadButton> 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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "ParticleSystem.h"
|
||||
|
||||
|
||||
#include "World.h"
|
||||
|
||||
void Systems::ParticleSystem::Initialize()
|
||||
{
|
||||
m_TransformSystem = m_World->GetSystem<Systems::TransformSystem>("TransformSystem");
|
||||
}
|
||||
|
||||
void Systems::ParticleSystem::Update(double dt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Systems::ParticleSystem::UpdateEntity(double dt, EntityID entity, EntityID parent)
|
||||
{
|
||||
auto transformComponent = m_World->GetComponent<Components::Transform>(entity, "Transform");
|
||||
if(!transformComponent)
|
||||
return;
|
||||
|
||||
auto emitterComponent = m_World->GetComponent<Components::ParticleEmitter>(entity, "ParticleEmitter");
|
||||
if(emitterComponent)
|
||||
{
|
||||
emitterComponent->TimeSinceLastSpawn += dt;
|
||||
auto emitterTransformComponent = m_World->GetComponent<Components::Transform>(entity, "Transform");
|
||||
if(emitterComponent->TimeSinceLastSpawn > emitterComponent->SpawnFrequency)
|
||||
{
|
||||
SpawnParticles(entity);
|
||||
emitterComponent->TimeSinceLastSpawn = 0;
|
||||
}
|
||||
|
||||
std::list<ParticleData>::iterator it;
|
||||
for(it = m_ParticleEmitter[entity].begin(); it != m_ParticleEmitter[entity].end();)
|
||||
{
|
||||
EntityID particleID = (it)->ParticleID;
|
||||
auto transformComponent = m_World->GetComponent<Components::Transform>(particleID, "Transform");
|
||||
auto particleComponent = m_World->GetComponent<Components::Particle>(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<Components::ParticleEmitter>(emitterID, "ParticleEmitter");
|
||||
auto emitterTransform = m_World->GetComponent<Components::Transform>(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<Components::Transform>(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<Components::Particle>(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<glm::vec3> 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<Color> 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<float> spectrum, float &alpha)
|
||||
{
|
||||
float dAlpha = glm::abs(spectrum[0] - spectrum[1]);
|
||||
if(spectrum[0] > spectrum[1])
|
||||
dAlpha *= -1;
|
||||
alpha = spectrum[0] + dAlpha * timeProgress;
|
||||
}
|
||||
@@ -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 <GLFW/glfw3.h>
|
||||
|
||||
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<float> spectrum, glm::vec3 &scale);
|
||||
void VectorInterpolation(double timeProgress, std::vector<glm::vec3> spectrum, glm::vec3 &velocity);
|
||||
//void ColorInterpolation(double timeProgress, std::vector<Color> spectrum, Color &color);
|
||||
void ScalarInterpolation(double timeProgress, std::vector<float> spectrum, float &alpha);
|
||||
void Billboard();
|
||||
std::map<EntityID, std::list<ParticleData>> m_ParticleEmitter;
|
||||
std::map<EntityID, double> m_TimeSinceLastSpawn;
|
||||
std::shared_ptr<Systems::TransformSystem> m_TransformSystem;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // !ParticleSystem_h__
|
||||
+399
-234
@@ -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<Systems::TransformSystem>("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<float>(spinAngle, glm::vec3(1, 0, 0));
|
||||
glm::quat orientation = ConvertRotation(steeringOrientation) * glm::angleAxis<float>(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<Components::Transform>(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<Components::Vehicle>(entity, "Vehicle");
|
||||
auto inputComponent = m_World->GetComponent<Components::Input>(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<Components::Wheel>(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<Components::SphereShape>(entity, "SphereShape");
|
||||
auto boxComponent = m_World->GetComponent<Components::BoxShape>(entity, "BoxShape");
|
||||
auto meshShapeComponent = m_World->GetComponent<Components::MeshShape >(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<Components::Physics>(entity, "Physics");
|
||||
if (!physicsComponent)
|
||||
return;
|
||||
|
||||
auto sphereComponent = m_World->GetComponent<Components::Sphere >(entity, "Sphere");
|
||||
auto boxComponent = m_World->GetComponent<Components::Box >(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<Components::Vehicle >(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<hkpShape*> 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<Systems::TransformSystem>("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<Components::Vehicle >(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<Components::Transform>(entity, "Transform");
|
||||
if (!transformComponent)
|
||||
return;
|
||||
|
||||
auto physicsComponent = m_World->GetComponent<Components::Physics>(entity, "Physics");
|
||||
if (!physicsComponent)
|
||||
return;
|
||||
|
||||
auto sphereComponent = m_World->GetComponent<Components::Sphere >(entity, "Sphere");
|
||||
auto boxComponent = m_World->GetComponent<Components::Box >(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<Components::Transform>(shapeData.Entity, "Transform");
|
||||
|
||||
auto vehicleComponent = m_World->GetComponent<Components::Vehicle >(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<Systems::TransformSystem>("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<hkReal>* vertices = new std::vector<hkReal>;
|
||||
std::vector<hkUint16>* vertexIndices = new std::vector<hkUint16>;
|
||||
auto meshShape = m_World->GetResourceManager()->Load<OBJ>("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<hkProcessContext*> 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<Components::Vehicle>(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;
|
||||
}
|
||||
|
||||
@@ -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 <Common/Base/hkBase.h>
|
||||
@@ -34,6 +42,21 @@
|
||||
#include <Common/Visualize/hkVisualDebugger.h>
|
||||
#include <Physics2012/Utilities/VisualDebugger/hkpPhysicsContext.h>
|
||||
|
||||
#include <Physics2012/Collide/Shape/Compound/Collection/ExtendedMeshShape/hkpExtendedMeshShape.h>
|
||||
#include <Physics2012/Collide/Shape/Compound/Tree/Mopp/hkpMoppBvTreeShape.h>
|
||||
#include <Physics2012/Collide/Shape/Compound/Tree/Mopp/hkpMoppUtility.h>
|
||||
|
||||
#include <Common/Base/Thread/JobQueue/hkJobQueue.h>
|
||||
#include <Common/Base/Thread/Job/ThreadPool/Cpu/hkCpuJobThreadPool.h>
|
||||
#include <Common/Base/DebugUtil/MultiThreadCheck/hkMultiThreadCheck.h>
|
||||
#include <Physics/Constraint/Data/Hinge/hkpHingeConstraintData.h>
|
||||
#include <Physics/Constraint/Data/LimitedHinge/hkpLimitedHingeConstraintData.h>
|
||||
|
||||
#include <Physics2012/Collide/Shape/Compound/Collection/List/hkpListShape.h>
|
||||
#include <Physics2012/Internal/Collide/StaticCompound/hkpStaticCompoundShape.h>
|
||||
#include <Physics2012/Collide/Util/ShapeShrinker/hkpShapeShrinker.h>
|
||||
#include <Physics2012/Collide/Shape/Misc/Bv/hkpBvShape.h>
|
||||
|
||||
#include "Physics/VehicleSetup.h"
|
||||
|
||||
#include <unordered_map>
|
||||
@@ -59,6 +82,13 @@ private:
|
||||
double m_Accumulator;
|
||||
hkpWorld* m_PhysicsWorld;
|
||||
|
||||
// Events
|
||||
EventRelay<Events::TankSteer> m_ETankSteer;
|
||||
bool OnTankSteer(const Events::TankSteer &event);
|
||||
|
||||
EventRelay<Events::SetVelocity> 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<EntityID, hkpRigidBody*> m_RigidBodies;
|
||||
|
||||
hkJobThreadPool* m_ThreadPool;
|
||||
hkJobQueue* m_JobQueue;
|
||||
int m_TotalNumThreadsUsed;
|
||||
hkpPhysicsContext* m_Context;
|
||||
|
||||
std::unordered_map<EntityID, hkpVehicleInstance*> m_Vehicles;
|
||||
std::vector<EntityID> 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<EntityID, std::list<ShapeArrayData>> m_Shapes;
|
||||
std::unordered_map<EntityID, hkpListShape*> m_ListShapes;
|
||||
|
||||
|
||||
|
||||
struct ExtendedShapeData
|
||||
{
|
||||
hkpExtendedMeshShape* ExtendedMeshShape;
|
||||
std::vector<hkReal>* Vertices;
|
||||
std::vector<hkUint16>* VertexIndices;
|
||||
hkpMoppCode* Code;
|
||||
hkpMoppBvTreeShape* MoppShape;
|
||||
};
|
||||
std::unordered_map<EntityID, ExtendedShapeData > m_ExtendedMeshShapes;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -23,10 +23,11 @@ void Systems::RenderSystem::UpdateEntity(double dt, EntityID entity, EntityID pa
|
||||
auto model = m_World->GetResourceManager()->Load<Model>("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<Components::Camera>(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<Components::Sprite>(entity, "Sprite");
|
||||
if(spriteComponent != nullptr)
|
||||
{
|
||||
//TEMP
|
||||
Texture* texture = m_World->GetResourceManager()->Load<Texture>("Texture", spriteComponent->SpriteFile);
|
||||
//glBindTexture(GL_TEXTURE_2D, texture);
|
||||
auto transform = m_World->GetComponent<Components::Transform>(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<Systems::TransformSystem>("TransformSystem");
|
||||
|
||||
m_Renderer->SetSphereModel(m_World->GetResourceManager()->Load<Model>("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>("OBJ", resourceName)); });
|
||||
rm->RegisterType("OBJ", [](std::string resourceName) { return new OBJ(resourceName); });
|
||||
rm->RegisterType("Texture", [](std::string resourceName) { return new Texture(resourceName); });
|
||||
}
|
||||
|
||||
|
||||
@@ -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<TankSteeringInputController>(new TankSteeringInputController(EventBroker));
|
||||
m_TowerInputController = std::unique_ptr<TowerSteeringInputController>(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<Components::TankSteering>(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<Components::TowerSteering>(entity, "TowerSteering");
|
||||
if(towerSteeringComponent)
|
||||
{
|
||||
auto transformComponent = m_World->GetComponent<Components::Transform>(entity, "Transform");
|
||||
glm::quat orientation = glm::angleAxis(towerSteeringComponent->TurnSpeed * m_TowerInputController->TowerDirection * (float)dt, towerSteeringComponent->Axis);
|
||||
transformComponent->Orientation *= orientation;
|
||||
}
|
||||
|
||||
auto barrelSteeringComponent = m_World->GetComponent<Components::BarrelSteering>(entity, "BarrelSteering");
|
||||
if(barrelSteeringComponent)
|
||||
{
|
||||
auto transformComponent = m_World->GetComponent<Components::Transform>(entity, "Transform");
|
||||
auto absoluteTransform = m_World->GetSystem<Systems::TransformSystem>("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<Systems::TransformSystem>("TransformSystem")->AbsoluteTransform(barrelSteeringComponent->ShotTemplate);
|
||||
auto cloneTransform = m_World->GetComponent<Components::Transform>(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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
#include <array>
|
||||
|
||||
#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<TankSteeringInputController> m_TankInputController;
|
||||
class TowerSteeringInputController;
|
||||
std::unique_ptr<TowerSteeringInputController> m_TowerInputController;
|
||||
|
||||
std::map<EntityID, double> 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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -24,10 +24,10 @@ glm::vec3 Systems::TransformSystem::AbsolutePosition(EntityID entity)
|
||||
//absPosition += transform->Position;
|
||||
entity = m_World->GetEntityParent(entity);
|
||||
auto transform2 = m_World->GetComponent<Components::Transform>(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<Components::Transform>(entity, "Transform");
|
||||
entity = m_World->GetEntityParent(entity);
|
||||
auto transform2 = m_World->GetComponent<Components::Transform>(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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user