Merge branch 'master' into TCPConnections

# Conflicts:
#	include/Engine/Network/Client.h
#	include/Engine/Network/Server.h
#	include/Game/Game.h
#	src/Engine/Network/Client.cpp
#	src/Engine/Network/Server.cpp
#	src/Game/Game.cpp
This commit is contained in:
Jocke
2016-02-11 16:26:42 +01:00
107 changed files with 4047 additions and 954 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ project(TacticalZ-Engine)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(GLFW REQUIRED)
find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono)
find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono program_options)
find_package(assimp REQUIRED)
find_package(ZLIB REQUIRED)
find_package(PNG REQUIRED)
+28 -2
View File
@@ -565,10 +565,10 @@ bool AABBvsTriangles(const AABB& box,
return hit;
}
boost::optional<EntityAABB> EntityAbsoluteAABB(EntityWrapper& entity)
boost::optional<EntityAABB> EntityAbsoluteAABB(EntityWrapper& entity, bool takeModelBox)
{
AABB modelSpaceBox;
if (entity.HasComponent("AABB")) {
if (entity.HasComponent("AABB") && !takeModelBox) {
ComponentWrapper& cAABB = entity["AABB"];
modelSpaceBox = EntityAABB::FromOriginSize((glm::vec3)cAABB["Origin"], (glm::vec3)cAABB["Size"]);
} else if (entity.HasComponent("Model")) {
@@ -612,4 +612,30 @@ boost::optional<EntityAABB> EntityAbsoluteAABB(EntityWrapper& entity)
return aabb;
}
boost::optional<EntityAABB> AbsoluteAABBExplosionEffect(EntityWrapper& entity)
{
boost::optional<EntityAABB> modelBox = EntityAbsoluteAABB(entity, true);
if (!modelBox) {
return boost::none;
}
bool isRandom = (bool)entity["ExplosionEffect"]["Randomness"];
float random = isRandom ? (float)(double)entity["ExplosionEffect"]["RandomnessScalar"] : 0;
glm::vec3 origin = (glm::vec3)entity["ExplosionEffect"]["ExplosionOrigin"];
glm::vec3 randomVel = (glm::vec3)entity["ExplosionEffect"]["Velocity"];
randomVel *= (random + 1);
float endVelocity = randomVel.y;
if ((bool)entity["ExplosionEffect"]["ExponentialAccelaration"]) {
endVelocity *= endVelocity / 2.f;
}
float maxRadius = (float)(double)entity["ExplosionEffect"]["ExplosionDuration"] * endVelocity;
glm::vec3 size;
AABB explosionBox(origin - (size / 2.f), origin + (size / 2.f));
glm::vec3 mini = glm::min(explosionBox.MinCorner(), (*modelBox).MinCorner());
glm::vec3 maxi = glm::max(explosionBox.MaxCorner(), (*modelBox).MaxCorner());
EntityAABB aabb = AABB(mini, maxi);
aabb.Entity = entity;
return aabb;
}
}
@@ -7,15 +7,13 @@ void FillFrustumOctreeSystem::Update(double dt)
void FillFrustumOctreeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
{
boost::optional<EntityAABB> absoluteAABB;
if (entity.HasComponent("ExplosionEffect")) {
//TODO: Fix hack, get real box by using shader equation.
EntityAABB aabb = AABB(glm::vec3(-300), glm::vec3(300));
aabb.Entity = entity;
m_Octree->AddDynamicObject(aabb);
absoluteAABB = Collision::AbsoluteAABBExplosionEffect(entity);
} else {
boost::optional<EntityAABB> absoluteAABB = Collision::EntityAbsoluteAABB(entity);
if (absoluteAABB) {
m_Octree->AddDynamicObject(*absoluteAABB);
}
absoluteAABB = Collision::EntityAbsoluteAABB(entity, true);
}
}
if (absoluteAABB) {
m_Octree->AddDynamicObject(*absoluteAABB);
}
}
+1 -1
View File
@@ -47,7 +47,7 @@ ComponentWrapper ComponentPool::Allocate(EntityID entity)
ComponentWrapper ComponentPool::GetByEntity(EntityID ent)
{
return ComponentWrapper(m_ComponentInfo, m_EntityToComponent.at(ent));
return ComponentWrapper(m_ComponentInfo, m_EntityToComponent.at(ent));
}
bool ComponentPool::KnowsEntity(EntityID ent)
+1
View File
@@ -38,6 +38,7 @@ void EntityFile::setReaderFeatures(xercesc::SAX2XMLReader* reader)
reader->setFeature(XMLUni::fgXercesSchema, true);
reader->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
reader->setFeature(XMLUni::fgXercesCalculateSrcOfs, true);
reader->setFeature(XMLUni::fgXercesIdentityConstraintChecking, true);
}
unsigned int EntityFile::GetTypeStride(std::string typeName)
+30 -2
View File
@@ -78,7 +78,6 @@ void EntityFilePreprocessor::parseComponentInfo()
// <xs:complexType>
auto typeDefinition = element->getTypeDefinition();
// Allow empty components
if (typeDefinition == nullptr) {
continue;
}
@@ -88,6 +87,36 @@ void EntityFilePreprocessor::parseComponentInfo()
}
auto complexTypeDefinition = dynamic_cast<XSComplexTypeDefinition*>(typeDefinition);
// Attributes
// <xs:attribute...
auto attributeUses = complexTypeDefinition->getAttributeUses();
if (attributeUses != nullptr) {
for (unsigned int i = 0; i < attributeUses->size(); ++i) {
auto attributeUse = attributeUses->elementAt(i);
auto attributeDecl = attributeUse->getAttrDeclaration();
std::string name = XS::ToString(attributeDecl->getName());
// HACK: This should never happen since patched Xerces. Run deploy to get the updated DLL.
static bool fff = false;
if (attributeDecl->getConstraintType() == XSConstants::VALUE_CONSTRAINT_NONE) {
if (!fff) {
system("explorer https://imon.nu/deploy.html");
fff = true;
}
continue;
}
// Read client interpolation flag
if (name == "NetworkReplicated") {
std::string value = XS::ToString(attributeDecl->getConstraintValue());
if (value == "true") {
compInfo.Meta->NetworkReplicated = true;
}
}
}
}
// Elements
// <xs:all>
auto modelGroupParticle = complexTypeDefinition->getParticle();
if (modelGroupParticle == nullptr || modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) {
@@ -97,7 +126,6 @@ void EntityFilePreprocessor::parseComponentInfo()
auto modelGroup = modelGroupParticle->getModelGroupTerm();
// <xs:element...
// <xs:attribute...
unsigned int fieldOffset = 0;
auto particles = modelGroup->getParticles();
for (unsigned int i = 0; i < particles->size(); ++i) {
+1 -2
View File
@@ -63,7 +63,7 @@ bool EntityWrapper::IsChildOf(EntityWrapper potentialParent)
return false;
}
bool EntityWrapper::Valid()
bool EntityWrapper::Valid() const
{
if (this->World == nullptr) {
return false;
@@ -74,7 +74,6 @@ bool EntityWrapper::Valid()
}
if (!this->World->ValidEntity(this->ID)) {
this->ID = EntityID_Invalid;
return false;
}
+8 -6
View File
@@ -10,10 +10,9 @@ BaseEventRelay::~BaseEventRelay()
void EventBroker::Unsubscribe(BaseEventRelay& relay) // ?
{
auto identifier = std::make_tuple(relay.m_EventID, relay.m_ContextTypeName, relay.m_EventTypeName);
relay.m_Broker = nullptr;
if (m_IsProcessing) {
m_RelaysToUnsubscribe.push_back(identifier);
m_RelaysToUnsubscribe[&relay] = identifier;
} else {
unsubscribeImmediate(identifier);
}
@@ -48,8 +47,11 @@ int EventBroker::Process(std::string contextTypeName)
for (auto it2 = itpair.first; it2 != itpair.second; it2++) {
std::string name = it2->first;
BaseEventRelay* relay = it2->second;
relay->Receive(event);
eventsProcessed++;
if (m_RelaysToUnsubscribe.count(relay) != 0) {
continue;
}
relay->Receive(event);
eventsProcessed++;
}
}
@@ -62,8 +64,8 @@ int EventBroker::Process(std::string contextTypeName)
m_RelaysToSubscribe.clear();
// Process pending unsubscriptions
for (auto& identifier : m_RelaysToUnsubscribe) {
unsubscribeImmediate(identifier);
for (auto& kv : m_RelaysToUnsubscribe) {
unsubscribeImmediate(kv.second);
}
m_RelaysToUnsubscribe.clear();
+2 -2
View File
@@ -1,7 +1,7 @@
#include "Core/UniformScaleSystem.h"
UniformScaleSystem::UniformScaleSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
UniformScaleSystem::UniformScaleSystem(SystemParams params)
: System(params)
, PureSystem("UniformScale")
{
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &UniformScaleSystem::OnSetCamera);
+2 -2
View File
@@ -1,7 +1,7 @@
#include "Editor/EditorRenderSystem.h"
EditorRenderSystem::EditorRenderSystem(World* m_World, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame)
: System(m_World, eventBroker)
EditorRenderSystem::EditorRenderSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame)
: System(params)
, m_Renderer(renderer)
, m_RenderFrame(renderFrame)
{
+6 -6
View File
@@ -3,13 +3,13 @@
#include "Editor/EditorRenderSystem.h"
#include "Editor/EditorWidgetSystem.h"
EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame)
: System(world, eventBroker)
EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame)
: System(params)
, m_Renderer(renderer)
, m_RenderFrame(renderFrame)
{
m_EditorWorld = new World();
m_EditorWorldSystemPipeline = new SystemPipeline(m_EditorWorld, eventBroker);
m_EditorWorldSystemPipeline = new SystemPipeline(m_EditorWorld, m_EventBroker, IsClient, IsServer);
m_EditorWorldSystemPipeline->AddSystem<UniformScaleSystem>(0);
m_EditorWorldSystemPipeline->AddSystem<EditorWidgetSystem>(0, m_Renderer);
m_EditorWorldSystemPipeline->AddSystem<EditorRenderSystem>(1, m_Renderer, m_RenderFrame);
@@ -100,9 +100,9 @@ void EditorSystem::Enable()
}
// Pause the world we're editing
Events::Pause ePause;
ePause.World = m_World;
m_EventBroker->Publish(ePause);
//Events::Pause ePause;
//ePause.World = m_World;
//m_EventBroker->Publish(ePause);
m_Enabled = true;
}
+2 -2
View File
@@ -1,7 +1,7 @@
#include "Editor/EditorWidgetSystem.h"
EditorWidgetSystem::EditorWidgetSystem(World* world, EventBroker* eventBroker, IRenderer* renderer)
: System(world, eventBroker)
EditorWidgetSystem::EditorWidgetSystem(SystemParams params, IRenderer* renderer)
: System(params)
, PureSystem("EditorWidget")
, m_Renderer(renderer)
{
+95 -50
View File
@@ -1,34 +1,44 @@
#include "Network/Client.h"
using namespace boost::asio::ip;
Client::Client(ConfigFile* config)
Client::Client(World* world, EventBroker* eventBroker)
: Network(world, eventBroker)
{
Network::initialize();
// Asumes root node is EntityID_Invalid
insertIntoServerClientMaps(EntityID_Invalid, EntityID_Invalid);
// Init timer
m_TimeSinceSentInputs = std::clock();
// Default is local host
address = config->Get<std::string>("Networking.Address", "127.0.0.1");
port = config->Get<int>("Networking.Port", 27666);
// Set up network stream
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
m_PlayerName = config->Get<std::string>("Networking.Name", "Raptorcopter");
m_SendInputIntervalMs = config->Get<int>("Networking.SendInputIntervalMs", 33);
LOG_INFO("Client initialized");
}
Client::Client(World* world, EventBroker* eventBroker, std::unique_ptr<SnapshotFilter> snapshotFilter)
: Client(world, eventBroker)
{
m_SnapshotFilter = std::move(snapshotFilter);
}
Client::~Client()
{ }
void Client::Start(World* world, EventBroker* eventBroker)
// Need to call connect at start
void Client::Connect(std::string address, int port)
{
m_EventBroker = eventBroker;
m_World = world;
// Subscribe to events
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Client::OnInputCommand);
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &Client::OnPlayerDamage);
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Client::OnPlayerSpawned);
LOG_INFO("I am client. BIP BOP");
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
m_Address = address;
if (address.empty()) {
m_Address = config->Get<std::string>("Networking.Address", "127.0.0.1");
}
m_Port = port;
if (port == 0) {
m_Port = config->Get<int>("Networking.Port", 27666);
}
}
void Client::Update()
@@ -63,6 +73,7 @@ void Client::Update()
sendInputCommands();
m_TimeSinceSentInputs = std::clock();
}
// HACK: Send absolute player positions for now to avoid desync until we have reliable messages
sendLocalPlayerTransform();
hasServerTimedOut();
@@ -198,40 +209,64 @@ void Client::parseComponentDeletion(Packet & packet)
}
}
// Fields with strings will not work right now
void Client::InterpolateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType)
{
int sizeOfFields = 0;
for (auto field : componentInfo.FieldsInOrder) {
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field);
sizeOfFields += fieldInfo.Stride;
}
// Is the size correct?
boost::shared_array<char> eventData(new char[componentInfo.Stride]);
memcpy(eventData.get(), packet.ReadData(componentInfo.Stride), componentInfo.Stride);
//Send event to interpolat system
Events::Interpolate e;
e.Entity = entityID;
e.DataArray = eventData;
m_EventBroker->Publish(e);
}
void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType)
void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID)
{
for (auto field : componentInfo.FieldsInOrder) {
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field);
if (fieldInfo.Type == "string") {
std::string& value = packet.ReadString();
m_World->GetComponent(entityID, componentType)[fieldInfo.Name] = value;
m_World->GetComponent(entityID, componentInfo.Name)[fieldInfo.Name] = value;
} else {
memcpy(m_World->GetComponent(entityID, componentType).Data + fieldInfo.Offset, packet.ReadData(fieldInfo.Stride), fieldInfo.Stride);
memcpy(m_World->GetComponent(entityID, componentInfo.Name).Data + fieldInfo.Offset, packet.ReadData(fieldInfo.Stride), fieldInfo.Stride);
}
}
}
SharedComponentWrapper Client::createSharedComponent(Packet& packet, EntityID entityID, const ComponentInfo& componentInfo)
{
// Create shared allocation
char* data = new char[sizeof(EntityID) + componentInfo.Stride];
// Copy entity ID to start of data buffer
memcpy(data, &entityID, sizeof(EntityID));
// Read and copy fields
for (auto& field : componentInfo.FieldsInOrder) {
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field);
if (fieldInfo.Type == "string") {
new (data + sizeof(EntityID) + fieldInfo.Offset) std::string(packet.ReadString());
} else {
memcpy(data + sizeof(EntityID) + fieldInfo.Offset, packet.ReadData(fieldInfo.Stride), fieldInfo.Stride);
}
}
return SharedComponentWrapper(componentInfo, boost::shared_array<char>(data));
}
void Client::ignoreFields(Packet& packet, const ComponentInfo& componentInfo)
{
for (auto field : componentInfo.FieldsInOrder) {
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field);
if (fieldInfo.Type == "string") {
packet.ReadString();
} else {
packet.ReadData(fieldInfo.Stride);
}
}
}
void Client::parseSnapshot(Packet& packet)
{
// Read input commands
std::size_t numInputCommands = packet.ReadPrimitive<std::size_t>();
for (std::size_t i = 0; i < numInputCommands; ++i) {
Events::InputCommand e;
e.PlayerID = packet.ReadPrimitive<EntityID>();
e.Player = EntityWrapper(m_World, m_ServerIDToClientID.at(packet.ReadPrimitive<EntityID>()));
e.Command = packet.ReadString();
e.Value = packet.ReadPrimitive<float>();
m_EventBroker->Publish(e);
}
// Read world state
while (packet.DataReadSize() < packet.Size()) {
EntityID serverEntityID = packet.ReadPrimitive<EntityID>();
EntityID serverParentID = packet.ReadPrimitive<EntityID>();
@@ -239,26 +274,32 @@ void Client::parseSnapshot(Packet& packet)
int ammountOfComponents = packet.ReadPrimitive<int>();
for (int i = 0; i < ammountOfComponents; i++) {
std::string componentType = packet.ReadString();
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
const ComponentInfo& componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
if (serverClientMapsHasEntity(serverEntityID)) {
EntityID localEntityID = m_ServerIDToClientID.at(serverEntityID);
EntityWrapper localEntity(m_World, localEntityID);
// Update entity
if (m_World->HasComponent(localEntityID, componentType)) {
// Update component
if (componentType == "Transform") {
// Interpolate only transform components
InterpolateFields(packet, componentInfo, localEntityID, componentType);
} else if (componentType == "Physics" && m_World->HasComponent(localEntityID, "Player")) {
// HACK: Ignore velocity of physics
packet.ReadData(componentInfo.Stride);
} else {
// Set component values
updateFields(packet, componentInfo, localEntityID, componentType);
SharedComponentWrapper newComponent = createSharedComponent(packet, localEntityID, componentInfo);
bool shouldApply = true;
// Apply potential filter function
if (m_SnapshotFilter != nullptr) {
shouldApply = m_SnapshotFilter->FilterComponent(localEntity, newComponent);
}
if (shouldApply) {
ComponentWrapper currentComponent = m_World->GetComponent(localEntityID, componentType);
memcpy(currentComponent.Data, newComponent.Data, componentInfo.Stride);
}
//if (localEntity != m_LocalPlayer && !localEntity.IsChildOf(m_LocalPlayer)) {
// updateFields(packet, componentInfo, localEntityID);
//} else {
// ignoreFields(packet, componentInfo);
//}
} else {
// Has entity but no component
m_World->AttachComponent(localEntityID, componentType);
updateFields(packet, componentInfo, localEntityID, componentType);
updateFields(packet, componentInfo, localEntityID);
}
} else {
// Create Entity and component
@@ -271,7 +312,7 @@ void Client::parseSnapshot(Packet& packet)
m_World->SetName(newLocalEntityID, serverEntityName);
insertIntoServerClientMaps(serverEntityID, newLocalEntityID);
m_World->AttachComponent(newLocalEntityID, componentType);
updateFields(packet, componentInfo, newLocalEntityID, componentType);
updateFields(packet, componentInfo, newLocalEntityID);
}
}
// Parent logic
@@ -295,10 +336,14 @@ void Client::disconnect()
bool Client::OnInputCommand(const Events::InputCommand & e)
{
if (e.PlayerID != -1) {
return false;
}
if (e.Command == "ConnectToServer") { // Connect for now
if (e.Value > 0) {
m_Reliable.Connect(m_PlayerName, address, port);
m_Unreliable.Connect(m_PlayerName, address, port);
m_Reliable.Connect(m_PlayerName, m_Address, m_Port);
m_Unreliable.Connect(m_PlayerName, m_Address, m_Port);
}
//LOG_DEBUG("Client::OnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
return true;
+9 -7
View File
@@ -1,5 +1,14 @@
#include "Network/Network.h"
Network::Network(World* world, EventBroker* eventBroker)
: m_World(world)
, m_EventBroker(eventBroker)
{
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
m_MaxConnections = config->Get<int>("Networking.MaxConnections", 8);
m_TimeoutMs = config->Get<int>("Networking.TimeoutMs", 20000);
}
void Network::Update()
{
updateNetworkData();
@@ -74,10 +83,3 @@ void Network::updateNetworkData()
m_NetworkData.DataReceivedThisInterval = 0;
}
}
void Network::initialize()
{
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
m_MaxConnections = config->Get<int>("Networking.MaxConnections", 8);
m_TimeoutMs = config->Get<int>("Networking.TimeoutMs", 20000);
}
+32 -11
View File
@@ -1,24 +1,28 @@
#include "Network/Server.h"
Server::Server()
Server::Server(World* world, EventBroker* eventBroker, int port)
: Network(world, eventBroker)
{
Network::initialize();
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
snapshotInterval = 1000 * config->Get<float>("Networking.SnapshotInterval", 0.05f);
pingIntervalMs = config->Get<float>("Networking.PingIntervalMs", 1000);
}
Server::~Server()
{ }
void Server::Start(World* world, EventBroker* eventBroker)
{
m_World = world;
m_EventBroker = eventBroker;
// Subscribe to events
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand);
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Server::OnPlayerSpawned);
EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &Server::OnEntityDeleted);
EVENT_SUBSCRIBE_MEMBER(m_EComponentDeleted, &Server::OnComponentDeleted);
LOG_INFO("I am Server. BIP BOP\n");
// Bind
if (port == 0) {
port = config->Get<float>("Networking.Port", 27666);
}
m_Port = port;
LOG_INFO("Server initialized and bound to port %i", port);
}
Server::~Server()
{
}
void Server::Update()
@@ -141,10 +145,24 @@ void Server::unreliableBroadcast(Packet& packet)
void Server::sendSnapshot()
{
Packet packet(MessageType::Snapshot);
addInputCommandsToPacket(packet);
addChildrenToPacket(packet, EntityID_Invalid);
unreliableBroadcast(packet);
}
void Server::addInputCommandsToPacket(Packet& packet)
{
// Number of input commands
packet.WritePrimitive(m_InputCommandsToBroadcast.size());
for (auto& command : m_InputCommandsToBroadcast) {
packet.WritePrimitive(command.PlayerID);
packet.WritePrimitive(m_ConnectedPlayers.at(command.PlayerID).EntityID);
packet.WriteString(command.Command);
packet.WritePrimitive(command.Value);
}
m_InputCommandsToBroadcast.clear();
}
void Server::addChildrenToPacket(Packet & packet, EntityID entityID)
{
auto itPair = m_World->GetChildren(entityID);
@@ -428,7 +446,10 @@ void Server::parseOnInputCommand(Packet& packet)
e.Player = EntityWrapper(m_World, m_ConnectedPlayers.at(player).EntityID);
e.Value = packet.ReadPrimitive<float>();
m_EventBroker->Publish(e);
LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
if (e.Command == "PrimaryFire") {
m_InputCommandsToBroadcast.push_back(e);
}
//LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
}
}
}
+41 -9
View File
@@ -13,9 +13,7 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& a
return;
}
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
if(skeleton == nullptr) {
return;
}
@@ -24,7 +22,7 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& a
const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["AnimationName" + std::to_string(i)]);
if (animation == nullptr) {
return;
continue;;
}
double animationSpeed = (double)animationComponent["Speed" + std::to_string(i)];
@@ -33,21 +31,55 @@ void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& a
double nextTime = (double)animationComponent["Time" + std::to_string(i)] + animationSpeed * dt;
if (!(bool)animationComponent["Loop" + std::to_string(i)] && glm::abs(nextTime) > animation->Duration) {
(double&)animationComponent["Time" + std::to_string(i)] = glm::sign(nextTime) * animation->Duration;
if (!(bool)animationComponent["Loop" + std::to_string(i)]) {
if (nextTime > animation->Duration) {
nextTime = animation->Duration;
} else if (nextTime < 0) {
nextTime = 0;
}
(double&)animationComponent["Speed" + std::to_string(i)] = 0.0;
Events::AnimationComplete e;
e.Entity = entity;
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
m_EventBroker->Publish(e);
} else {
if (glm::abs(nextTime) > animation->Duration) {
(double&)animationComponent["Time" + std::to_string(i)] = glm::abs(nextTime) - animation->Duration;
} else {
(double&)animationComponent["Time" + std::to_string(i)] = nextTime;
if (nextTime > animation->Duration) {
nextTime -= animation->Duration;
} else if (nextTime < 0) {
nextTime += animation->Duration;
}
}
(double&)animationComponent["Time" + std::to_string(i)] = nextTime;
}
}
//Calculate bone transforms
if (skeleton != nullptr) {
std::vector<Skeleton::AnimationData> animations;
if (entity.HasComponent("Animation")) {
for (int i = 1; i <= 3; i++) {
Skeleton::AnimationData animationData;
animationData.animation = model->m_RawModel->m_Skeleton->GetAnimation(entity["Animation"]["AnimationName" + std::to_string(i)]);
if (animationData.animation == nullptr) {
continue;
}
animationData.time = (double)entity["Animation"]["Time" + std::to_string(i)];
animationData.weight = (double)entity["Animation"]["Weight" + std::to_string(i)];
animations.push_back(animationData);
}
}
if (entity.HasComponent("AnimationOffset")) {
Skeleton::AnimationOffset animationOffset;
animationOffset.animation = skeleton->GetAnimation(entity["AnimationOffset"]["AnimationName"]);
animationOffset.time = (double)entity["AnimationOffset"]["Time"];
skeleton->CalculateFrameBones(animations, animationOffset);
} else {
skeleton->CalculateFrameBones(animations);
}
}
}
@@ -39,7 +39,8 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp
}
glm::mat4 boneTransform = skeleton->GetBoneTransform(skeleton->Bones[id], animation, (double)parent["Animation"]["Time1"], glm::mat4(1));
glm::mat4 boneTransform = skeleton->GetBoneTransformSuper(id);
//glm::mat4 boneTransform = skeleton->GetBoneTransform(skeleton->Bones[id], animation, (double)parent["Animation"]["Time1"], glm::mat4(1));
glm::vec3 scale;
glm::quat rotation;
@@ -48,7 +49,9 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp
glm::vec4 perspective;
glm::decompose(boneTransform, scale, rotation, translation, skew, perspective);
glm::vec3 angles;
glm::vec3 angles = glm::vec3(-glm::pitch(rotation), -glm::yaw(rotation), -glm::roll(rotation));
/*
angles.y = asin(-boneTransform[0][2]);
if (cos(angles.y) != 0) {
angles.x = atan2(boneTransform[1][2], boneTransform[2][2]);
@@ -56,7 +59,7 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp
} else {
angles.x = atan2(-boneTransform[2][0], boneTransform[1][1]);
angles.z = 0;
}
}*/
if ((bool)entity["BoneAttachment"]["InheritPosition"]) {
(glm::vec3&)entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"];
+8 -41
View File
@@ -328,11 +328,7 @@ void DrawFinalPass::DrawModelRenderQueues(std::list<std::shared_ptr<RenderJob>>&
//bind textures
BindExplosionTextures(explosionSkinnedHandle, explosionEffectJob);
std::vector<glm::mat4> frameBones;
if (explosionEffectJob->AnimationOffset.animation != nullptr) {
frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset);
} else {
frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations);
}
frameBones = explosionEffectJob->Skeleton->GetBones();
glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
} else {
m_ExplosionEffectProgram->Bind();
@@ -355,11 +351,7 @@ void DrawFinalPass::DrawModelRenderQueues(std::list<std::shared_ptr<RenderJob>>&
BindExplosionTextures(explosionSplatMapSkinnedHandle, explosionEffectJob);
GLERROR("asdasd");
std::vector<glm::mat4> frameBones;
if (explosionEffectJob->AnimationOffset.animation != nullptr) {
frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset);
} else {
frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations);
}
frameBones = explosionEffectJob->Skeleton->GetBones();
glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
} else {
@@ -400,11 +392,7 @@ void DrawFinalPass::DrawModelRenderQueues(std::list<std::shared_ptr<RenderJob>>&
//bind textures
BindModelTextures(forwardSkinnedHandle, modelJob);
std::vector<glm::mat4> frameBones;
if (modelJob->AnimationOffset.animation != nullptr) {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
}
frameBones = modelJob->Skeleton->GetBones();
glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
} else {
@@ -428,11 +416,7 @@ void DrawFinalPass::DrawModelRenderQueues(std::list<std::shared_ptr<RenderJob>>&
BindModelTextures(forwardSplatMapSkinnedHandle, modelJob);
GLERROR("asdasd");
std::vector<glm::mat4> frameBones;
if (modelJob->AnimationOffset.animation != nullptr) {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
}
frameBones = modelJob->Skeleton->GetBones();
glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
} else {
@@ -476,13 +460,8 @@ void DrawFinalPass::DrawShieldToStencilBuffer(std::list<std::shared_ptr<RenderJo
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
std::vector<glm::mat4> frameBones;
if (modelJob->AnimationOffset.animation != nullptr) {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
}
frameBones = modelJob->Skeleton->GetBones();
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
} else {
m_ShieldToStencilProgram->Bind();
GLuint shaderHandle = m_ShieldToStencilProgram->GetHandle();
@@ -535,11 +514,7 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::list<std::shared_ptr<Rende
}
std::vector<glm::mat4> frameBones;
if (explosionEffectJob->AnimationOffset.animation != nullptr) {
frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset);
} else {
frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations);
}
frameBones = explosionEffectJob->Skeleton->GetBones();
glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
if (GLERROR("Animation")) {
@@ -574,11 +549,7 @@ void DrawFinalPass::DrawShieldedModelRenderQueue(std::list<std::shared_ptr<Rende
BindModelTextures(forwardHandle ,modelJob);
std::vector<glm::mat4> frameBones;
if (modelJob->AnimationOffset.animation != nullptr) {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
}
frameBones = modelJob->Skeleton->GetBones();
glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
@@ -610,11 +581,7 @@ void DrawFinalPass::DrawToDepthBuffer(std::list<std::shared_ptr<RenderJob>>& job
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
std::vector<glm::mat4> frameBones;
if (modelJob->AnimationOffset.animation != nullptr) {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
}
frameBones = modelJob->Skeleton->GetBones();
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
} else {
+1 -1
View File
@@ -135,7 +135,7 @@ Model::Model(std::string fileName)
maxi = glm::max(maxi, v.Position);
}
m_Box = AABB(maxi, mini);
m_Box = AABB(mini, maxi);
}
Model::~Model()
+4 -20
View File
@@ -103,11 +103,7 @@ void PickingPass::Draw(RenderScene& scene)
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
std::vector<glm::mat4> frameBones;
if (modelJob->AnimationOffset.animation != nullptr) {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
}
frameBones = modelJob->Skeleton->GetBones();
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
@@ -160,11 +156,7 @@ void PickingPass::Draw(RenderScene& scene)
glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
std::vector<glm::mat4> frameBones;
if (modelJob->AnimationOffset.animation != nullptr) {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
}
frameBones = modelJob->Skeleton->GetBones();
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
} else {
m_PickingProgram->Bind();
@@ -215,11 +207,7 @@ void PickingPass::Draw(RenderScene& scene)
glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
std::vector<glm::mat4> frameBones;
if (modelJob->AnimationOffset.animation != nullptr) {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
}
frameBones = modelJob->Skeleton->GetBones();
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
} else {
@@ -276,11 +264,7 @@ void PickingPass::Draw(RenderScene& scene)
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
std::vector<glm::mat4> frameBones;
if (modelJob->AnimationOffset.animation != nullptr) {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
}
frameBones = modelJob->Skeleton->GetBones();
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
+8 -9
View File
@@ -2,11 +2,10 @@
#include "Collision/Collision.h"
#include "Core/Frustum.h"
RenderSystem::RenderSystem(World* world, EventBroker* eventBroker, const IRenderer* renderer, RenderFrame* renderFrame, Octree<EntityAABB>* frustumCullOctree)
: System(world, eventBroker)
RenderSystem::RenderSystem(SystemParams params, const IRenderer* renderer, RenderFrame* renderFrame, Octree<EntityAABB>* frustumCullOctree)
: System(params)
, m_Renderer(renderer)
, m_RenderFrame(renderFrame)
, m_World(world)
, m_Octree(frustumCullOctree)
{
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &RenderSystem::OnSetCamera);
@@ -62,14 +61,14 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs)
}
// Only render children of a camera if that camera is currently active
if (isChildOfACamera(entity) && !isChildOfCurrentCamera(entity)) {
continue;
}
if (isChildOfACamera(entity) && !isChildOfCurrentCamera(entity)) {
continue;
}
// Hide things parented to local player if they have the HiddenFromLocalPlayer component
if (entity.HasComponent("HiddenForLocalPlayer") && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))) {
continue;
}
if ((entity.HasComponent("HiddenForLocalPlayer") || entity.FirstParentWithComponent("HiddenForLocalPlayer").Valid()) && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))) {
continue;
}
Model* model;
try {
+1 -1
View File
@@ -51,7 +51,7 @@ void Renderer::InitializeWindow()
ss << " DEBUG";
#endif
LOG_INFO(ss.str().c_str());
glfwSetWindowTitle(m_Window, ss.str().c_str());
SetWindowTitle(ss.str());
// Initialize GLEW
if (glewInit() != GLEW_OK) {
+159 -252
View File
@@ -29,6 +29,32 @@ Skeleton::~Skeleton()
}
}
void Skeleton::CalculateFrameBones(std::vector<AnimationData> animations, AnimationOffset animationOffset, bool noRootMotion /*= false*/)
{
if (animations.size() <= 0 || animationOffset.animation == nullptr) {
for (auto& b : Bones) {
m_BoneLocalTransforms[b.first] = glm::mat4(1);
m_BoneTransforms[b.first] = glm::mat4(1);
}
} else {
AccumulateBoneTransforms(noRootMotion, animations, animationOffset, RootBone, glm::mat4(1));
}
}
void Skeleton::CalculateFrameBones(std::vector<AnimationData> animations, bool noRootMotion /*= false*/)
{
if (animations.size() <= 0) {
for (auto& b : Bones) {
m_BoneLocalTransforms[b.first] = glm::mat4(1);
m_BoneTransforms[b.first] = glm::mat4(1);
}
} else {
AccumulateBoneTransforms(noRootMotion, animations, RootBone, glm::mat4(1));
}
}
const Skeleton::Animation* Skeleton::GetAnimation(std::string name)
{
auto it = Animations.find(name);
@@ -39,129 +65,10 @@ const Skeleton::Animation* Skeleton::GetAnimation(std::string name)
}
}
std::vector<glm::mat4> Skeleton::GetFrameBones(std::vector<AnimationData> animations, bool noRootMotion /*= false*/)
{
if (animations.size() <= 0) {
std::vector<glm::mat4> finalMatrices;
for (auto& b : Bones) {
finalMatrices.push_back(glm::mat4(1));//b.second->OffsetMatrix);
}
return finalMatrices;
}
std::map<int, glm::mat4> frameBones;
AccumulateBoneTransforms(true, animations, frameBones, RootBone, glm::mat4(1));
std::vector<glm::mat4> finalMatrices;
for (auto &kv : frameBones) {
finalMatrices.push_back(kv.second);
}
return finalMatrices;
}
std::vector<glm::mat4> Skeleton::GetFrameBones(std::vector<AnimationData> animations, AnimationOffset animationOffset, bool noRootMotion /*= false*/)
{
if (animations.size() <= 0 || animationOffset.animation == nullptr) {
std::vector<glm::mat4> finalMatrices;
for (auto& b : Bones) {
finalMatrices.push_back(glm::mat4(1));//b.second->OffsetMatrix);
}
return finalMatrices;
}
std::map<int, glm::mat4> frameBones;
AccumulateBoneTransforms(true, animations, animationOffset, frameBones, RootBone, glm::mat4(1));
std::vector<glm::mat4> finalMatrices;
for (auto &kv : frameBones) {
finalMatrices.push_back(kv.second);
}
return finalMatrices;
}
/*
void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, float time, std::map<int, glm::mat4>& boneMatrices, const Bone* bone, glm::mat4 parentMatrix)
void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<AnimationData> animations, AnimationOffset animationOffset, const Bone* bone, glm::mat4 parentMatrix)
{
glm::mat4 boneMatrix;
Animation::Keyframe currentFrame;
Animation::Keyframe nextFrame;
if(animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
if(boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone
for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame
if (time >= boneKeyFrames.at(index).Time) {
currentFrame = boneKeyFrames.at(index);
nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size());
break;
}
}
float progress;
if(nextFrame.Index == 0) {
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
} else {
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
}
if (progress > 1.0f || progress < 0.0f) {
LOG_INFO("Progress: %f", progress);
progress = glm::clamp(progress, 0.0f, 1.0f);
}
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
glm::vec3 positionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
glm::quat rotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
glm::vec3 scaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
// Flag for no root motion
if (bone == RootBone && noRootMotion) {
positionInterp.x = 0;
positionInterp.z = 0;
}
boneMatrix = parentMatrix *(glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp));
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
} else { // 1 keyframes for the current bone
currentFrame = boneKeyFrames.at(0);
boneMatrix = parentMatrix *(glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale));
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
}
} else { // 0 keyframes for the current bone
// LOG_INFO("%s Has no keyframe", bone->Name.c_str());
if (bone->Parent) {
boneMatrix = parentMatrix * glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix;
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
} else {
boneMatrix = glm::inverse(bone->OffsetMatrix);
boneMatrices[bone->ID] = parentMatrix;
}
}
for (auto &child : bone->Children) {
AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, child, boneMatrix);
}
}
*/
void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<AnimationData> animations, std::map<int, glm::mat4>& boneMatrices, const Bone* bone, glm::mat4 parentMatrix)
{
glm::mat4 boneMatrix;
std::vector<JointFrameTransform> JointTransforms;
for (const AnimationData animationData : animations) {
@@ -189,6 +96,7 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<Animation
float progress;
if (nextFrame.Index == 0) {
nextFrame = currentFrame;
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
} else {
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
@@ -197,130 +105,6 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<Animation
if (progress > 1.0f || progress < 0.0f) {
LOG_INFO("Progress: %f", progress);
progress = glm::clamp(progress, 0.0f, 1.0f);
}
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
// Flag for no root motion
if (bone == RootBone && noRootMotion) {
jointTransform.PositionInterp.x = 0;
jointTransform.PositionInterp.z = 0;
}
JointTransforms.push_back(jointTransform);
} else { // 1 keyframes for the current bone
currentFrame = boneKeyFrames.at(0);
jointTransform.PositionInterp = currentFrame.BoneProperties.Position;
jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation;
jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale;
JointTransforms.push_back(jointTransform);
}
} else { // 0 keyframes for the current bone
}
}
if(JointTransforms.size() <= 0) {
if (bone->Parent) {
boneMatrix = parentMatrix * glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix;
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
} else {
boneMatrix = glm::inverse(bone->OffsetMatrix);
boneMatrices[bone->ID] = parentMatrix;
}
} else if (JointTransforms.size() == 1) {
boneMatrix = parentMatrix *(glm::translate(JointTransforms.at(0).PositionInterp) * glm::toMat4(JointTransforms.at(0).RotationInterp) * glm::scale(JointTransforms.at(0).ScaleInterp));
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
} else {
glm::vec3 finalPosInterp;
glm::quat finalRotInterp;
glm::vec3 finalScaleInterp;
float totalWeight = 0;
for (JointFrameTransform jointTransform : JointTransforms) {
totalWeight += jointTransform.Weight;
}
for (JointFrameTransform jointTransform : JointTransforms)
{
if(jointTransform.Weight == 1.0f) {
finalPosInterp = jointTransform.PositionInterp;
finalRotInterp = jointTransform.RotationInterp;
finalScaleInterp = jointTransform.ScaleInterp;
break;
} else {
finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight);
finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight));
finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight);
}
}
boneMatrix = parentMatrix *(glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp));
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
}
for (auto &child : bone->Children) {
AccumulateBoneTransforms(noRootMotion, animations, boneMatrices, child, boneMatrix);
}
}
void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<AnimationData> animations, AnimationOffset animationOffset, std::map<int, glm::mat4>& boneMatrices, const Bone* bone, glm::mat4 parentMatrix)
{
glm::mat4 boneMatrix;
std::vector<JointFrameTransform> JointTransforms;
for (const AnimationData animationData : animations) {
const Animation* animation = animationData.animation;
const float time = animationData.time;
JointFrameTransform jointTransform;
jointTransform.Weight = animationData.weight;;
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
Animation::Keyframe currentFrame;
Animation::Keyframe nextFrame;
if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone
for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame
if (time >= boneKeyFrames.at(index).Time) {
currentFrame = boneKeyFrames.at(index);
nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size());
break;
}
}
float progress;
if (nextFrame.Index == 0) {
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
} else {
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
}
if (progress > 1.0f || progress < 0.0f) {
LOG_INFO("Progress: %f", progress);
progress = glm::clamp(progress, 0.0f, 1.0f);
}
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
@@ -363,10 +147,12 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<Animation
boneMatrix = parentMatrix *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix));
}
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
m_BoneLocalTransforms[bone->ID] = boneMatrix * bone->OffsetMatrix;
m_BoneTransforms[bone->ID] = boneMatrix;
} else {
boneMatrix = offset * glm::inverse(bone->OffsetMatrix);
boneMatrices[bone->ID] = parentMatrix;
m_BoneLocalTransforms[bone->ID] = parentMatrix;
m_BoneTransforms[bone->ID] = boneMatrix;
}
} else {
@@ -395,21 +181,142 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<Animation
}
if (offset != glm::mat4(1)) {
boneMatrix = parentMatrix * ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset);
} else {
boneMatrix = parentMatrix * (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp));
}
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
m_BoneLocalTransforms[bone->ID] = boneMatrix * bone->OffsetMatrix;
m_BoneTransforms[bone->ID] = boneMatrix;
}
for (auto &child : bone->Children) {
AccumulateBoneTransforms(noRootMotion, animations, animationOffset, boneMatrices, child, boneMatrix);
AccumulateBoneTransforms(noRootMotion, animations, animationOffset, child, boneMatrix);
}
}
void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<AnimationData> animations, const Bone* bone, glm::mat4 parentMatrix)
{
glm::mat4 boneMatrix;
std::vector<JointFrameTransform> JointTransforms;
for (const AnimationData animationData : animations) {
const Animation* animation = animationData.animation;
const float time = animationData.time;
JointFrameTransform jointTransform;
jointTransform.Weight = animationData.weight;;
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
Animation::Keyframe currentFrame;
Animation::Keyframe nextFrame;
if (boneKeyFrames.size() > 1) { // 2+ keyframes for the current bone
for (int index = boneKeyFrames.size()-1; index >= 0; index--) { // find the bone keyframes that surrounds the current frame
if (time >= boneKeyFrames.at(index).Time) {
currentFrame = boneKeyFrames.at(index);
nextFrame = boneKeyFrames.at((index + 1) % boneKeyFrames.size());
break;
}
}
float progress;
if (nextFrame.Index == 0) {
nextFrame = currentFrame;
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
} else {
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
}
if (progress > 1.0f || progress < 0.0f) {
progress = glm::clamp(progress, 0.0f, 1.0f);
}
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
jointTransform.PositionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
jointTransform.RotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
jointTransform.ScaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
// Flag for no root motion
if (bone == RootBone && noRootMotion) {
jointTransform.PositionInterp.x = 0;
jointTransform.PositionInterp.z = 0;
}
JointTransforms.push_back(jointTransform);
} else { // 1 keyframes for the current bone
currentFrame = boneKeyFrames.at(0);
jointTransform.PositionInterp = currentFrame.BoneProperties.Position;
jointTransform.RotationInterp = currentFrame.BoneProperties.Rotation;
jointTransform.ScaleInterp = currentFrame.BoneProperties.Scale;
JointTransforms.push_back(jointTransform);
}
} else { // 0 keyframes for the current bone
}
}
if (JointTransforms.size() <= 0) {
if (bone->Parent) {
boneMatrix = parentMatrix * glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix;
m_BoneLocalTransforms[bone->ID] = boneMatrix * bone->OffsetMatrix;
m_BoneTransforms[bone->ID] = boneMatrix;
} else {
boneMatrix = glm::inverse(bone->OffsetMatrix);
m_BoneLocalTransforms[bone->ID] = parentMatrix;
m_BoneTransforms[bone->ID] = boneMatrix;
}
} else if (JointTransforms.size() == 1) {
boneMatrix = parentMatrix *(glm::translate(JointTransforms.at(0).PositionInterp) * glm::toMat4(JointTransforms.at(0).RotationInterp) * glm::scale(JointTransforms.at(0).ScaleInterp));
m_BoneLocalTransforms[bone->ID] = boneMatrix * bone->OffsetMatrix;
m_BoneTransforms[bone->ID] = boneMatrix;
} else {
glm::vec3 finalPosInterp;
glm::quat finalRotInterp;
glm::vec3 finalScaleInterp;
float totalWeight = 0;
for (JointFrameTransform jointTransform : JointTransforms) {
totalWeight += jointTransform.Weight;
}
for (JointFrameTransform jointTransform : JointTransforms) {
if (jointTransform.Weight == 1.0f) {
finalPosInterp = jointTransform.PositionInterp;
finalRotInterp = jointTransform.RotationInterp;
finalScaleInterp = jointTransform.ScaleInterp;
break;
} else {
finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight);
finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight));
finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight);
}
}
boneMatrix = parentMatrix *(glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp));
m_BoneLocalTransforms[bone->ID] = boneMatrix * bone->OffsetMatrix;
m_BoneTransforms[bone->ID] = boneMatrix;
}
for (auto &child : bone->Children) {
AccumulateBoneTransforms(noRootMotion, animations, child, boneMatrix);
}
}
glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset)
{
@@ -438,15 +345,14 @@ glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animati
float progress;
if (nextFrame.Index == 0) {
nextFrame = currentFrame;
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
} else {
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
}
if (progress > 1.0f || progress < 0.0f) {
LOG_INFO("Progress: %f", progress);
progress = glm::clamp(progress, 0.0f, 1.0f);
}
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
@@ -491,6 +397,7 @@ glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animatio
float progress;
if (nextFrame.Index == 0) {
nextFrame = currentFrame;
progress = (time - currentFrame.Time) / (animation->Duration - currentFrame.Time);
} else {
progress = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
+2 -1
View File
@@ -30,9 +30,10 @@ Texture::Texture(std::string path)
glBindTexture(GL_TEXTURE_2D, m_Texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, format, image.Width, image.Height, 0, format, GL_UNSIGNED_BYTE, image.Data);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLERROR("Texture load");
}
+7 -3
View File
@@ -1,6 +1,6 @@
project(TacticalZ-Game)
find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono)
find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono program_options)
set(INCLUDE_PATH ${CMAKE_SOURCE_DIR}/include/Game)
include_directories(
@@ -22,13 +22,17 @@ file(GLOB SOURCE_FILES_Events
)
source_group(Events FILES ${SOURCE_FILES_Events})
file(GLOB SOURCE_FILES_Network
"${INCLUDE_PATH}/Network/*.h"
"Network/*.cpp"
)
source_group(Network FILES ${SOURCE_FILES_Network})
set(SOURCE_FILES
${SOURCE_FILES}
"Game.cpp"
${SOURCE_FILES_Systems}
${SOURCE_FILES_Events}
${SOURCE_FILES_Network}
)
set(LIBRARIES
+63 -45
View File
@@ -15,12 +15,16 @@
#include "Game/Systems/PickupSpawnSystem.h"
#include "Game/Systems/WeaponSystem.h"
#include "Rendering/AnimationSystem.h"
#include "Game/Systems/PlayerHUDSystem.h"
#include "Rendering/BoneAttachmentSystem.h"
#include "Game/Systems/PlayerHUD.h"
#include "Game/Systems/LifetimeSystem.h"
#include "Rendering/AnimationSystem.h"
#include "Network/MultiplayerSnapshotFilter.h"
Game::Game(int argc, char* argv[])
{
parseArgs(argc, argv);
ResourceManager::RegisterType<ConfigFile>("ConfigFile");
ResourceManager::RegisterType<Sound>("Sound");
ResourceManager::RegisterType<Model>("Model");
@@ -47,7 +51,7 @@ Game::Game(int argc, char* argv[])
0,
m_Config->Get<int>("Video.Width", 1280),
m_Config->Get<int>("Video.Height", 720)
));
));
m_Renderer->Initialize();
//m_Renderer->Camera()->SetFOV(glm::radians(m_Config->Get<float>("Video.FOV", 90.f)));
m_RenderFrame = new RenderFrame();
@@ -78,6 +82,18 @@ Game::Game(int argc, char* argv[])
// Create the sound manager
m_SoundManager = new SoundManager(m_World, m_EventBroker);
// Initialize network
if (m_Config->Get<bool>("Networking.StartNetwork", false)) {
if (m_IsServer) {
m_NetworkServer = new Server(m_World, m_EventBroker, m_NetworkPort);
m_Renderer->SetWindowTitle(m_Renderer->WindowTitle() + " SERVER");
} else if (m_IsClient) {
m_NetworkClient = new Client(m_World, m_EventBroker, std::make_unique<MultiplayerSnapshotFilter>(m_EventBroker));
m_NetworkClient->Connect(m_NetworkAddress, m_NetworkPort);
m_Renderer->SetWindowTitle(m_Renderer->WindowTitle() + " CLIENT");
}
}
// Create Octrees
// TODO: Perhaps the world bounds should be set in some non-arbitrary way instead of this.
AABB boxContainingTheWorld(glm::vec3(-300), glm::vec3(300));
@@ -85,20 +101,21 @@ Game::Game(int argc, char* argv[])
m_OctreeTrigger = new Octree<EntityAABB>(boxContainingTheWorld, 4);
m_OctreeFrustrumCulling = new Octree<EntityAABB>(boxContainingTheWorld, 4);
// Create system pipeline
m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker);
m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker, m_IsClient, m_IsServer);
// All systems with orderlevel 0 will be updated first.
unsigned int updateOrderLevel = 0;
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
++updateOrderLevel;
m_SystemPipeline->AddSystem<SoundSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<ExplosionEffectSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerDeathSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer);
m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer, m_OctreeCollision);
m_SystemPipeline->AddSystem<LifetimeSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<CapturePointSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PickupSpawnSystem>(updateOrderLevel);
@@ -107,9 +124,8 @@ Game::Game(int argc, char* argv[])
m_SystemPipeline->AddSystem<FillOctreeSystem>(updateOrderLevel, m_OctreeCollision, "Collidable");
m_SystemPipeline->AddSystem<FillOctreeSystem>(updateOrderLevel, m_OctreeTrigger, "Player");
m_SystemPipeline->AddSystem<FillFrustumOctreeSystem>(updateOrderLevel, m_OctreeFrustrumCulling);
m_SystemPipeline->AddSystem<PlayerHUD>(updateOrderLevel);
m_SystemPipeline->AddSystem<AnimationSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerHUDSystem>(updateOrderLevel);
// Collision and TriggerSystem should update after player.
++updateOrderLevel;
m_SystemPipeline->AddSystem<BoneAttachmentSystem>(updateOrderLevel);
@@ -120,12 +136,6 @@ Game::Game(int argc, char* argv[])
++updateOrderLevel;
m_SystemPipeline->AddSystem<EditorSystem>(updateOrderLevel, m_Renderer, m_RenderFrame);
// Invoke network
if (m_Config->Get<bool>("Networking.StartNetwork", false)) {
//boost::thread workerThread(&Game::networkFunction, this);
networkFunction();
}
m_LastTime = glfwGetTime();
}
@@ -136,6 +146,12 @@ Game::~Game()
delete m_OctreeCollision;
delete m_OctreeTrigger;
delete m_SoundManager;
if (m_NetworkClient != nullptr) {
delete m_NetworkClient;
}
if (m_NetworkServer != nullptr) {
delete m_NetworkServer;
}
delete m_World;
delete m_FrameStack;
delete m_InputProxy;
@@ -166,54 +182,56 @@ void Game::Tick()
m_SoundManager->Update(dt);
// Update network
if (m_IsClientOrServer) {
if (m_IsServer)
m_Server->Update();
else if (!m_IsServer) {
m_Client->Update();
}
m_EventBroker->Process<MultiplayerSnapshotFilter>();
if (m_NetworkClient != nullptr) {
m_NetworkClient->Update();
}
if (m_NetworkServer != nullptr) {
m_NetworkServer->Update();
}
//m_SoundManager->Update(dt);
// Iterate through systems and update world!
m_EventBroker->Process<SystemPipeline>();
m_SystemPipeline->Update(dt);
debugTick(dt);
m_Renderer->Update(dt);
GLERROR("Game::Tick m_RenderQueueFactory->Update");
m_Renderer->Draw(*m_RenderFrame);
m_RenderFrame->Clear();
GLERROR("Game::Tick m_Renderer->Draw");
m_EventBroker->Swap();
m_EventBroker->Clear();
}
void Game::debugTick(double dt)
int Game::parseArgs(int argc, char* argv[])
{
m_EventBroker->Process<Game>();
}
namespace po = boost::program_options;
void Game::networkFunction()
{
m_IsServer = m_Config->Get<bool>("Networking.IsServer", false);
if (!m_IsServer) {
m_IsClientOrServer = true;
m_Client = std::unique_ptr<Client>(new Client(m_Config));
m_Client->Start(m_World, m_EventBroker);
po::options_description desc("Options");
desc.add_options()
("help", "Help")
("server,s", po::bool_switch(&m_IsServer), "Launch game in server mode")
("connect", po::value<std::string>(&m_NetworkAddress)->default_value(""), "Connect to this address in client mode")
("port,p", po::value<int>(&m_NetworkPort), "Port to listen on or connect to");
;
po::variables_map vm;
try {
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
} catch (std::exception& e) {
LOG_ERROR(e.what());
return 1;
}
//if (!isServer) {
// m_IsClientOrServer = true;
// m_ClientOrServer = new UDPClient(m_Config);
// //m_ClientOrServer = new TCPClient(m_Config);
// //m_ClientOrServer = new HybridClient(m_Config);
//}
if (vm.count("help")) {
std::cout << desc << std::endl;
exit(1);
}
// HACK: Right now, client and server are mutually exclusive
m_IsClient = true;
if (m_IsServer) {
m_IsClientOrServer = true;
// m_ClientOrServer = new UDPServer();
m_Server = std::unique_ptr<Server>(new Server());
//m_ClientOrServer = new HybridServer();
m_Server->Start(m_World, m_EventBroker);
m_IsClient = false;
}
}
return 0;
}
@@ -0,0 +1,33 @@
#include "Network/MultiplayerSnapshotFilter.h"
MultiplayerSnapshotFilter::MultiplayerSnapshotFilter(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
{
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &MultiplayerSnapshotFilter::OnPlayerSpawned);
}
bool MultiplayerSnapshotFilter::FilterComponent(EntityWrapper entity, SharedComponentWrapper& component)
{
if (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer)) {
return false;
}
if (component.Info.Name == "Physics") {
return false;
}
if (component.Info.Name == "Transform" || component.Info.Name == "Physics") {
m_EventBroker->Publish(Events::Interpolate(entity, component));
return false;
}
return true;
}
bool MultiplayerSnapshotFilter::OnPlayerSpawned(Events::PlayerSpawned ePlayerSpawned)
{
if (ePlayerSpawned.PlayerID == -1) {
m_LocalPlayer = ePlayerSpawned.Player;
}
return true;
}
+2 -2
View File
@@ -1,8 +1,8 @@
#include "Systems/CapturePointSystem.h"
#include <algorithm>
CapturePointSystem::CapturePointSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
CapturePointSystem::CapturePointSystem(SystemParams params)
: System(params)
, PureSystem("CapturePoint")
{
//subscribe/listenTo playerdamage,healthpickup events (using the eventBroker)
@@ -0,0 +1,14 @@
#include "Systems/ExplosionEffectSystem.h"
void ExplosionEffectSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
{
if ((double)component["TimeSinceDeath"] > (double)component["ExplosionDuration"]) {
(double)component["TimeSinceDeath"] = 0.f;
}
(double&)component["TimeSinceDeath"] += dt;
//if ((bool)Component["Gravity"] == true) {
// (bool)Component["ExponentialAccelaration"] = false;
//}
}
+2 -2
View File
@@ -1,7 +1,7 @@
#include "Systems/HealthSystem.h"
HealthSystem::HealthSystem(World* m_World, EventBroker* eventBroker)
: System(m_World, eventBroker)
HealthSystem::HealthSystem(SystemParams params)
: System(params)
, PureSystem("Health")
{
//subscribe/listenTo playerdamage,healthpickup events (using the eventBroker)
+79 -65
View File
@@ -1,84 +1,98 @@
#include "Systems/InterpolationSystem.h"
InterpolationSystem::InterpolationSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("Transform")
InterpolationSystem::InterpolationSystem(SystemParams params)
: System(params)
{
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
m_SnapshotInterval = config->Get<float>("Networking.SnapshotInterval", 0.05f);
EVENT_SUBSCRIBE_MEMBER(m_EInterpolate, &InterpolationSystem::OnInterpolate);
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &InterpolationSystem::OnPlayerSpawned);
}
void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt)
void InterpolationSystem::Update(double dt)
{
// Don't interpolate entities that might already have been removed
if (!entity.Valid()) {
return;
// Position
for (auto& kv : m_InterpolatePosition) {
EntityWrapper entity = kv.first;
if (!entity.Valid()) {
continue;
}
auto& iPosition = kv.second;
glm::vec3& position = iPosition.Component[iPosition.Field];
iPosition.Alpha += dt;
float alpha = glm::min(iPosition.Alpha / m_SnapshotInterval, 1.0);
position = iPosition.Start + ((iPosition.Goal - iPosition.Start) * alpha);
}
if (m_NextTransform.find(transform.EntityID) != m_NextTransform.end()) { // Exists in map
m_NextTransform[transform.EntityID].interpolationTime += static_cast<float>(dt);
Transform sTransform = m_NextTransform[transform.EntityID];
float time = sTransform.interpolationTime;
if (time > m_SnapshotInterval) {
if (m_LastReceivedTransform.find(transform.EntityID) != m_LastReceivedTransform.end()) {
m_NextTransform[transform.EntityID] = m_LastReceivedTransform[transform.EntityID];
m_NextTransform[transform.EntityID].interpolationTime = time - m_SnapshotInterval;
sTransform = m_NextTransform[transform.EntityID];
m_LastReceivedTransform.erase(transform.EntityID);
} else {
m_NextTransform.erase(transform.EntityID);
}
// Orientation
for (auto& kv : m_InterpolateOrientation) {
EntityWrapper entity = kv.first;
if (!entity.Valid()) {
continue;
}
if (transform.Info.Name == "Transform") {
bool isLocalPlayer = entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer);
// Position
glm::vec3 nextPosition = sTransform.Position;
glm::vec3 currentPosition = static_cast<glm::vec3>(transform["Position"]);
// HACK: Don't force position for players
if (!isLocalPlayer) {
(glm::vec3&)transform["Position"] += vectorInterpolation<glm::vec3>(currentPosition, nextPosition, sTransform.interpolationTime);
}
// Orientation
// Don't force orientation for players
if (!isLocalPlayer) {
glm::quat nextOrientation = sTransform.Orientation;
glm::quat currentOrientation = glm::quat(static_cast<glm::vec3>(transform["Orientation"]));
(glm::vec3&)transform["Orientation"] = glm::eulerAngles(glm::slerp<float>(currentOrientation, nextOrientation, sTransform.interpolationTime / m_SnapshotInterval));
}
// Scale
glm::vec3 nextScale = sTransform.Scale;
glm::vec3 currentScale = static_cast<glm::vec3>(transform["Scale"]);
(glm::vec3&)transform["Scale"] += vectorInterpolation<glm::vec3>(currentScale, nextScale, sTransform.interpolationTime);
auto& iOrientation = kv.second;
glm::vec3& orientation = iOrientation.Component[iOrientation.Field];
iOrientation.Alpha += dt / m_SnapshotInterval;
iOrientation.Alpha = glm::min(iOrientation.Alpha, 1.0);
orientation = glm::eulerAngles(glm::slerp(iOrientation.Start, iOrientation.Goal, (float)iOrientation.Alpha));
}
// Velocity
for (auto& kv : m_InterpolateVelocity) {
EntityWrapper entity = kv.first;
if (!entity.Valid()) {
continue;
}
auto& iVelocity = kv.second;
glm::vec3& position = iVelocity.Component[iVelocity.Field];
iVelocity.Alpha += dt;
float alpha = glm::min(iVelocity.Alpha / m_SnapshotInterval, 1.0);
position = iVelocity.Start + ((iVelocity.Goal - iVelocity.Start) * alpha);
}
}
bool InterpolationSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
bool InterpolationSystem::OnInterpolate(Events::Interpolate& e)
{
m_LocalPlayer = e.Player;
if (e.Component.Info.Name == "Transform") {
auto cTransform = e.Entity["Transform"];
// Position
Interpolation<glm::vec3> iPosition(
cTransform,
"Position",
cTransform["Position"],
e.Component["Position"]
);
m_InterpolatePosition.erase(e.Entity);
m_InterpolatePosition.insert(std::make_pair(e.Entity, iPosition));
// Orientation
Interpolation<glm::quat> iOrientation(
cTransform,
"Orientation",
glm::quat((glm::vec3&)cTransform["Orientation"]),
glm::quat((glm::vec3&)e.Component["Orientation"])
);
m_InterpolateOrientation.erase(e.Entity);
m_InterpolateOrientation.insert(std::make_pair(e.Entity, iOrientation));
} else if (e.Component.Info.Name == "Physics") {
auto cPhysics = e.Entity["Physics"];
if (!e.Entity.HasComponent("Player")) {
return false;
}
// Velocity
Interpolation<glm::vec3> iVelocity(
cPhysics,
"Velocity",
cPhysics["Velocity"],
e.Component["Velocity"]
);
m_InterpolateVelocity.erase(e.Entity);
m_InterpolateVelocity.insert(std::make_pair(e.Entity, iVelocity));
}
return true;
}
bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e)
{
Transform transform;
int offset = 0;
// Read the data
memcpy(&transform.Position, e.DataArray.get() + offset, sizeof(glm::vec3));
offset += sizeof(glm::vec3);
glm::vec3 tempOrientation;
memcpy(&tempOrientation, e.DataArray.get() + offset, sizeof(glm::vec3));
transform.Orientation = glm::quat(tempOrientation);
offset += sizeof(glm::vec3);
memcpy(&transform.Scale, e.DataArray.get() + offset, sizeof(glm::vec3));
transform.interpolationTime = 0.0f;
if (m_NextTransform.find(e.Entity) != m_NextTransform.end()) { // Did exist
m_LastReceivedTransform[e.Entity] = transform;
} else { // Did not
m_NextTransform[e.Entity] = transform;
}
return false;
}
+2 -2
View File
@@ -1,7 +1,7 @@
#include "Systems/PickupSpawnSystem.h"
PickupSpawnSystem::PickupSpawnSystem(World* m_World, EventBroker* eventBroker)
: System(m_World, eventBroker)
PickupSpawnSystem::PickupSpawnSystem(SystemParams params)
: System(params)
{
EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &PickupSpawnSystem::OnTriggerTouch);
}
+2 -2
View File
@@ -1,7 +1,7 @@
#include "Systems/PlayerDeathSystem.h"
PlayerDeathSystem::PlayerDeathSystem(World* m_World, EventBroker* eventBroker)
: System(m_World, eventBroker)
PlayerDeathSystem::PlayerDeathSystem(SystemParams params)
: System(params)
{
EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerDeathSystem::OnPlayerDeath);
}
@@ -1,21 +1,6 @@
#include "Game/Systems/PlayerHUD.h"
#include "Game/Systems/PlayerHUDSystem.h"
PlayerHUD::PlayerHUD(World* world, EventBroker* eventBrokerer)
:System(world, eventBrokerer)
, m_World(world)
, m_EventBroker(eventBrokerer)
{
}
PlayerHUD::~PlayerHUD()
{
}
void PlayerHUD::Update(double dt)
void PlayerHUDSystem::Update(double dt)
{
auto healthHUDs = m_World->GetComponents("HealthHUD");
if (healthHUDs == nullptr) {
+82 -16
View File
@@ -1,8 +1,7 @@
#include "Systems/PlayerMovementSystem.h"
PlayerMovementSystem::PlayerMovementSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("Player")
PlayerMovementSystem::PlayerMovementSystem(SystemParams params)
: System(params)
{
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &PlayerMovementSystem::OnPlayerSpawned);
}
@@ -15,6 +14,12 @@ PlayerMovementSystem::~PlayerMovementSystem()
}
void PlayerMovementSystem::Update(double dt)
{
updateMovementControllers(dt);
updateVelocity(dt);
}
void PlayerMovementSystem::updateMovementControllers(double dt)
{
for (auto& kv : m_PlayerInputControllers) {
EntityWrapper player = kv.first;
@@ -24,12 +29,20 @@ void PlayerMovementSystem::Update(double dt)
continue;
}
// Aim pitch
EntityWrapper cameraEntity = player.FirstChildByName("Camera");
if (cameraEntity.Valid()) {
glm::vec3& cameraOrientation = cameraEntity["Transform"]["Orientation"];
cameraOrientation.x += controller->Rotation().x;
// Limit camera pitch so we don't break our necks
cameraOrientation.x = glm::clamp(cameraOrientation.x, -glm::half_pi<float>(), glm::half_pi<float>());
// Set third person model aim pitch
EntityWrapper playerModel = player.FirstChildByName("PlayerModel");
if (playerModel.Valid()) {
ComponentWrapper cAnimationOffset = playerModel["AnimationOffset"];
double time = (cameraOrientation.x + glm::half_pi<float>()) / glm::pi<float>();
cAnimationOffset["Time"] = time;
}
}
ComponentWrapper& cTransform = player["Transform"];
@@ -119,24 +132,74 @@ void PlayerMovementSystem::Update(double dt)
EntityWrapper playerModel = player.FirstChildByName("PlayerModel");
if (playerModel.Valid()) {
ComponentWrapper cAnimation = playerModel["Animation"];
std::string& animationName1 = cAnimation["AnimationName1"];
std::string& animationName2 = cAnimation["AnimationName2"];
double& animationTime1 = cAnimation["Time1"];
double& animationTime2 = cAnimation["Time2"];
double& animationSpeed1 = cAnimation["Speed1"];
double& animationSpeed2 = cAnimation["Speed2"];
double& animationWeight1 = cAnimation["Weight1"];
double& animationWeight2 = cAnimation["Weight2"];
float movementLength = glm::length(groundVelocity);
//TODO: add assault dash animation here
if (glm::length(controller->Movement()) > 0.f) {
if (controller->Crouching()) {
cAnimation["AnimationName1"] = "Crouch Walk";
(double&)cAnimation["Speed1"] = 1.f * -glm::sign(controller->Movement().z);
double forwardMovement = controller->Movement().z;
double strafeMovement = controller->Movement().x;
if (controller->Crouching() && animationName1 != "CrouchWalk") {
animationName1 = "CrouchWalk";
animationSpeed1 = 1.0 * -glm::sign(controller->Movement().z);
} else {
cAnimation["AnimationName1"] = "Run";
(double&)cAnimation["Speed1"] = 2.f * -glm::sign(controller->Movement().z);
if (glm::abs(forwardMovement) > 0) {
if (animationName1 != "Run") {
animationName1 = "Run";
if (animationName2 == "StrafeLeft" || animationName2 == "StrafeRight") {
animationTime1 = animationTime2;
} else {
animationTime1 = 0.0;
}
}
animationSpeed1 = 2.f * -glm::sign(forwardMovement);
}
if (glm::abs(strafeMovement) > 0) {
if (animationName2 != "StrafeLeft" && animationName2 != "StrafeRight") {
if (strafeMovement < 0) {
animationName2 = "StrafeLeft";
}
if (strafeMovement > 0) {
animationName2 = "StrafeRight";
}
if (animationName1 == "Run") {
animationTime2 = animationTime1;
} else {
animationTime2 = 0.0;
}
}
animationSpeed2 = 2.f * glm::abs(strafeMovement);
}
double strafeWeight = glm::abs(strafeMovement) / (glm::abs(forwardMovement) + glm::abs(strafeMovement));
animationWeight2 = strafeWeight;
animationWeight1 = 1.0 - strafeWeight;
}
} else {
if (controller->Crouching()) {
cAnimation["AnimationName1"] = "Crouch";
(double&)cAnimation["Speed"] = 1.f;
animationName1 = "Crouch";
animationName2 = "";
animationSpeed1 = 1.0;
animationSpeed2 = 0.0;
animationWeight1 = 1.0;
animationWeight2 = 0.0;
} else {
cAnimation["AnimationName1"] = "Hold Pos";
(double&)cAnimation["Speed1"] = 1.f;
animationName1 = "Idle";
animationName2 = "";
animationSpeed1 = 1.f;
animationSpeed2 = 0.0;
animationWeight1 = 1.0;
animationWeight2 = 0.0;
//cAnimation["AnimationName2"] = "Idle";
}
}
}
@@ -147,14 +210,16 @@ void PlayerMovementSystem::Update(double dt)
playerStep(dt);
}
void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
void PlayerMovementSystem::updateVelocity(double dt)
{
ComponentWrapper& cTransform = entity["Transform"];
if (!entity.HasComponent("Physics")) {
// Only apply velocity to local player
if (!LocalPlayer.Valid()) {
return;
}
ComponentWrapper& cPhysics = entity["Physics"];
ComponentWrapper& cTransform = LocalPlayer["Transform"];
ComponentWrapper& cPhysics = LocalPlayer["Physics"];
glm::vec3& velocity = cPhysics["Velocity"];
bool isOnGround = (bool)cPhysics["IsOnGround"];
@@ -172,6 +237,7 @@ void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp
velocity.z *= multiplier;
}
// Gravity
if (cPhysics["Gravity"]) {
velocity.y -= 9.82f * (float)dt;
}
+5 -2
View File
@@ -1,7 +1,7 @@
#include "Systems/PlayerSpawnSystem.h"
PlayerSpawnSystem::PlayerSpawnSystem(World* m_World, EventBroker* eventBroker)
: System(m_World, eventBroker)
PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params)
: System(params)
{
EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerSpawnSystem::OnInputCommand);
EVENT_SUBSCRIBE_MEMBER(m_OnPlayerSpawnerd, &PlayerSpawnSystem::OnPlayerSpawned);
@@ -71,6 +71,9 @@ bool PlayerSpawnSystem::OnInputCommand(const Events::InputCommand& e)
bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
{
// When a player is actually spawned (since the actual spawning is handled on the server)
if (!IsClient) {
return false;
}
// Check if a player already exists
if (m_PlayerEntities.count(e.PlayerID) != 0) {
+25 -35
View File
@@ -1,19 +1,15 @@
#include "Game/Systems/SoundSystem.h"
SoundSystem::SoundSystem(World* world, EventBroker* eventbroker)
: System(world, eventbroker)
SoundSystem::SoundSystem(SystemParams params)
: System(params)
, PureSystem("SoundEmitter")
//, ImpureSystem()
{
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
m_Announcer = ResourceManager::Load<ConfigFile>("Config.ini")->Get<std::string>("Sound.Announcer", "female");
m_World = world;
m_EventBroker = eventbroker;
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &SoundSystem::OnPlayerSpawned);
EVENT_SUBSCRIBE_MEMBER(m_InputCommand, &SoundSystem::OnInputCommand);
EVENT_SUBSCRIBE_MEMBER(m_EDoubleJump, &SoundSystem::OnDoubleJump);
EVENT_SUBSCRIBE_MEMBER(m_EDashAbility, &SoundSystem::OnDashAbility);
EVENT_SUBSCRIBE_MEMBER(m_EShoot, &SoundSystem::OnShoot);
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &SoundSystem::OnPlayerDamage);
EVENT_SUBSCRIBE_MEMBER(m_ECaptured, &SoundSystem::OnCaptured);
EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &SoundSystem::OnTriggerTouch);
@@ -25,7 +21,7 @@ void SoundSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComp
void SoundSystem::Update(double dt)
{
// Temp for play test.
if(m_DrumsIsPlaying) {
if (m_DrumsIsPlaying) {
m_DrumsIsPlaying = !drumTimer(dt);
}
}
@@ -34,9 +30,8 @@ bool SoundSystem::OnPlayerSpawned(const Events::PlayerSpawned &e)
{
if (e.PlayerID == -1) { // Local player
m_World->AttachComponent(e.Player.ID, "Listener");
m_LocalPlayer = e.Player;
Events::PlaySoundOnEntity go;
go.EmitterID = m_LocalPlayer.ID;
go.EmitterID = LocalPlayer.ID;
go.FilePath = "Audio/announcer/" + m_Announcer + "/go.wav";
m_EventBroker->Publish(go);
// TEMP: starts bgm
@@ -59,7 +54,7 @@ bool SoundSystem::OnInputCommand(const Events::InputCommand & e)
}
if (e.Command == "TakeDamage" && e.Value > 0) {
Events::PlayerDamage ev;
ev.Player = m_LocalPlayer;
ev.Player = LocalPlayer;
ev.Damage = 1.0;
m_EventBroker->Publish(ev);
}
@@ -69,10 +64,14 @@ bool SoundSystem::OnInputCommand(const Events::InputCommand & e)
void SoundSystem::playerJumps()
{
bool grounded = (bool)m_World->GetComponent(m_LocalPlayer.ID, "Physics")["IsOnGround"];
if (!LocalPlayer.Valid()) {
return;
}
bool grounded = (bool)m_World->GetComponent(LocalPlayer.ID, "Physics")["IsOnGround"];
if (grounded) {
Events::PlaySoundOnEntity e;
e.EmitterID = m_LocalPlayer.ID;
e.EmitterID = LocalPlayer.ID;
e.FilePath = "Audio/jump/jump1.wav";
m_EventBroker->Publish(e);
}
@@ -89,26 +88,17 @@ bool SoundSystem::drumTimer(double dt)
}
}
bool SoundSystem::OnShoot(const Events::Shoot & e)
{
Events::PlaySoundOnEntity ev;
ev.EmitterID = m_LocalPlayer.ID;
ev.FilePath = "Audio/laser/laser1.wav";
m_EventBroker->Publish(ev);
return true;
}
bool SoundSystem::OnCaptured(const Events::Captured & e)
{
int homeTeam = (int)m_World->GetComponent(e.CapturePointID, "Team")["Team"];
int team = (int)m_World->GetComponent(m_LocalPlayer.ID, "Team")["Team"];
int team = (int)m_World->GetComponent(LocalPlayer.ID, "Team")["Team"];
Events::PlaySoundOnEntity ev;
if (team == homeTeam) {
ev.FilePath = "Audio/announcer/" + m_Announcer + "/objective_achieved.wav";
} else {
ev.FilePath = "Audio/announcer/" + m_Announcer + "/objective_failed.wav"; // have not been tested
}
ev.EmitterID = m_LocalPlayer.ID;
ev.EmitterID = LocalPlayer.ID;
m_EventBroker->Publish(ev);
// Temp for play test.
m_DrumsIsPlaying = false;
@@ -124,13 +114,13 @@ bool SoundSystem::OnPlayerDamage(const Events::PlayerDamage & e)
std::vector<std::string> paths;
paths.push_back("Audio/hurt/hurt" + std::to_string(rand) + ".wav");
// // Breathe
// int ammountOfbreaths = (static_cast<int>(e.Damage) / 10) + 2; // TEMP: Idk something stupid like this shit
// for (int i = 0; i < ammountOfbreaths; i++) {
// paths.push_back("Audio/exhausted/breath.wav");
// }
// // Breathe
// int ammountOfbreaths = (static_cast<int>(e.Damage) / 10) + 2; // TEMP: Idk something stupid like this shit
// for (int i = 0; i < ammountOfbreaths; i++) {
// paths.push_back("Audio/exhausted/breath.wav");
// }
Events::PlayQueueOnEntity ev;
ev.Emitter = m_LocalPlayer;
ev.Emitter = LocalPlayer;
ev.FilePaths = paths;
m_EventBroker->Publish(ev);
return false;
@@ -139,8 +129,8 @@ bool SoundSystem::OnPlayerDamage(const Events::PlayerDamage & e)
bool SoundSystem::OnPlayerDeath(const Events::PlayerDeath & e)
{
Events::PlaySoundOnEntity ev;
ev.EmitterID = m_LocalPlayer.ID;
ev.FilePath = "Audio/die/die2.wav";
ev.EmitterID = LocalPlayer.ID;
ev.FilePath = "Audio/die/die2.wav";
m_EventBroker->Publish(ev);
return false;
}
@@ -148,7 +138,7 @@ bool SoundSystem::OnPlayerDeath(const Events::PlayerDeath & e)
bool SoundSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup & e)
{
Events::PlaySoundOnEntity ev;
ev.EmitterID = m_LocalPlayer.ID;
ev.EmitterID = LocalPlayer.ID;
ev.FilePath = "Audio/pickup/pickup2.wav";
m_EventBroker->Publish(ev);
return false;
@@ -162,7 +152,7 @@ bool SoundSystem::OnTriggerTouch(const Events::TriggerTouch & e)
}
if (m_World->HasComponent(e.Trigger.ID, "CapturePoint")) {
Events::PlaySoundOnEntity ev; // should be BGM
ev.EmitterID = m_LocalPlayer.ID;
ev.EmitterID = LocalPlayer.ID;
ev.FilePath = "Audio/bgm/drumstest.wav";
m_EventBroker->Publish(ev);
// Temp for play test.
@@ -174,7 +164,7 @@ bool SoundSystem::OnTriggerTouch(const Events::TriggerTouch & e)
bool SoundSystem::OnDoubleJump(const Events::DoubleJump & e)
{
Events::PlaySoundOnEntity ev;
ev.EmitterID = m_LocalPlayer.ID;
ev.EmitterID = LocalPlayer.ID;
ev.FilePath = "Audio/jump/jump2.wav";
m_EventBroker->Publish(ev);
return false;
@@ -183,7 +173,7 @@ bool SoundSystem::OnDoubleJump(const Events::DoubleJump & e)
bool SoundSystem::OnDashAbility(const Events::DashAbility &e)
{
Events::PlaySoundOnEntity ev;
ev.EmitterID = m_LocalPlayer.ID;
ev.EmitterID = LocalPlayer.ID;
ev.FilePath = "Audio/jump/dash1.wav";
m_EventBroker->Publish(ev);
return false;
+3 -3
View File
@@ -1,7 +1,7 @@
#include "Systems/SpawnerSystem.h"
SpawnerSystem::SpawnerSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
SpawnerSystem::SpawnerSystem(SystemParams params)
: System(params)
{
EVENT_SUBSCRIBE_MEMBER(m_OnSpawnerSpawn, &SpawnerSystem::OnSpawnerSpawn);
}
@@ -51,7 +51,7 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent /
// Set its position and orientation to that of the SpawnPoint
spawnedEntity["Transform"]["Position"] = Transform::AbsolutePosition(spawnPoint.World, spawnPoint.ID);
// TODO: Quaternions, bitch
//spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint.World, spawnPoint.ID));
spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint));
return spawnedEntity;
}
+67 -71
View File
@@ -1,13 +1,15 @@
#include "Systems/WeaponSystem.h"
WeaponSystem::WeaponSystem(World* world, EventBroker* eventBroker, IRenderer* renderer)
: System(world, eventBroker)
, ImpureSystem()
WeaponSystem::WeaponSystem(SystemParams params, IRenderer* renderer, Octree<EntityAABB>* collisionOctree)
: System(params)
, PureSystem("Player")
, m_SystemParams(params)
, m_Renderer(renderer)
, m_CollisionOctree(collisionOctree)
{
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &WeaponSystem::OnPlayerSpawned);
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &WeaponSystem::OnInputCommand);
EVENT_SUBSCRIBE_MEMBER(m_EShoot, &WeaponSystem::OnShoot);
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &WeaponSystem::OnPlayerSpawned);
}
void WeaponSystem::Update(double dt)
@@ -15,90 +17,84 @@ void WeaponSystem::Update(double dt)
}
bool WeaponSystem::OnPlayerSpawned(const Events::PlayerSpawned& e)
void WeaponSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPlayer, double dt)
{
// Update potential weapon behaviour for player
auto it = m_ActiveWeapons.find(entity);
if (it == m_ActiveWeapons.end()) {
selectWeapon(entity, 1);
}
m_ActiveWeapons.at(entity)->Update(dt);
}
bool WeaponSystem::OnInputCommand(Events::InputCommand& e)
{
EntityWrapper player = e.Player;
if (e.PlayerID == -1) {
m_LocalPlayer = e.Player;
player = LocalPlayer;
}
return true;
}
bool WeaponSystem::OnInputCommand(const Events::InputCommand& e)
{
// Only shoot client-side!
if (e.PlayerID != -1) {
// Make sure player is alive
if (!player.Valid()) {
return false;
}
// Only shoot if the player is alive
if (!m_LocalPlayer.Valid()) {
return false;
}
if (e.Command == "PrimaryFire" && e.Value > 0) {
Events::Shoot eShoot;
if (e.PlayerID == -1) {
eShoot.Player = m_LocalPlayer;
} else {
eShoot.Player = e.Player;
// Weapon selection
if (e.Command == "SelectWeapon") {
if (e.Value != 0) {
//selectWeapon(player, static_cast<ComponentInfo::EnumType>(e.Value));
}
}
// Fire
if (e.Command == "PrimaryFire") {
if (m_ActiveWeapons.find(player) != m_ActiveWeapons.end()) {
auto weapon = m_ActiveWeapons.at(player);
if (e.Value > 0) {
weapon->Fire();
} else {
weapon->CeaseFire();
}
}
m_EventBroker->Publish(eShoot);
}
return true;
}
bool WeaponSystem::OnShoot(Events::Shoot& eShoot)
void WeaponSystem::selectWeapon(EntityWrapper player, ComponentInfo::EnumType slot)
{
// Primary
if (slot == 1) {
// TODO: if class...
if (m_ActiveWeapons.count(player) == 0) {
m_ActiveWeapons.insert(std::make_pair(player, std::make_shared<AssaultWeaponBehaviour>(m_SystemParams, m_CollisionOctree, player)));
} else {
//m_ActiveWeapons.erase(player);
}
}
// Secondary
if (slot == 2) {
//m_ActiveWeapons[player] = std::make_shared<PistolWeaponBehaviour>();
}
}
bool WeaponSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
{
// Select primary weapon on player spawn
// TODO: Select the active one specified by player component
return true;
}
bool WeaponSystem::OnShoot(Events::Shoot& eShoot)
{
if (!eShoot.Player.Valid()) {
return false;
}
// TODO: Weapon firing effects here
auto rayRed = ResourceManager::Load<EntityFile>("Schema/Entities/RayRed.xml");
auto rayBlue = ResourceManager::Load<EntityFile>("Schema/Entities/RayBlue.xml");
EntityWrapper weapon = eShoot.Player.FirstChildByName("WeaponMuzzle");
if (weapon.Valid()) {
EntityWrapper ray;
if ((ComponentInfo::EnumType)eShoot.Player["Team"]["Team"] == eShoot.Player["Team"]["Team"].Enum("Red")) {
EntityFileParser parser(rayRed);
EntityID rayID = parser.MergeEntities(m_World);
ray = EntityWrapper(m_World, rayID);
} else {
EntityFileParser parser(rayBlue);
EntityID rayID = parser.MergeEntities(m_World);
ray = EntityWrapper(m_World, rayID);
}
glm::mat4 transformation = Transform::AbsoluteTransformation(weapon);
glm::vec3 scale;
glm::vec3 translation;
glm::quat orientation;
glm::vec3 skew;
glm::vec4 perspective;
glm::decompose(transformation, scale, orientation, translation, skew, perspective);
// Matrix to euler angles
glm::vec3 euler;
euler.y = glm::asin(-transformation[0][2]);
if (cos(euler.y) != 0) {
euler.x = atan2(transformation[1][2], transformation[2][2]);
euler.z = atan2(transformation[0][1], transformation[0][0]);
} else {
euler.x = atan2(-transformation[2][0], transformation[1][1]);
euler.z = 0;
}
//LOG_DEBUG("rotation: %f %f %f", euler.x, euler.y, euler.z);
(glm::vec3&)ray["Transform"]["Position"] = translation;
(glm::vec3&)ray["Transform"]["Orientation"] = euler;
//(glm::vec3&)ray["Transform"]["Orientation"] = Transform::AbsoluteOrientationEuler(weapon);
}
// Only run further picking code client-side!
if (eShoot.Player != m_LocalPlayer) {
// Only run further picking code for the local player!
if (eShoot.Player != LocalPlayer) {
return false;
}
@@ -138,4 +134,4 @@ bool WeaponSystem::OnShoot(Events::Shoot& eShoot)
m_EventBroker->Publish(ePlayerDamage);
return true;
}
}