Merge branch 'master' into Shadows

This commit is contained in:
FakeShemp
2016-03-07 19:46:04 +01:00
159 changed files with 50716 additions and 5946 deletions
+84 -82
View File
@@ -17,105 +17,107 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
EntityAABB& boxA = *boundingBox;
bool everHitTheGround = false;
auto prevPosIt = m_PrevPositions.find(entity);
if (prevPosIt != m_PrevPositions.end()) {
glm::vec3 size = boxA.Size();
float diameter = std::min(size.x, size.z);
glm::vec3 prevOrigin = prevPosIt->second;
glm::vec3 toCurrentPos = boxA.Origin() - prevOrigin;
float rayLength = glm::length(toCurrentPos) + 0.5f*diameter;
//If the entity has moved farther than the size of its box, we need to handle it specially.
if (rayLength > diameter) {
Ray ray(prevOrigin, toCurrentPos);
m_OctreeResult.clear();
m_Octree->ObjectsPossiblyHitByRay(ray, m_OctreeResult);
for (auto& boxB : m_OctreeResult) {
if (boxA.Entity == boxB.Entity) {
continue;
}
bool hit;
float dist;
if (boxB.Entity.HasComponent("Model")) {
RawModel* model;
std::string res = (std::string)boxB.Entity["Model"]["Resource"];
try {
model = ResourceManager::Load<RawModel, true>(res);
} catch (const std::exception&) {
if (entity == LocalPlayer) {
auto prevPosIt = m_PrevPositions.find(entity);
if (prevPosIt != m_PrevPositions.end()) {
glm::vec3 size = boxA.Size();
float diameter = std::min(size.x, size.z);
glm::vec3 prevOrigin = prevPosIt->second;
glm::vec3 toCurrentPos = boxA.Origin() - prevOrigin;
float rayLength = glm::length(toCurrentPos) + 0.5f*diameter;
//If the entity has moved farther than the size of its box, we need to handle it specially.
if (rayLength > diameter) {
Ray ray(prevOrigin, toCurrentPos);
m_OctreeResult.clear();
m_Octree->ObjectsPossiblyHitByRay(ray, m_OctreeResult);
for (auto& boxB : m_OctreeResult) {
if (boxA.Entity == boxB.Entity) {
continue;
}
float u, v;
hit = Collision::RayVsModel(ray, model->Vertices(), model->m_Indices, Transform::ModelMatrix(boxB.Entity), dist, u, v);
} else {
hit = Collision::RayVsAABB(ray, boxB, dist);
}
if (hit && dist < rayLength) {
//Set the entity to where it was colliding, minus the maximum box size.
//TODO: Perhaps this should be done slightly more properly.
glm::vec3 newOriginPos = ray.Origin() + (dist - 0.707107f*diameter) * ray.Direction();
glm::vec3 resolve = newOriginPos - boxA.Origin();
(glm::vec3&)cTransform["Position"] += resolve;
boxA = *Collision::EntityAbsoluteAABB(entity);
if (resolve.y > 0) {
everHitTheGround = true;
(bool)cPhysics["IsOnGround"] = true;
((glm::vec3&)cPhysics["Velocity"]).y = 0.f;
bool hit;
float dist;
if (boxB.Entity.HasComponent("Model")) {
RawModel* model;
std::string res = (std::string)boxB.Entity["Model"]["Resource"];
try {
model = ResourceManager::Load<RawModel, true>(res);
} catch (const std::exception&) {
continue;
}
float u, v;
hit = Collision::RayVsModel(ray, model->Vertices(), model->m_Indices, Transform::ModelMatrix(boxB.Entity), dist, u, v);
} else {
hit = Collision::RayVsAABB(ray, boxB, dist);
}
if (hit && dist < rayLength) {
//Set the entity to where it was colliding, minus the maximum box size.
//TODO: Perhaps this should be done slightly more properly.
glm::vec3 newOriginPos = ray.Origin() + (dist - 0.707107f*diameter) * ray.Direction();
glm::vec3 resolve = newOriginPos - boxA.Origin();
(glm::vec3&)cTransform["Position"] += resolve;
boxA = *Collision::EntityAbsoluteAABB(entity);
if (resolve.y > 0) {
everHitTheGround = true;
(bool)cPhysics["IsOnGround"] = true;
((glm::vec3&)cPhysics["Velocity"]).y = 0.f;
}
break;
}
break;
}
}
}
}
// Collide against octree items
m_OctreeResult.clear();
m_Octree->ObjectsInSameRegion(*boundingBox, m_OctreeResult);
for (auto& boxB : m_OctreeResult) {
glm::vec3 resolutionVector;
if (boxA.Entity == boxB.Entity) {
continue;
}
if (boxB.Entity.HasComponent("Model") && Collision::AABBVsAABB(boxA, boxB)) {
//Here we know boxB is a entity with Collideable, AABB, and Model.
RawModel* model;
try {
model = ResourceManager::Load<RawModel, true>(boxB.Entity["Model"]["Resource"]);
} catch (const std::exception&) {
// Collide against octree items
m_OctreeResult.clear();
m_Octree->ObjectsInSameRegion(*boundingBox, m_OctreeResult);
for (auto& boxB : m_OctreeResult) {
glm::vec3 resolutionVector;
if (boxA.Entity == boxB.Entity) {
continue;
}
glm::mat4 modelMatrix = Transform::ModelMatrix(boxB.Entity);
if (boxB.Entity.HasComponent("Model") && Collision::AABBVsAABB(boxA, boxB)) {
//Here we know boxB is a entity with Collideable, AABB, and Model.
RawModel* model;
try {
model = ResourceManager::Load<RawModel, true>(boxB.Entity["Model"]["Resource"]);
} catch (const std::exception&) {
continue;
}
glm::vec3 inOutVelocity = (glm::vec3)cPhysics["Velocity"];
bool notMovingxz = glm::all(glm::lessThan(glm::abs(glm::vec2(inOutVelocity.x, inOutVelocity.z)), glm::vec2(0.01f))) && prevPosIt != m_PrevPositions.end();
bool isOnGround = (bool)cPhysics["IsOnGround"];
float verticalStepHeight = (float)(double)cPhysics["VerticalStepHeight"];
if (Collision::AABBvsTriangles(boxA, model->Vertices(), model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) {
//Move the position to previous position if it is not moving in the xz-plane, else resolve with the resolution vector.
(glm::vec3&)cTransform["Position"] += notMovingxz ? prevPosIt->second - boxA.Origin() : resolutionVector;
glm::mat4 modelMatrix = Transform::ModelMatrix(boxB.Entity);
glm::vec3 inOutVelocity = (glm::vec3)cPhysics["Velocity"];
bool notMovingxz = glm::all(glm::lessThan(glm::abs(glm::vec2(inOutVelocity.x, inOutVelocity.z)), glm::vec2(0.01f))) && prevPosIt != m_PrevPositions.end();
bool isOnGround = (bool)cPhysics["IsOnGround"];
float verticalStepHeight = (float)(double)cPhysics["VerticalStepHeight"];
if (Collision::AABBvsTriangles(boxA, model->Vertices(), model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) {
//Move the position to previous position if it is not moving in the xz-plane, else resolve with the resolution vector.
(glm::vec3&)cTransform["Position"] += notMovingxz ? prevPosIt->second - boxA.Origin() : resolutionVector;
boxA = *Collision::EntityAbsoluteAABB(entity);
cPhysics["Velocity"] = inOutVelocity;
if (isOnGround) {
everHitTheGround = true;
(bool)cPhysics["IsOnGround"] = true;
}
}
} else if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) {
//Enter here if boxB has no Model.
(glm::vec3&)cTransform["Position"] += resolutionVector;
boxA = *Collision::EntityAbsoluteAABB(entity);
cPhysics["Velocity"] = inOutVelocity;
if (isOnGround) {
if (resolutionVector.y > 0) {
everHitTheGround = true;
(bool)cPhysics["IsOnGround"] = true;
((glm::vec3&)cPhysics["Velocity"]).y = 0.f;
}
}
} else if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) {
//Enter here if boxB has no Model.
(glm::vec3&)cTransform["Position"] += resolutionVector;
boxA = *Collision::EntityAbsoluteAABB(entity);
if (resolutionVector.y > 0) {
everHitTheGround = true;
(bool)cPhysics["IsOnGround"] = true;
((glm::vec3&)cPhysics["Velocity"]).y = 0.f;
}
}
}
//This should apply air friction and such, iff zero models were hit.
if (!everHitTheGround) {
(bool)cPhysics["IsOnGround"] = false;
}
//This should apply air friction and such, iff zero models were hit.
if (!everHitTheGround) {
(bool)cPhysics["IsOnGround"] = false;
}
m_PrevPositions[entity] = boxA.Origin();
m_PrevPositions[entity] = boxA.Origin();
}
}
+37
View File
@@ -34,11 +34,48 @@ EntityWrapper EntityWrapper::Parent()
}
}
EntityWrapper EntityWrapper::FirstParentByName(const std::string& parentEntityName)
{
EntityWrapper entity = *this;
while (entity.Parent().Valid()) {
entity = entity.Parent();
if (entity.Name() == parentEntityName) {
return entity;
}
}
return EntityWrapper::Invalid;
}
EntityWrapper EntityWrapper::FirstChildByName(const std::string& name)
{
return firstChildByNameRecursive(name, this->ID);
}
EntityWrapper EntityWrapper::FirstLevelChildByName(const std::string& name)
{
EntityID parent = this->ID;
if (!this->World->ValidEntity(parent)) {
return EntityWrapper::Invalid;
}
auto itPair = this->World->GetDirectChildren(parent);
if (itPair.first == itPair.second) {
return EntityWrapper::Invalid;
}
for (auto it = itPair.first; it != itPair.second; ++it) {
std::string itName = this->World->GetName(it->second);
if (itName == name) {
return EntityWrapper(this->World, it->second);
} else if (it->second != EntityID_Invalid) {
continue;
}
}
return EntityWrapper::Invalid;
}
EntityWrapper EntityWrapper::FirstParentWithComponent(const std::string& componentType)
{
EntityWrapper entity = *this;
+58 -8
View File
@@ -157,7 +157,7 @@ void EditorGUI::drawEntitiesRecursive(World* world, EntityID parent)
auto entityChildren = world->GetEntityChildren();
auto range = entityChildren.equal_range(parent);
for (auto it = range.first; it != range.second; it++) {
if (EditorGUI::drawEntityNode(EntityWrapper(world, it->second))) {
if (drawEntityNode(EntityWrapper(world, it->second))) {
drawEntitiesRecursive(world, it->second);
ImGui::TreePop();
}
@@ -217,6 +217,7 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity)
ImGui::EndPopup();
}
ImGui::PushID(("EntityNode" + std::to_string(entity.ID)).c_str());
ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once);
if (ImGui::TreeNode(formatEntityName(entity).c_str())) {
// Handle drop events for reparenting
@@ -224,8 +225,10 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity)
entityChangeParent(m_CurrentlyDragging, entity);
m_CurrentlyDragging = EntityWrapper::Invalid;
}
ImGui::PopID();
return true;
} else {
ImGui::PopID();
return false;
}
}
@@ -338,6 +341,15 @@ bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci)
}
}
if (ci.Name == "Spawner") {
if (ImGui::Button("Activate")) {
Events::SpawnerSpawn e;
e.Spawner = entity;
e.Parent = entity;
m_EventBroker->Publish(e);
}
}
return true;
}
@@ -381,14 +393,52 @@ bool EditorGUI::drawComponentField_Vector(ComponentWrapper &c, const ComponentIn
// Limit scale values to a minimum of 0
return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max());
} else if (field.Name == "Orientation") {
// Make orentations have a period of 2*Pi
glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi<float>()));
if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi<float>())) {
val = tempVal;
return true;
} else {
return false;
//glm::vec3 tempVal = val;
glm::vec3 originalVal = val;
ImVec2 cursorPos = ImGui::GetCursorScreenPos();
glm::tvec3<bool> isSnapping(false, false, false);
bool changed = ImGui::DragFloat3("", glm::value_ptr(val), 0.066666f);
if (changed) {
// Make orentations have a period of 2*Pi
val = glm::fmod(val, glm::vec3(glm::two_pi<float>()));
for (int i = 0; i < 3; i++) {
if (val[i] < 0) {
val[i] += glm::two_pi<float>();
}
}
}
// Snap to angle
//float snapRange = glm::pi<float>() / 15.f;
//float snapAngle = glm::quarter_pi<float>();
//glm::vec3 snap = glm::fmod(val, glm::vec3(snapAngle));
//for (int i = 0; i < 3; i++) {
// isSnapping[i] = glm::abs(snap[i] - (snapRange / 2.f)) < snapRange;
//}
//if (changed && ImGui::IsMouseDown(0)) {
// glm::vec3 change = val - originalVal;
// for (int i = 0; i < 3; i++) {
// if (isSnapping[i] && glm::abs(change[i]) < snapRange) {
// val[i] -= snap[i] - snapRange;
// }
// }
//}
// Draw snapping outline
float width = ImGui::CalcItemWidth() / 3.f;;
float spacing = GImGui->Style.ItemInnerSpacing.x;
for (int i = 0; i < 3; i++) {
if (isSnapping[i]) {
ImVec2 pos = cursorPos + ImVec2(i * (width + spacing), 0.f);
ImRect bb(pos - ImVec2(1, 1), pos + ImVec2(width, 17));
auto window = ImGui::GetCurrentWindow();
const ImU32 col = window->Color(ImGuiCol_HeaderActive);
window->DrawList->AddRect(bb.Min, bb.Max, col, 3.f);
}
}
return changed;
} else {
return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
}
+1 -1
View File
@@ -19,7 +19,7 @@ EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame
m_ActualCamera = m_EditorCamera;
m_EditorWorld->AttachComponent(m_EditorCamera.ID, "Transform");
m_EditorWorld->AttachComponent(m_EditorCamera.ID, "Camera");
m_EditorCameraInputController = new EditorCameraInputController<EditorSystem>(m_EventBroker, -1);
m_EditorCameraInputController = new EditorCameraInputController<EditorSystem>(m_EventBroker, -1, EntityWrapper::Invalid);
m_EditorGUI = new EditorGUI(m_World, m_EventBroker);
m_EditorGUI->SetEntitySelectedCallback(std::bind(&EditorSystem::OnEntitySelected, this, std::placeholders::_1));
+29 -8
View File
@@ -1,4 +1,5 @@
#include "GUI/ButtonSystem.h"
#include "Input/EInputCommand.h"
ButtonSystem::ButtonSystem(SystemParams params, IRenderer* renderer)
: System(params)
@@ -37,10 +38,20 @@ bool ButtonSystem::OnMousePress(const Events::MousePress& e)
m_PickEntity = EntityWrapper(m_World, m_PickData.Entity);
//You have clicked on a button entity, send pressed event.
Events::ButtonPressed ePressed;
ePressed.Entity = m_PickEntity;
ePressed.EntityName = m_PickEntity.Name();
m_EventBroker->Publish(ePressed);
if (m_World->HasComponent(m_PickData.Entity, "InputCmdButton")) {
Events::InputCommand eInputCmd;
eInputCmd.PlayerID = LocalPlayer.ID;
eInputCmd.Player = LocalPlayer;
EntityWrapper button = EntityWrapper(m_World, m_PickData.Entity);
eInputCmd.Command = (std::string)button["InputCmdButton"]["Command"];
eInputCmd.Value = (float)button["InputCmdButton"]["PressValue"];
m_EventBroker->Publish(eInputCmd);
} else {
Events::ButtonPressed ePressed;
ePressed.Entity = m_PickEntity;
ePressed.EntityName = m_PickEntity.Name();
m_EventBroker->Publish(ePressed);
}
}
}
}
@@ -55,10 +66,20 @@ bool ButtonSystem::OnMouseRelease(const Events::MouseRelease& e)
if(m_PickData.Entity != EntityID_Invalid && m_PickData.World == m_World) {
EntityWrapper ent = EntityWrapper(m_World, m_PickData.Entity);
Events::ButtonReleased eReleased;
eReleased.EntityName = m_PickEntity.Name();
eReleased.Entity = m_PickEntity;
m_EventBroker->Publish(eReleased);
if (m_World->HasComponent(m_PickData.Entity, "InputCmdButton")) {
Events::InputCommand eInputCmd;
eInputCmd.PlayerID = LocalPlayer.ID;
eInputCmd.Player = LocalPlayer;
EntityWrapper button = EntityWrapper(m_World, m_PickData.Entity);
eInputCmd.Command = (std::string)button["InputCmdButton"]["Command"];
eInputCmd.Value = 0;
m_EventBroker->Publish(eInputCmd);
} else {
Events::ButtonReleased eReleased;
eReleased.EntityName = m_PickEntity.Name();
eReleased.Entity = m_PickEntity;
m_EventBroker->Publish(eReleased);
}
if(m_World->HasComponent(m_PickData.Entity, "Button")) {
if (ent == m_PickEntity) {
+14 -14
View File
@@ -49,16 +49,16 @@ void Client::Connect(std::string address, int port)
void Client::Update()
{
m_EventBroker->Process<Client>();
while (m_Unreliable.IsSocketAvailable()) {
// Packet will get real data in receive
Packet packet(MessageType::Invalid);
m_Unreliable.Receive(packet);
if (packet.GetMessageType() == MessageType::Connect) {
parseUDPConnect(packet);
} else {
parseMessageType(packet);
}
}
//while (m_Unreliable.IsSocketAvailable()) {
// // Packet will get real data in receive
// Packet packet(MessageType::Invalid);
// m_Unreliable.Receive(packet);
// if (packet.GetMessageType() == MessageType::Connect) {
// parseUDPConnect(packet);
// } else {
// parseMessageType(packet);
// }
//}
while (m_Reliable.IsSocketAvailable()) {
// Packet will get real data in receive
Packet packet(MessageType::Invalid);
@@ -177,8 +177,8 @@ void Client::parseTCPConnect(Packet& packet)
Packet UnreliablePacket(MessageType::Connect, m_SendPacketID);
// Add player id and other stuff
packet.WritePrimitive(m_PlayerID);
m_Unreliable.Send(packet);
LOG_INFO("Sent UDP Connect Server");
// m_Unreliable.Send(packet);
// LOG_INFO("Sent UDP Connect Server");
}
void Client::parsePlayerConnected(Packet & packet)
@@ -476,7 +476,7 @@ bool Client::OnInputCommand(const Events::InputCommand & e)
if (e.Command == "ConnectToServer") { // Connect for now
if (e.Value > 0) {
m_Reliable.Connect(m_PlayerName, m_Address, m_Port);
m_Unreliable.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;
@@ -613,7 +613,7 @@ void Client::sendLocalPlayerTransform()
packet.WritePrimitive((int)cAssaultWeapon["Ammo"]);
}
m_Unreliable.Send(packet);
m_Reliable.Send(packet);
}
void Client::identifyPacketLoss()
+10 -4
View File
@@ -49,18 +49,24 @@ void Packet::WriteString(const std::string& str)
// Message, add one extra byte for null terminator
size_t sizeOfString = str.size() + 1;
if (m_Offset + sizeOfString > m_MaxPacketSize) {
//LOG_WARNING("Package::WriteString(): Data size in packet exceeded maximum package size. New size is %i bytes\n", m_MaxPacketSize*2);
if (m_MaxPacketSize >= 32000) {
LOG_WARNING("Package::WriteString(): New size is huge %i bytes\n", m_MaxPacketSize*2);
}
resizeData();
}
memcpy(m_Data + m_Offset, str.data(), sizeOfString * sizeof(char));
m_Offset += sizeOfString * sizeof(char);
memcpy(m_Data + m_Offset, str.data(), str.size() * sizeof(char));
m_Offset += str.size() * sizeof(char);
m_Data[m_Offset] = '\0';
m_Offset += 1;
}
void Packet::WriteData(char * data, int sizeOfData)
{
if (m_Offset + sizeOfData > m_MaxPacketSize) {
//LOG_WARNING("Packet::WriteData(): Data size in packet exceeded maximum packet size. New size is %i bytes\n", m_MaxPacketSize*2);
if (m_MaxPacketSize >= 32000) {
LOG_WARNING("Package::WriteData(): New size is huge %i bytes\n", m_MaxPacketSize*2);
}
while (m_Offset + sizeOfData > m_MaxPacketSize) {
resizeData();
}
+77 -43
View File
@@ -14,6 +14,7 @@ Server::Server(World* world, EventBroker* eventBroker, int port)
EVENT_SUBSCRIBE_MEMBER(m_EComponentDeleted, &Server::OnComponentDeleted);
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &Server::OnPlayerDamage);
EVENT_SUBSCRIBE_MEMBER(m_EAmmoPickup, &Server::OnAmmoPickup);
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDeath, &Server::OnPlayerDeath);
// BindWW
if (port == 0) {
port = config->Get<float>("Networking.Port", 27666);
@@ -46,19 +47,19 @@ void Server::Update()
}
}
PlayerDefinition pd;
while (m_Unreliable.IsSocketAvailable()) {
// Packet will get real data in receive
Packet packet(MessageType::Invalid);
m_Unreliable.Receive(packet, pd);
m_Address = pd.Endpoint.address();
m_Port = pd.Endpoint.port();
if (packet.GetMessageType() == MessageType::Connect) {
parseUDPConnect(packet);
} else {
parseMessageType(packet);
}
}
//PlayerDefinition pd;
//while (m_Unreliable.IsSocketAvailable()) {
// // Packet will get real data in receive
// Packet packet(MessageType::Invalid);
// m_Unreliable.Receive(packet, pd);
// m_Address = pd.Endpoint.address();
// m_Port = pd.Endpoint.port();
// if (packet.GetMessageType() == MessageType::Connect) {
// parseUDPConnect(packet);
// } else {
// parseMessageType(packet);
// }
//}
while (m_ServerlistRequest.IsSocketAvailable()) {
Packet packet(MessageType::Invalid);
@@ -161,7 +162,7 @@ void Server::unreliableBroadcast(Packet& packet)
{
for (auto& kv : m_ConnectedPlayers) {
packet.ChangePacketID(kv.second.PacketID);
m_Unreliable.Send(packet, kv.second);
// m_Unreliable.Send(packet, kv.second);
}
}
@@ -171,7 +172,7 @@ void Server::sendSnapshot()
Packet packet(MessageType::Snapshot);
addInputCommandsToPacket(packet);
addPlayersToPacket(packet, EntityID_Invalid);
unreliableBroadcast(packet);
reliableBroadcast(packet);
}
void Server::addInputCommandsToPacket(Packet& packet)
@@ -319,25 +320,28 @@ void Server::checkForTimeOuts()
}
}
void Server::parseUDPConnect(Packet & packet)
{
// Pop size of message int
packet.ReadPrimitive<int>();
int messageType = packet.ReadPrimitive<int>();
// Read packet ID
m_PreviousPacketID = m_PacketID; // Set previous packet id
m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id
// parse player id and other stuff
PlayerID playerID = packet.ReadPrimitive<int>();
// Do something here?
boost::asio::ip::udp::endpoint endpoint(m_Address, m_Port);
m_ConnectedPlayers.at(playerID).Endpoint = endpoint;
LOG_INFO("parseUDPConnect: Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str());
// Send a message to the player that connected
Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID);
m_Unreliable.Send(connnectPacket);
LOG_INFO("UDP Connect sent to client");
}
//void Server::parseUDPConnect(Packet & packet)
//{
// // Pop size of message int
// packet.ReadPrimitive<int>();
// int messageType = packet.ReadPrimitive<int>();
// // Read packet ID
// m_PreviousPacketID = m_PacketID; // Set previous packet id
// m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id
// // parse player id and other stuff
// PlayerID playerID = packet.ReadPrimitive<int>();
// if (!EntityWrapper(m_World, playerID).Valid()) {
//
// }
// // Do something here?
// boost::asio::ip::udp::endpoint endpoint(m_Address, m_Port);
// m_ConnectedPlayers.at(playerID).Endpoint = endpoint;
// LOG_INFO("parseUDPConnect: Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(), m_ConnectedPlayers.at(playerID).Endpoint.address().to_string().c_str());
// // Send a message to the player that connected
// Packet connnectPacket(MessageType::Connect, m_ConnectedPlayers.at(playerID).PacketID);
// m_Unreliable.Send(connnectPacket);
// LOG_INFO("UDP Connect sent to client");
//}
void Server::parseTCPConnect(Packet & packet)
{
@@ -351,7 +355,7 @@ void Server::parseTCPConnect(Packet & packet)
LOG_INFO("Parsing connections");
// Check if player is already connected
// Ska vara till lagd i TCPServer receive
PlayerID playerID = GetPlayerIDFromEndpoint();
PlayerID playerID = getPlayerIDFromEndpoint();
if (playerID == -1) {
return;
}
@@ -363,6 +367,11 @@ void Server::parseTCPConnect(Packet & packet)
m_ConnectedPlayers.at(playerID).TCPAddress = m_Address;
m_ConnectedPlayers.at(playerID).TCPPort = m_Port;
Events::PlayerConnected e;
e.PlayerID = playerID;
e.PlayerName = m_ConnectedPlayers.at(playerID).Name;
m_EventBroker->Publish(e);
LOG_INFO("parseTCPConnect: Spectator \"%s\" connected on IP: %s", m_ConnectedPlayers.at(playerID).Name.c_str(),
m_ConnectedPlayers.at(playerID).TCPAddress.to_string().c_str());
@@ -526,10 +535,20 @@ bool Server::OnAmmoPickup(const Events::AmmoPickup & e)
return true;
}
bool Server::OnPlayerDeath(const Events::PlayerDeath& e)
{
Events::KillDeath eKD;
eKD.Casualty = getPlayerIDFromEntityID(e.Player.ID);
eKD.Killer = getPlayerIDFromEntityID(e.Killer.ID);
m_EventBroker->Publish(eKD);
return false;
}
void Server::parseClientPing()
{
LOG_INFO("%i: Parsing ping", m_PacketID);
PlayerID player = GetPlayerIDFromEndpoint();
PlayerID player = getPlayerIDFromEndpoint();
if (player == -1) {
return;
}
@@ -567,7 +586,7 @@ void Server::parseOnInputCommand(Packet& packet)
{
PlayerID player = -1;
// Check which player it was who sent the message
player = GetPlayerIDFromEndpoint();
player = getPlayerIDFromEndpoint();
if (player != -1) {
while (packet.DataReadSize() < packet.Size()) {
Events::InputCommand e;
@@ -586,7 +605,7 @@ void Server::parseOnInputCommand(Packet& packet)
void Server::parsePlayerTransform(Packet& packet)
{
PlayerID playerID = GetPlayerIDFromEndpoint();
PlayerID playerID = getPlayerIDFromEndpoint();
if (playerID == -1) {
return;
}
@@ -630,12 +649,17 @@ bool Server::shouldSendToClient(EntityWrapper childEntity)
return true;
}
}
return childEntity.HasComponent("Player") || childEntity.FirstParentWithComponent("Player").Valid()
|| childEntity.HasComponent("CapturePoint") || childEntity.HasComponent("HealthPickup")
|| childEntity.HasComponent("AmmoPickup");
return childEntity.HasComponent("Player")
|| childEntity.FirstParentWithComponent("Player").Valid()
|| childEntity.HasComponent("CapturePoint")
|| childEntity.HasComponent("HealthPickup")
|| childEntity.HasComponent("AmmoPickup")
|| childEntity.HasComponent("ScoreScreen")
|| childEntity.FirstParentWithComponent("ScoreScreen").Valid()
|| childEntity.FirstParentWithComponent("CapturePoint").Valid();
}
PlayerID Server::GetPlayerIDFromEndpoint()
PlayerID Server::getPlayerIDFromEndpoint()
{
// check both tcp and udp connection
for (auto& kv : m_ConnectedPlayers) {
@@ -647,4 +671,14 @@ PlayerID Server::GetPlayerIDFromEndpoint()
}
}
return -1;
}
}
PlayerID Server::getPlayerIDFromEntityID(EntityID entityID)
{
for (auto& kv : m_ConnectedPlayers) {
if (entityID == kv.second.EntityID) {
return kv.first;
}
}
return -1;
}
+13 -7
View File
@@ -74,7 +74,10 @@ size_t TCPClient::readBuffer()
boost::asio::ip::tcp::socket::message_peek, error);
unsigned int sizeOfPacket = 0;
memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int));
if (sizeOfPacket > m_Socket->available()) {
LOG_WARNING("TCPClient::readBuffer(): We haven't got the whole packet yet.");
//return 0;
}
// if the buffer is to small increase the size of it
// TODO if message is huge 1 time the buffer will not decrease.
if (sizeOfPacket > m_BufferSize) {
@@ -82,12 +85,15 @@ size_t TCPClient::readBuffer()
m_ReadBuffer = new char[sizeOfPacket];
m_BufferSize = sizeOfPacket;
}
// Read the rest of the message
size_t bytesReceived = m_Socket->read_some(boost
::asio::buffer((void*)(m_ReadBuffer), sizeOfPacket),
error);
if (error) {
//LOG_ERROR("receive: %s", error.message().c_str());
size_t bytesReceived = 0;
while (sizeOfPacket > bytesReceived) {
// Read the rest of the message
bytesReceived += m_Socket->read_some(boost
::asio::buffer((void*)(m_ReadBuffer), sizeOfPacket - bytesReceived),
error);
if (error) {
//LOG_ERROR("receive: %s", error.message().c_str());
}
}
if (sizeOfPacket > 1000000)
LOG_WARNING("The packets received are bigger than 1MB");
+4 -1
View File
@@ -106,7 +106,10 @@ int TCPServer::readBuffer(PlayerDefinition & playerDefinition)
boost::asio::ip::tcp::socket::message_peek, error);
unsigned int sizeOfPacket = 0;
memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int));
if (sizeOfPacket > playerDefinition.TCPSocket->available()) {
LOG_WARNING("TCPServer::readBuffer(): We haven't got the whole packet yet.");
return 0;
}
// if the buffer is to small increase the size of it
if (sizeOfPacket > m_BufferSize) {
delete[] m_ReadBuffer;
+4 -1
View File
@@ -45,7 +45,10 @@ int UDPClient::readBuffer()
boost::asio::ip::udp::socket::message_peek, error);
int sizeOfPacket = 0;
memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int));
if (sizeOfPacket > m_Socket->available()) {
LOG_WARNING("UDPClient::readBuffer(): We haven't got the whole packet yet.");
//return 0;
}
// if the buffer is to small increase the size of it
if (sizeOfPacket > m_BufferSize) {
delete[] m_ReadBuffer;
+13 -3
View File
@@ -21,33 +21,38 @@ void UDPServer::Send(Packet& packet, PlayerDefinition & playerDefinition)
boost::asio::buffer(packet.Data(), packet.Size()),
playerDefinition.Endpoint,
0);
LOG_INFO("Size of packet is %i", bytesSent);
} catch (const boost::system::system_error& e) {
LOG_INFO(e.what());
// TODO: Clean up invalid endpoints out of m_ConnectedPlayers later
playerDefinition.Endpoint = boost::asio::ip::udp::endpoint();
}
}
// Send back to endpoint of received packet
void UDPServer::Send(Packet & packet)
{
packet.UpdateSize();
m_Socket->send_to(
size_t bytesSent = m_Socket->send_to(
boost::asio::buffer(
packet.Data(),
packet.Size()),
m_ReceiverEndpoint,
0);
LOG_INFO("Size of packet is %i", bytesSent);
}
// Broadcasting respond specific logic
void UDPServer::Send(Packet & packet, boost::asio::ip::udp::endpoint endpoint)
{
packet.UpdateSize();
m_Socket->send_to(
size_t bytesSent = m_Socket->send_to(
boost::asio::buffer(
packet.Data(),
packet.Size()),
endpoint,
0);
LOG_INFO("Size of packet is %i", bytesSent);
}
// Broadcasting
@@ -55,7 +60,7 @@ void UDPServer::Broadcast(Packet & packet, int port)
{
packet.UpdateSize();
m_Socket->set_option(boost::asio::socket_base::broadcast(true));
m_Socket->send_to(
size_t bytesSent = m_Socket->send_to(
boost::asio::buffer(
packet.Data(),
packet.Size()),
@@ -92,6 +97,11 @@ int UDPServer::readBuffer()
unsigned int sizeOfPacket = 0;
memcpy(&sizeOfPacket, m_ReadBuffer, sizeof(int));
if (sizeOfPacket > m_Socket->available()) {
LOG_WARNING("UDPServer::readBuffer(): We haven't got the whole packet yet.");
//return 0;
}
// if the buffer is to small increase the size of it
if (sizeOfPacket > m_BufferSize) {
delete[] m_ReadBuffer;
+191 -40
View File
@@ -1,71 +1,222 @@
#include "Rendering/AnimationSystem.h"
void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt)
AnimationSystem::AnimationSystem(SystemParams params)
: System(params)
{
if(!entity.HasComponent("Model")) {
EVENT_SUBSCRIBE_MEMBER(m_EAutoAnimationBlend, &AnimationSystem::OnAutoAnimationBlend);
}
void AnimationSystem::Update(double dt)
{
UpdateAnimations(dt);
CreateBlendTrees();
UpdateWeights(dt);
for(auto& autoBlendQueue : m_AutoBlendQueues) {
autoBlendQueue.second.UpdateTime(dt);
}
}
void AnimationSystem::CreateBlendTrees()
{
auto modelComponents = m_World->GetComponents("Model");
if (modelComponents == nullptr) {
return;
}
Model* model;
try {
model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]);
} catch (const std::exception&) {
return;
for (auto& modelC : *modelComponents) {
EntityWrapper entity = EntityWrapper(m_World, modelC.EntityID);
Model* model;
try {
model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]);
} catch (const std::exception&) {
continue;;
}
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
if (skeleton == nullptr) {
continue;
}
if (entity.HasComponent("Blend") || entity.HasComponent("BlendOverride") ||
entity.HasComponent("BlendAdditive") || entity.HasComponent("Animation"))
{
std::shared_ptr<BlendTree> blendTree = std::shared_ptr<BlendTree>(new BlendTree(entity, skeleton));
if(blendTree->IsValid()) {
skeleton->BlendTrees[entity] = blendTree;
}
}
}
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
if(skeleton == nullptr) {
}
void AnimationSystem::UpdateAnimations(double dt)
{
auto animationComponents = m_World->GetComponents("Animation");
if(animationComponents == nullptr) {
return;
}
for (int i = 1; i <= 3; i++) {
const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["AnimationName" + std::to_string(i)]);
for (auto& animationC : *animationComponents) {
EntityWrapper entity = EntityWrapper(m_World, animationC.EntityID);
EntityWrapper modelEntity;
if(!entity.HasComponent("Model")) {
modelEntity = entity.FirstParentWithComponent("Model");
} else {
modelEntity = entity;
}
Model* model;
try {
model = ResourceManager::Load<::Model, true>(modelEntity["Model"]["Resource"]);
} catch (const std::exception&) {
return;
}
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
if (skeleton == nullptr) {
return;
}
const Skeleton::Animation* animation = skeleton->GetAnimation(animationC["AnimationName"]);
if (animation == nullptr) {
continue;;
}
double animationSpeed = (double)animationComponent["Speed" + std::to_string(i)];
double animationSpeed = (double)animationC["Speed"];
if (animationSpeed != 0.0) {
double nextTime = (double)animationComponent["Time" + std::to_string(i)] + animationSpeed * dt;
if((bool)animationC["Reverse"]) {
animationSpeed *= -1;
}
if (!(bool)animationComponent["Loop" + std::to_string(i)]) {
if ((bool)animationC["Play"]) {
double nextTime = (double)animationC["Time"] + animationSpeed * dt;
if (!(bool)animationC["Loop"]) {
if (nextTime > animation->Duration) {
nextTime = animation->Duration;
Events::AnimationComplete e;
e.Entity = entity;
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
m_EventBroker->Publish(e);
(bool&)animationC["Play"] = false;
} else if (nextTime < 0) {
Events::AnimationComplete e;
e.Entity = entity;
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
m_EventBroker->Publish(e);
nextTime = 0;
(bool&)animationC["Play"] = false;
}
(double&)animationComponent["Speed" + std::to_string(i)] = 0.0;
} else {
if (nextTime > animation->Duration) {
Events::AnimationComplete e;
e.Entity = entity;
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
m_EventBroker->Publish(e);
nextTime -= animation->Duration;
while (nextTime > animation->Duration) {
nextTime -= animation->Duration;
}
} else if (nextTime < 0) {
Events::AnimationComplete e;
e.Entity = entity;
e.Name = (std::string)animationComponent["AnimationName" + std::to_string(i)];
m_EventBroker->Publish(e);
nextTime += animation->Duration;
while (nextTime < 0) {
nextTime += animation->Duration;
}
}
}
(double&)animationComponent["Time" + std::to_string(i)] = nextTime;
(double&)animationC["Time"] = nextTime;
}
}
}
}
void AnimationSystem::UpdateWeights(double dt)
{
for (auto& autoBlendQueue : m_AutoBlendQueues) {
if(autoBlendQueue.second.HasActiveBlendJob()) {
AutoBlendQueue::AutoBlendJob& blendJob = autoBlendQueue.second.GetActiveBlendJob();
std::shared_ptr<BlendTree> blendTree = autoBlendQueue.second.GetBlendTree();
if (blendTree != nullptr) {
if (blendJob.Duration != 0.0) {
blendJob.BlendInfo.progress = glm::clamp(blendJob.CurrentTime / blendJob.Duration, 0.0, 1.0);
} else {
blendJob.BlendInfo.progress = 1.0;
}
blendJob.BlendInfo = blendTree->AutoBlendStep(blendJob.BlendInfo);
}
}
}
}
bool AnimationSystem::OnAutoAnimationBlend(Events::AutoAnimationBlend& e)
{
if (!e.RootNode.Valid()) {
return false;
}
if (!e.RootNode.HasComponent("Model")) {
return false;
}
Model* model;
try {
model = ResourceManager::Load<::Model, true>((std::string)e.RootNode["Model"]["Resource"]);
} catch (const std::exception&) {
return false;
}
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
if (skeleton == nullptr) {
return false;
}
std::shared_ptr<BlendTree> blendTree;
if (skeleton->BlendTrees.find(e.RootNode) != skeleton->BlendTrees.end()) {
blendTree = skeleton->BlendTrees.at(e.RootNode);
} else {
return false;
}
EntityWrapper subTreeRoot = blendTree->GetSubTreeRoot(e.NodeName);
if (!subTreeRoot.Valid()) {
return false;
}
AutoBlendQueue::AutoBlendJob abj;
abj.AnimationEntity = e.AnimationEntity;
abj.CurrentTime = 0.0;
abj.Delay = e.Delay;
abj.Duration = e.Duration;
abj.RootNode = e.RootNode;
abj.BlendInfo.NodeName = e.NodeName;
abj.BlendInfo.progress = 0.0;
abj.BlendInfo.Start = e.Start;
abj.BlendInfo.SingleBlend = e.SingleLevelBlend;
abj.BlendInfo.Weight = e.Weight;
EntityWrapper nodeEntity = subTreeRoot.FirstChildByName(e.NodeName); // more than one
if (nodeEntity.Valid()) {
if (nodeEntity.HasComponent("Animation")) {
const Skeleton::Animation* animation = skeleton->GetAnimation(nodeEntity["Animation"]["AnimationName"]);
(bool&)nodeEntity["Animation"]["Reverse"] = e.Reverse;
if (e.Restart) {
if (animation != nullptr) {
if (e.Restart) {
if (e.Reverse) {
(double&)nodeEntity["Animation"]["Time"] = animation->Duration;
} else {
(double&)nodeEntity["Animation"]["Time"] = 0.0;
}
}
}
}
}
}
m_AutoBlendQueues[subTreeRoot].Insert(abj);
return true;
}
+195
View File
@@ -0,0 +1,195 @@
#include "Rendering/AutoBlendQueue.h"
void AutoBlendQueue::Insert(AutoBlendJob autoBlendJob)
{
if(!autoBlendJob.RootNode.HasComponent("Model")) {
return;
}
AutoblendNode blendNode;
blendNode.BlendJob = autoBlendJob;
blendNode.StartTime = autoBlendJob.Delay;
blendNode.EndTime = autoBlendJob.Delay + autoBlendJob.Duration;
if (autoBlendJob.AnimationEntity.Valid()) {
if (autoBlendJob.AnimationEntity.HasComponent("Animation")) {
Model* model;
try {
model = ResourceManager::Load<::Model, true>((std::string)autoBlendJob.RootNode["Model"]["Resource"]);
} catch (const std::exception&) {
return;
}
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
if (skeleton == nullptr) {
return;
}
const Skeleton::Animation* animation = skeleton->GetAnimation((std::string)autoBlendJob.AnimationEntity["Animation"]["AnimationName"]);
if (animation == nullptr) {
return;
}
double AnimationDuration = 0.0;
double animationSpeed = (double)autoBlendJob.AnimationEntity["Animation"]["Speed"];
double animationTime = (double)autoBlendJob.AnimationEntity["Animation"]["Time"];
if ((bool)autoBlendJob.AnimationEntity["Animation"]["Reverse"]) {
AnimationDuration = (animation->Duration * animationSpeed) - (animation->Duration - animationTime);
} else {
AnimationDuration = (animation->Duration * animationSpeed) - animationTime;
}
blendNode.StartTime += AnimationDuration;
blendNode.EndTime += AnimationDuration;
if (m_BlendQueue.size() == 0) {
m_BlendQueue.push_back(blendNode);
} else {
for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end(); it++) {
auto next = std::next(it, 1);
if (it->BlendJob.BlendInfo.NodeName == autoBlendJob.BlendInfo.NodeName) {
(*it) = blendNode;
}
if (next != m_BlendQueue.end()) {
if (it->StartTime >= blendNode.StartTime && next->StartTime <= blendNode.StartTime) {
m_BlendQueue.insert(next, blendNode);
return;
}
} else if(it->StartTime > blendNode.StartTime){
m_BlendQueue.push_front(blendNode);
return;
} else if (it->StartTime <= blendNode.StartTime) {
m_BlendQueue.push_back(blendNode);
return;
}
}
}
}
}
m_BlendQueue.clear();
m_BlendQueue.push_back(blendNode);
}
void AutoBlendQueue::UpdateTime(double dt)
{
for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end();) {
if (it->EndTime <= 0) {
it = m_BlendQueue.erase(it);
} else {
it->EndTime -= dt;
it->StartTime -= dt;
it++;
}
}
}
void AutoBlendQueue::PrintQueue()
{
for (auto it = m_BlendQueue.begin(); it != m_BlendQueue.end(); it++) {
LOG_INFO("Start: %f End: %f \t %s", it->StartTime, it->EndTime, it->BlendJob.BlendInfo.NodeName.c_str());
}
}
bool AutoBlendQueue::HasActiveBlendJob()
{
if(m_BlendQueue.empty()) {
return false;
} else {
AutoblendNode blendNode = m_BlendQueue.front();
if (blendNode.StartTime <= 0) {
AutoBlendJob blendJob = blendNode.BlendJob;
if (!blendJob.RootNode.Valid()) {
m_BlendQueue.pop_front();
return false;
}
if (!blendJob.RootNode.HasComponent("Model")) {
m_BlendQueue.pop_front();
return HasActiveBlendJob();
}
Model* model;
try {
model = ResourceManager::Load<::Model, true>(blendJob.RootNode["Model"]["Resource"]);
} catch (const std::exception&) {
m_BlendQueue.pop_front();
return HasActiveBlendJob();
}
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
if (skeleton == nullptr) {
m_BlendQueue.pop_front();
return HasActiveBlendJob();
}
if (skeleton->BlendTrees.find(blendJob.RootNode) != skeleton->BlendTrees.end()) {
return true;
} else {
m_BlendQueue.pop_front();
return HasActiveBlendJob();
}
} else {
return false;
}
}
}
std::shared_ptr<BlendTree> AutoBlendQueue::GetBlendTree()
{
AutoblendNode blendNode = m_BlendQueue.front();
AutoBlendJob blendJob = blendNode.BlendJob;
if (!blendJob.RootNode.Valid()) {
m_BlendQueue.pop_front();
return false;
}
if (!blendJob.RootNode.HasComponent("Model")) {
return nullptr;
}
Model* model;
try {
model = ResourceManager::Load<::Model, true>(blendJob.RootNode["Model"]["Resource"]);
} catch (const std::exception&) {
return nullptr;
}
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
if (skeleton == nullptr) {
return nullptr;
}
if (skeleton->BlendTrees.find(blendJob.RootNode) != skeleton->BlendTrees.end()) {
return skeleton->BlendTrees.at(blendJob.RootNode);
} else {
return nullptr;
}
}
AutoBlendQueue::AutoBlendJob& AutoBlendQueue::GetActiveBlendJob()
{
AutoblendNode& blendNode = m_BlendQueue.front();
blendNode.BlendJob.CurrentTime = -blendNode.StartTime;
return blendNode.BlendJob;
}
+499
View File
@@ -0,0 +1,499 @@
#include "Rendering/BlendTree.h"
BlendTree::BlendTree(EntityWrapper ModelEntity, Skeleton* skeleton)
{
m_Skeleton = skeleton;
if (ModelEntity.HasComponent("Animation")) {
const Skeleton::Animation* animation = skeleton->GetAnimation(ModelEntity["Animation"]["AnimationName"]);
if (animation == nullptr) {
return;
}
m_Root = new Node();
m_Root->Entity = ModelEntity;
m_Root->Name = ModelEntity.Name();
m_Root->Pose = m_Skeleton->GetFrameBones(animation, (double)ModelEntity["Animation"]["Time"], (bool)ModelEntity["Animation"]["Additive"]);
m_Root->Parent = nullptr;
m_Root->Type = NodeType::Animation;
} else if (ModelEntity.HasComponent("Blend")) {
m_Root = new Node();
m_Root->Entity = ModelEntity;
m_Root->Name = ModelEntity.Name();
m_Root->Parent = nullptr;
m_Root->Type = NodeType::Blend;
m_Root->Weight = (double)ModelEntity["Blend"]["Weight"];
m_Root->SubTreeRoot = (bool)ModelEntity["Blend"]["SubTreeRoot"];
(double&)ModelEntity["Blend"]["Weight"] = glm::clamp((double)ModelEntity["Blend"]["Weight"], 0.0, 1.0);
m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["Blend"]["Pose1"], ModelEntity);
m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["Blend"]["Pose2"], ModelEntity);
} else if (ModelEntity.HasComponent("BlendOverride")) {
m_Root = new Node();
m_Root->Entity = ModelEntity;
m_Root->Name = ModelEntity.Name();
m_Root->Parent = nullptr;
m_Root->Type = NodeType::Override;
m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendOverride"]["Master"], ModelEntity);
m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendOverride"]["Slave"], ModelEntity);
} else if (ModelEntity.HasComponent("BlendAdditive")) {
m_Root = new Node();
m_Root->Entity = ModelEntity;
m_Root->Name = ModelEntity.Name();
m_Root->Parent = nullptr;
m_Root->Type = NodeType::Additive;
m_Root->Child[0] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendAdditive"]["Adder"], ModelEntity);
m_Root->Child[1] = FillTreeByName(m_Root, (std::string)ModelEntity["BlendAdditive"]["Receiver"], ModelEntity);
}
m_FinalPose = AccumulateFinalPose();
// PrintTree();
}
BlendTree::~BlendTree()
{
Node* currentNode = m_Root;
if (currentNode != nullptr) {
while (currentNode->Child[0] != nullptr) {
currentNode = currentNode->Child[0];
}
std::list<Node*> m_NodesToRemove;
while (currentNode != nullptr) {
m_NodesToRemove.push_back(currentNode);
currentNode = currentNode->Next();
}
for (auto it = m_NodesToRemove.begin(); it != m_NodesToRemove.end(); it++) {
delete (*it);
}
}
}
glm::mat4 BlendTree::GetBoneTransform(int boneID)
{
if(m_FinalBoneTransforms.find(boneID) != m_FinalBoneTransforms.end()) {
return m_FinalBoneTransforms.at(boneID);
} else {
return glm::mat4(1);
}
}
void BlendTree::PrintTree()
{
Node* currentNode = m_Root;
LOG_INFO("\n\n");
while(currentNode->Child[0] != nullptr) {
currentNode = currentNode->Child[0];
}
while (currentNode != nullptr)
{
LOG_INFO("%s", currentNode->Name.c_str());
currentNode = currentNode->Next();
}
}
BlendTree::Node* BlendTree::FillTreeByName(Node* parentNode, std::string name, EntityWrapper parentEntity)
{
EntityWrapper childEntity = parentEntity.FirstLevelChildByName(name); // Make first level child by name
if (!childEntity.Valid()) {
return nullptr;
}
if (childEntity.HasComponent("Animation")) {
const Skeleton::Animation* animation = m_Skeleton->GetAnimation(childEntity["Animation"]["AnimationName"]);
if (animation == nullptr) {
return nullptr;
}
Node* node = new Node();
node->Entity = childEntity;
node->Name = childEntity.Name();
node->Pose = m_Skeleton->GetFrameBones(animation, (double)childEntity["Animation"]["Time"], (bool)childEntity["Animation"]["Additive"]);
node->Parent = parentNode;
node->Type = NodeType::Animation;
return node;
} else if (childEntity.HasComponent("Blend")) {
Node* node = new Node();
node->Entity = childEntity;
node->Name = childEntity.Name();
node->Parent = parentNode;
node->Type = NodeType::Blend;
(double&)childEntity["Blend"]["Weight"] = glm::clamp((double)childEntity["Blend"]["Weight"], 0.0, 1.0);
node->Weight = (double)childEntity["Blend"]["Weight"];
node->SubTreeRoot = (bool)childEntity["Blend"]["SubTreeRoot"];
//if (node->Weight < 1.f && node->Weight > 0.f) {
node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity);
node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity);
/* } else if (node->Weight == 1.f) {
node->Child[0] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose1"], childEntity);
} else if (node->Weight == 0.f) {
node->Child[1] = FillTreeByName(node, (std::string)childEntity["Blend"]["Pose2"], childEntity);
}*/
if(node->Child[0] == nullptr && node->Child[1] == nullptr) {
return nullptr;
} else {
return node;
}
} else if (childEntity.HasComponent("BlendOverride")) {
Node* node = new Node();
node->Entity = childEntity;
node->Name = childEntity.Name();
node->Parent = parentNode;
node->Type = NodeType::Override;
node->Child[0] = FillTreeByName(node, (std::string)childEntity["BlendOverride"]["Master"], childEntity);
node->Child[1] = FillTreeByName(node, (std::string)childEntity["BlendOverride"]["Slave"], childEntity);
if (node->Child[0] == nullptr && node->Child[1] == nullptr) {
return nullptr;
} else {
return node;
}
} else if (childEntity.HasComponent("BlendAdditive")) {
Node* node = new Node();
node->Entity = childEntity;
node->Name = childEntity.Name();
node->Parent = parentNode;
node->Type = NodeType::Additive;
node->Child[0] = FillTreeByName(node, (std::string)childEntity["BlendAdditive"]["Adder"], childEntity);
node->Child[1] = FillTreeByName(node, (std::string)childEntity["BlendAdditive"]["Receiver"], childEntity);
if(node->Child[0] == nullptr && node->Child[1] == nullptr) {
return nullptr;
} else {
return node;
}
}
return nullptr;
}
std::vector<BlendTree::Node*> BlendTree::FindNodesByName(std::string name)
{
std::vector<Node*> Nodes;
Node* currentNode = m_Root;
while (currentNode->Child[0] != nullptr) {
currentNode = currentNode->Child[0];
}
while (currentNode != nullptr) {
if(currentNode->Name == name) {
Nodes.push_back(currentNode);
}
currentNode = currentNode->Next();
}
return Nodes;
}
BlendTree::AutoBlendInfo BlendTree::AutoBlendStep(AutoBlendInfo blendInfo)
{
std::vector<Node*> goalNodes = FindNodesByName(blendInfo.NodeName);
if(blendInfo.Weight >= 0 && blendInfo.Weight <= 1.0) {
for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) {
EntityWrapper entity = (*it)->Entity;
if (entity.Valid()) {
if (entity.HasComponent("Blend")) {
(double&)entity["Blend"]["Weight"] = blendInfo.Weight;
}
}
}
return blendInfo;
}
if (blendInfo.Start) {
for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) {
EntityWrapper entity = (*it)->Entity;
if (entity.Valid()) {
if (entity.HasComponent("Animation")) {
(bool&)entity["Animation"]["Play"] = true;
}
}
}
}
if(goalNodes.size() == 0) {
return blendInfo;
} else if(goalNodes.size() == 1) {
Node* currentNode = goalNodes[0]->Parent;
Node* lastNode = goalNodes[0];
while (currentNode != nullptr)
{
if(!currentNode->Entity.HasComponent("Blend")) {
return blendInfo;
}
double startWeight;
if(blendInfo.StartWeights.find(currentNode->Entity) != blendInfo.StartWeights.end()) {
startWeight = blendInfo.StartWeights.at(currentNode->Entity);
} else {
startWeight = currentNode->Weight;
blendInfo.StartWeights[currentNode->Entity] = startWeight;
}
double goalWeight;
if(currentNode->Child[0] == lastNode) {
goalWeight = 0.0;
} else if (currentNode->Child[1] == lastNode) {
goalWeight = 1.0;
}
double weight = ((goalWeight - startWeight) * blendInfo.progress) + startWeight;
(double&)currentNode->Entity["Blend"]["Weight"] = weight;
currentNode->Weight = weight;
lastNode = currentNode;
currentNode = currentNode->Parent;
if (blendInfo.SingleBlend) {
break;
}
}
} else if(goalNodes.size() >= 2) {
std::vector<Node*> sharedParents;
std::vector<Node*> nodes = goalNodes;
for (auto it = nodes.begin(); it != nodes.end(); it++) {
auto next = std::next(it, 1);
if (next != nodes.end()) {
Node* commonParent = FirstCommonParent((*it), (*next));
sharedParents.push_back(commonParent);
(*next) = commonParent;
nodes.erase(it);
it = nodes.begin();
}
}
for (auto it = goalNodes.begin(); it != goalNodes.end(); it++) {
Node* currentNode = (*it)->Parent;
Node* lastNode = (*it);
while (currentNode != nullptr) {
if (!currentNode->Entity.HasComponent("Blend")) {
return blendInfo;
}
bool ShouldBreak = false;
for (auto it = sharedParents.begin(); it != sharedParents.end(); it++) {
if(currentNode == (*it)) {
ShouldBreak = true;
}
}
if(ShouldBreak) {
break;
}
double startWeight;
if (blendInfo.StartWeights.find(currentNode->Entity) != blendInfo.StartWeights.end()) {
startWeight = blendInfo.StartWeights.at(currentNode->Entity);
} else {
startWeight = currentNode->Weight;
blendInfo.StartWeights[currentNode->Entity] = startWeight;
}
double goalWeight;
if (currentNode->Child[0] == lastNode) {
goalWeight = 0.0;
} else if (currentNode->Child[1] == lastNode) {
goalWeight = 1.0;
}
double weight = ((goalWeight - startWeight) * blendInfo.progress) + startWeight;
(double&)currentNode->Entity["Blend"]["Weight"] = weight;
currentNode->Weight = weight;
lastNode = currentNode;
currentNode = currentNode->Parent;
}
}
}
return blendInfo;
}
BlendTree::Node* BlendTree::GetCommonParent(std::string NodeName1, std::string NodeName2)
{
std::vector<Node*> nodes1 = FindNodesByName(NodeName1);
std::vector<Node*> nodes2 = FindNodesByName(NodeName2);
for (auto it = nodes1.begin(); it != nodes1.end(); it++) {
auto next = std::next(it, 1);
if(next != nodes1.end()) {
Node* commonParent = FirstCommonParent((*it), (*next));
(*next) = commonParent;
nodes1.erase(it);
it = nodes1.begin();
}
}
for (auto it = nodes2.begin(); it != nodes2.end(); it++) {
auto next = std::next(it, 1);
if (next != nodes2.end()) {
Node* commonParent = FirstCommonParent((*it), (*next));
(*next) = commonParent;
nodes2.erase(it);
it = nodes2.begin();
}
}
return FirstCommonParent(nodes1.front(), nodes2.front());;
}
BlendTree::Node* BlendTree::FirstCommonParent(Node* node1, Node* node2)
{
std::list<Node*> node1Parents;
Node* currentNode = node1;
while (currentNode != nullptr) {
node1Parents.push_back(currentNode);
currentNode = currentNode->Parent;
}
currentNode = node2;
while (currentNode != nullptr) {
for (auto it = node1Parents.begin(); it != node1Parents.end(); it++) {
if (currentNode == (*it)) {
return currentNode;
}
}
currentNode = currentNode->Parent;
}
return nullptr;
}
EntityWrapper BlendTree::GetSubTreeRoot(std::string nodeName)
{
std::vector<Node*> nodes = FindNodesByName(nodeName);
if (nodes.size() == 0) {
return EntityWrapper::Invalid;
}
std::vector<Node*> subTreeRoots;
for (auto it = nodes.begin(); it != nodes.end(); it++) {
Node* currentNode = (*it)->Parent;
while (!currentNode->SubTreeRoot) {
currentNode = currentNode->Parent;
}
subTreeRoots.push_back(currentNode);
}
for (auto it = subTreeRoots.begin(); it != subTreeRoots.end(); it++) {
auto next = std::next(it, 1);
if (next != subTreeRoots.end()) {
Node* commonParent = FirstCommonParent((*it), (*next));
(*next) = commonParent;
subTreeRoots.erase(it);
it = subTreeRoots.begin();
}
}
return subTreeRoots.front()->Entity;
}
void BlendTree::Blend(std::map<int, Skeleton::PoseData>& pose)
{
Node* currentNode;
Node* start = m_Root;
while (start->Child[0] != nullptr) {
start = start->Child[0];
}
currentNode = start;
while (m_Root->Pose.size() == 0) {
if(currentNode->Pose.size() == 0) {
if (currentNode->Child[0] != nullptr && currentNode->Child[1] != nullptr) {
if (currentNode->Child[0]->Pose.size() != 0 && currentNode->Child[1]->Pose.size() != 0) {
switch (currentNode->Type) {
case BlendTree::NodeType::Additive:
currentNode->Pose = m_Skeleton->BlendPoseAdditive(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose);
break;
case BlendTree::NodeType::Blend:
currentNode->Pose = m_Skeleton->BlendPoses(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose, currentNode->Weight);
break;
case BlendTree::NodeType::Override:
currentNode->Pose = m_Skeleton->OverridePose(currentNode->Child[0]->Pose, currentNode->Child[1]->Pose);
break;
case BlendTree::NodeType::Animation:
// do nothing
break;
}
}
} else if (currentNode->Child[0] != nullptr) {
if (currentNode->Child[0]->Pose.size() != 0) {
currentNode->Pose = currentNode->Child[0]->Pose;
}
} else if (currentNode->Child[1] != nullptr) {
if (currentNode->Child[1]->Pose.size() != 0) {
currentNode->Pose = currentNode->Child[1]->Pose;
}
}
}
currentNode = currentNode->Next();
if (currentNode == nullptr) {
currentNode = start;
}
}
pose = m_Root->Pose;
}
std::vector<glm::mat4> BlendTree::AccumulateFinalPose()
{
std::vector<glm::mat4> finalPose;
if (m_Skeleton == nullptr || m_Root == nullptr || (m_Root->Child[0] == nullptr && m_Root->Child[1] == nullptr)) {
for (int i = 0; i < m_Skeleton->Bones.size(); i++) {
finalPose.push_back(glm::mat4(1));
}
return finalPose;
}
std::map<int, Skeleton::PoseData> pose;
Blend(pose);
m_Skeleton->GetFinalPose(pose, finalPose, m_FinalBoneTransforms);
return finalPose;
}
+23 -57
View File
@@ -8,10 +8,13 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp
return;
}
auto parent = entity.FirstParentWithComponent("Animation");
if (!parent.HasComponent("Model")) {
auto parent = entity.FirstParentWithComponent("Model");
if(!parent.Valid()) {
return;
}
Model* model;
try {
model = ResourceManager::Load<::Model, true>(parent["Model"]["Resource"]);
@@ -35,66 +38,29 @@ void BoneAttachmentSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp
return;
}
std::vector<::Skeleton::AnimationData> Animations;
::Skeleton::AnimationOffset AnimationOffset;
glm::mat4 boneTransform;
if (skeleton->BlendTrees.find(parent) != skeleton->BlendTrees.end()) {
if (parent.HasComponent("Animation")) {
for (int i = 1; i <= 3; i++) {
::Skeleton::AnimationData animationData;
animationData.animation = model->m_RawModel->m_Skeleton->GetAnimation(parent["Animation"]["AnimationName" + std::to_string(i)]);
if (animationData.animation == nullptr) {
continue;
}
animationData.time = (double)parent["Animation"]["Time" + std::to_string(i)];
animationData.weight = (double)parent["Animation"]["Weight" + std::to_string(i)];
Animations.push_back(animationData);
}
}
glm::mat4 boneTransform = skeleton->BlendTrees.at(parent)->GetBoneTransform(id);
if (parent.HasComponent("AnimationOffset")) {
AnimationOffset.animation = model->m_RawModel->m_Skeleton->GetAnimation(parent["AnimationOffset"]["AnimationName"]);
AnimationOffset.time = (double)parent["AnimationOffset"]["Time"];
glm::vec3 scale;
glm::quat rotation;
glm::vec3 translation;
glm::vec3 skew;
glm::vec4 perspective;
glm::decompose(boneTransform, scale, rotation, translation, skew, perspective);
if(AnimationOffset.animation != nullptr) {
boneTransform = skeleton->GetBoneTransform(false, skeleton->Bones.at(id), Animations, AnimationOffset, glm::mat4(1));
} else {
boneTransform = skeleton->GetBoneTransform(false, skeleton->Bones.at(id), Animations, glm::mat4(1));
}
glm::vec3 angles = glm::vec3(-glm::pitch(rotation), -glm::yaw(rotation), -glm::roll(rotation));
} else {
boneTransform = skeleton->GetBoneTransform(false, skeleton->Bones.at(id), Animations, glm::mat4(1));
if ((bool)entity["BoneAttachment"]["InheritPosition"]) {
(glm::vec3&)entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"];
}
if ((bool)entity["BoneAttachment"]["InheritOrientation"]) {
(glm::vec3&)entity["Transform"]["Orientation"] = angles + (glm::vec3)entity["BoneAttachment"]["OrientationOffset"];
}
if ((bool)entity["BoneAttachment"]["InheritScale"]) {
(glm::vec3&)entity["Transform"]["Scale"] = scale * (glm::vec3)entity["BoneAttachment"]["ScaleOffset"];
}
}
glm::vec3 scale;
glm::quat rotation;
glm::vec3 translation;
glm::vec3 skew;
glm::vec4 perspective;
glm::decompose(boneTransform, scale, rotation, translation, skew, perspective);
glm::vec3 angles = glm::vec3(-glm::pitch(rotation), -glm::yaw(rotation), -glm::roll(rotation));
/*
angles.y = asin(-boneTransform[0][2]);
if (cos(angles.y) != 0) {
angles.x = atan2(boneTransform[1][2], boneTransform[2][2]);
angles.z = atan2(boneTransform[0][1], boneTransform[0][0]);
} else {
angles.x = atan2(-boneTransform[2][0], boneTransform[1][1]);
angles.z = 0;
}*/
if ((bool)entity["BoneAttachment"]["InheritPosition"]) {
(glm::vec3&)entity["Transform"]["Position"] = translation + (glm::vec3)entity["BoneAttachment"]["PositionOffset"];
}
if ((bool)entity["BoneAttachment"]["InheritOrientation"]) {
(glm::vec3&)entity["Transform"]["Orientation"] = angles + (glm::vec3)entity["BoneAttachment"]["OrientationOffset"];
}
if ((bool)entity["BoneAttachment"]["InheritScale"]) {
(glm::vec3&)entity["Transform"]["Scale"] = scale * (glm::vec3)entity["BoneAttachment"]["ScaleOffset"];
}
}
+2
View File
@@ -45,6 +45,7 @@ void DrawBloomPass::InitializeShaderPrograms()
m_GaussianProgram_horiz->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Gaussian_horiz.vert.glsl")));
m_GaussianProgram_horiz->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Gaussian_horiz.frag.glsl")));
m_GaussianProgram_horiz->Compile();
m_GaussianProgram_horiz->BindFragDataLocation(0, "fragmentColor");
m_GaussianProgram_horiz->Link();
}
@@ -53,6 +54,7 @@ void DrawBloomPass::InitializeShaderPrograms()
m_GaussianProgram_vert->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Gaussian_vert.vert.glsl")));
m_GaussianProgram_vert->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Gaussian_vert.frag.glsl")));
m_GaussianProgram_vert->Compile();
m_GaussianProgram_vert->BindFragDataLocation(0, "fragmentColor");
m_GaussianProgram_vert->Link();
}
}
+124 -130
View File
@@ -358,27 +358,28 @@ void DrawFinalPass::DrawModelRenderQueues(std::list<std::shared_ptr<RenderJob>>&
case RawModel::MaterialType::Basic:
case RawModel::MaterialType::SingleTextures:
{
if (explosionEffectJob->Model->IsSkinned()) {
if (explosionEffectJob->Model->IsSkinned()) {
m_ExplosionEffectSkinnedProgram->Bind();
GLERROR("Bind ExplosionEffectSkinned program");
//bind uniforms
BindExplosionUniforms(explosionSkinnedHandle, explosionEffectJob, scene);
//bind textures
BindExplosionTextures(explosionSkinnedHandle, explosionEffectJob);
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture);
glUniform3fv(glGetUniformLocation(explosionSkinnedHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position()));
m_ExplosionEffectSkinnedProgram->Bind();
GLERROR("Bind ExplosionEffectSkinned program");
//bind uniforms
BindExplosionUniforms(explosionSkinnedHandle, explosionEffectJob, scene);
//bind textures
BindExplosionTextures(explosionSkinnedHandle, explosionEffectJob);
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture);
glUniform3fv(glGetUniformLocation(explosionSkinnedHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position()));
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);
}
glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
std::vector<glm::mat4> frameBones;
if (explosionEffectJob->BlendTree != nullptr) {
frameBones = explosionEffectJob->BlendTree->GetFinalPose();
} else {
frameBones = explosionEffectJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
else {
m_ExplosionEffectProgram->Bind();
GLERROR("Bind ExplosionEffect program");
@@ -394,23 +395,23 @@ void DrawFinalPass::DrawModelRenderQueues(std::list<std::shared_ptr<RenderJob>>&
}
case RawModel::MaterialType::SplatMapping:
{
if (explosionEffectJob->Model->IsSkinned()) {
m_ExplosionEffectSplatMapSkinnedProgram->Bind();
GLERROR("Bind ExplosionEffectSplatMapSkinned program");
//bind uniforms
BindExplosionUniforms(explosionSplatMapSkinnedHandle, explosionEffectJob, scene);
//bind textures
BindExplosionTextures(explosionSplatMapSkinnedHandle, explosionEffectJob);
GLERROR("asdasd");
std::vector<glm::mat4> frameBones;
if (explosionEffectJob->AnimationOffset.animation != nullptr) {
frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations, explosionEffectJob->AnimationOffset);
}
else {
frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations);
}
glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
if (explosionEffectJob->Model->IsSkinned()) {
m_ExplosionEffectSplatMapSkinnedProgram->Bind();
GLERROR("Bind ExplosionEffectSplatMapSkinned program");
//bind uniforms
BindExplosionUniforms(explosionSplatMapSkinnedHandle, explosionEffectJob, scene);
//bind textures
BindExplosionTextures(explosionSplatMapSkinnedHandle, explosionEffectJob);
GLERROR("asdasd");
std::vector<glm::mat4> frameBones;
if (explosionEffectJob->BlendTree != nullptr) {
frameBones = explosionEffectJob->BlendTree->GetFinalPose();
} else {
frameBones = explosionEffectJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
else {
m_ExplosionEffectSplatMapProgram->Bind();
GLERROR("Bind ExplosionEffectSplatMap program");
@@ -451,17 +452,15 @@ void DrawFinalPass::DrawModelRenderQueues(std::list<std::shared_ptr<RenderJob>>&
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture);
glUniform3fv(glGetUniformLocation(forwardSkinnedHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position()));
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);
}
glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
std::vector<glm::mat4> frameBones;
if (modelJob->BlendTree != nullptr) {
frameBones = modelJob->BlendTree->GetFinalPose();
} else {
frameBones = modelJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
else {
m_ForwardPlusProgram->Bind();
GLERROR("Bind ForwardPlusProgram");
@@ -485,14 +484,13 @@ void DrawFinalPass::DrawModelRenderQueues(std::list<std::shared_ptr<RenderJob>>&
//bind textures
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);
}
glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
std::vector<glm::mat4> frameBones;
if (modelJob->BlendTree != nullptr) {
frameBones = modelJob->BlendTree->GetFinalPose();
} else {
frameBones = modelJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
else {
@@ -569,14 +567,14 @@ void DrawFinalPass::DrawModelRenderQueuesWithShieldCheck(std::list<std::shared_p
glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture);
glUniform3fv(glGetUniformLocation(explosionSkinnedShieldCheckHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position()));
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);
}
glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedShieldCheckHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
std::vector<glm::mat4> frameBones;
if (explosionEffectJob->BlendTree != nullptr) {
frameBones = explosionEffectJob->BlendTree->GetFinalPose();
} else {
frameBones = explosionEffectJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedShieldCheckHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
else {
m_ExplosionEffectShieldCheckProgram->Bind();
@@ -602,14 +600,14 @@ void DrawFinalPass::DrawModelRenderQueuesWithShieldCheck(std::list<std::shared_p
//bind textures
BindExplosionTextures(explosionSplatMapSkinnedShieldCheckHandle, 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);
}
glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedShieldCheckHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
std::vector<glm::mat4> frameBones;
if (explosionEffectJob->BlendTree != nullptr) {
frameBones = explosionEffectJob->BlendTree->GetFinalPose();
} else {
frameBones = explosionEffectJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedShieldCheckHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
else {
@@ -642,15 +640,14 @@ void DrawFinalPass::DrawModelRenderQueuesWithShieldCheck(std::list<std::shared_p
glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture);
glUniform3fv(glGetUniformLocation(explosionSkinnedHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position()));
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);
}
glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
std::vector<glm::mat4> frameBones;
if (explosionEffectJob->BlendTree != nullptr) {
frameBones = explosionEffectJob->BlendTree->GetFinalPose();
} else {
frameBones = explosionEffectJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(explosionSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
else {
m_ExplosionEffectProgram->Bind();
GLERROR("Bind ExplosionEffect program");
@@ -674,14 +671,14 @@ void DrawFinalPass::DrawModelRenderQueuesWithShieldCheck(std::list<std::shared_p
//bind textures
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);
}
glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
std::vector<glm::mat4> frameBones;
if (explosionEffectJob->BlendTree != nullptr) {
frameBones = explosionEffectJob->BlendTree->GetFinalPose();
} else {
frameBones = explosionEffectJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(explosionSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
else {
m_ExplosionEffectSplatMapProgram->Bind();
@@ -726,14 +723,13 @@ void DrawFinalPass::DrawModelRenderQueuesWithShieldCheck(std::list<std::shared_p
glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture);
glUniform3fv(glGetUniformLocation(forwardSkinnedShieldCheckHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position()));
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);
}
glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedShieldCheckHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
std::vector<glm::mat4> frameBones;
if (modelJob->BlendTree != nullptr) {
frameBones = modelJob->BlendTree->GetFinalPose();
} else {
frameBones = modelJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedShieldCheckHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
else {
@@ -759,15 +755,14 @@ void DrawFinalPass::DrawModelRenderQueuesWithShieldCheck(std::list<std::shared_p
//bind textures
BindModelTextures(forwardSplatMapSkinnedShieldCheckHandle, 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);
}
glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedShieldCheckHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
std::vector<glm::mat4> frameBones;
if (modelJob->BlendTree != nullptr) {
frameBones = modelJob->BlendTree->GetFinalPose();
} else {
frameBones = modelJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedShieldCheckHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
else {
m_ForwardPlusSplatMapShieldCheckProgram->Bind();
@@ -797,14 +792,13 @@ void DrawFinalPass::DrawModelRenderQueuesWithShieldCheck(std::list<std::shared_p
glBindTexture(GL_TEXTURE_CUBE_MAP, m_CubeMapPass->m_CubeMapTexture);
glUniform3fv(glGetUniformLocation(forwardSkinnedHandle, "CameraPosition"), 1, glm::value_ptr(scene.Camera->Position()));
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);
}
glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
std::vector<glm::mat4> frameBones;
if (modelJob->BlendTree != nullptr) {
frameBones = modelJob->BlendTree->GetFinalPose();
} else {
frameBones = modelJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
else {
@@ -830,15 +824,14 @@ void DrawFinalPass::DrawModelRenderQueuesWithShieldCheck(std::list<std::shared_p
//bind textures
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);
}
glUniformMatrix4fv(glGetUniformLocation(forwardSplatMapSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
std::vector<glm::mat4> frameBones;
if (modelJob->BlendTree != nullptr) {
frameBones = modelJob->BlendTree->GetFinalPose();
} else {
frameBones = modelJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(forwardSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
else {
m_ForwardPlusSplatMapProgram->Bind();
@@ -897,10 +890,10 @@ 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);
if (explosionEffectJob->BlendTree != nullptr) {
frameBones = explosionEffectJob->BlendTree->GetFinalPose();
} else {
frameBones = explosionEffectJob->Skeleton->GetFrameBones(explosionEffectJob->Animations);
frameBones = explosionEffectJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
@@ -936,11 +929,12 @@ 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);
if (modelJob->BlendTree != nullptr) {
frameBones = modelJob->BlendTree->GetFinalPose();
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
frameBones = modelJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
@@ -972,10 +966,10 @@ void DrawFinalPass::DrawToDepthStencilBuffer(std::list<std::shared_ptr<RenderJob
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);
if (modelJob->BlendTree != nullptr) {
frameBones = modelJob->BlendTree->GetFinalPose();
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
frameBones = modelJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
+18 -26
View File
@@ -104,16 +104,15 @@ void PickingPass::Draw(RenderScene& scene)
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
std::vector<glm::mat4> frameBones;
if (modelJob->AnimationOffset.animation != nullptr) {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
}
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
std::vector<glm::mat4> frameBones;
if (modelJob->BlendTree != nullptr) {
frameBones = modelJob->BlendTree->GetFinalPose();
} else {
frameBones = modelJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
} else {
m_PickingProgram->Bind();
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
@@ -162,13 +161,11 @@ void PickingPass::Draw(RenderScene& scene)
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
std::vector<glm::mat4> frameBones;
if (modelJob->AnimationOffset.animation != nullptr) {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations, modelJob->AnimationOffset);
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
if (modelJob->BlendTree != nullptr) {
std::vector<glm::mat4> frameBones;
frameBones = modelJob->BlendTree->GetFinalPose();
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
} else {
m_PickingProgram->Bind();
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
@@ -218,11 +215,12 @@ 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);
if (modelJob->BlendTree != nullptr) {
frameBones = modelJob->BlendTree->GetFinalPose();
} else {
frameBones = modelJob->Skeleton->GetFrameBones(modelJob->Animations);
frameBones = modelJob->Skeleton->GetTPose();
}
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
} else {
@@ -322,16 +320,10 @@ void PickingPass::Draw(RenderScene& scene)
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
glUniform2fv(glGetUniformLocation(shaderSkinnedHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
if (modelJob->BlendTree != 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->BlendTree->GetFinalPose();
glUniformMatrix4fv(glGetUniformLocation(shaderSkinnedHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
}
} else {
m_PickingProgram->Bind();
+1 -1
View File
@@ -17,7 +17,7 @@ void Renderer::Initialize()
m_TextPass->Initialize();
/* m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
m_UnitQuad = ResourceManager::Load<Model>("Models/Core/UnitQuad.obj");
m_UnitQuad = ResourceManager::Load<Model>(sModels/Core/UnitQuad.obj");
m_UnitSphere = ResourceManager::Load<Model>("Models/Core/UnitSphere.obj");*/
m_ImGuiRenderPass = new ImGuiRenderPass(this, m_EventBroker);
+4
View File
@@ -56,6 +56,7 @@ void SSAOPass::InitializeShaderProgram()
m_SSAOProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/SSAO.vert.glsl")));
m_SSAOProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/SSAO.frag.glsl")));
m_SSAOProgram->Compile();
m_SSAOProgram->BindFragDataLocation(0, "AO");
m_SSAOProgram->Link();
}
@@ -64,6 +65,7 @@ void SSAOPass::InitializeShaderProgram()
m_SSAOViewSpaceZProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/SSAO.vert.glsl")));
m_SSAOViewSpaceZProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/SSAOViewSpaceZ.frag.glsl")));
m_SSAOViewSpaceZProgram->Compile();
m_SSAOViewSpaceZProgram->BindFragDataLocation(0, "depthLinear");
m_SSAOViewSpaceZProgram->Link();
}
@@ -72,6 +74,7 @@ void SSAOPass::InitializeShaderProgram()
m_GaussianProgram_horiz->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Gaussian_horiz.vert.glsl")));
m_GaussianProgram_horiz->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Gaussian_horiz.frag.glsl")));
m_GaussianProgram_horiz->Compile();
m_GaussianProgram_horiz->BindFragDataLocation(0, "fragmentColor");
m_GaussianProgram_horiz->Link();
}
@@ -80,6 +83,7 @@ void SSAOPass::InitializeShaderProgram()
m_GaussianProgram_vert->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Gaussian_vert.vert.glsl")));
m_GaussianProgram_vert->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Gaussian_vert.frag.glsl")));
m_GaussianProgram_vert->Compile();
m_GaussianProgram_vert->BindFragDataLocation(0, "fragmentColor");
m_GaussianProgram_vert->Link();
}
}
+209 -615
View File
@@ -1,343 +1,37 @@
#include "Rendering/Skeleton.h"
int Skeleton::CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix)
std::map<int, Skeleton::PoseData> Skeleton::GetFrameBones(const Animation* animation, double time, bool additive, bool noRootMotion /*= false*/)
{
if (m_BonesByName.find(name) != m_BonesByName.end()) {
return m_BonesByName.at(name)->ID;
} else {
Bone* bone;
if (parentID == -1) {
bone = new Bone(ID, nullptr, name, offsetMatrix);
RootBone = bone;
} else {
Bone* parent = Bones[parentID];
bone = new Bone(ID, parent, name, offsetMatrix);
parent->Children.push_back(bone);
}
Bones[ID] = bone;
m_BonesByName[name] = bone;
return ID;
}
}
Skeleton::~Skeleton()
{
for (auto &kv : Bones) {
delete kv.second;
}
}
const Skeleton::Animation* Skeleton::GetAnimation(std::string name)
{
auto it = Animations.find(name);
if (it != Animations.end()) {
return const_cast<const Animation*>(&it->second);
} else {
return nullptr;
}
}
std::vector<glm::mat4> Skeleton::GetFrameBones(std::vector<AnimationData> animations, bool noRootMotion /*= false*/)
{
if (animations.size() <= 0) {
std::vector<glm::mat4> finalMatrices;
if (animation == nullptr) {
std::map<int, PoseData> finalMatrices;
for (auto& b : Bones) {
finalMatrices.push_back(glm::mat4(1));//b.second->OffsetMatrix);
PoseData poseData;
poseData.Translation = glm::vec3(0);
poseData.Orientation = glm::quat();
poseData.Scale = glm::vec3(1);
finalMatrices[b.second->ID] = poseData;
}
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);
std::map<int, PoseData> frameBones;
if(!additive) {
AccumulateBoneTransforms(true, animation, time, frameBones, RootBone);
} else {
AdditiveBoneTransforms(animation, time, frameBones, RootBone);
}
return finalMatrices;
return frameBones;
}
std::vector<glm::mat4> Skeleton::GetFrameBones(std::vector<AnimationData> animations, AnimationOffset animationOffset, bool noRootMotion /*= false*/)
void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation* animation, double time, std::map<int, PoseData>& boneMatrices, const Bone* bone)
{
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;
}
PoseData poseData;
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, 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) {
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;
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) {
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
}
}
glm::mat4 offset = GetOffsetTransform(bone, animationOffset);
if (JointTransforms.size() == 0) {
if (bone->Parent) {
if (offset != glm::mat4(1)) {
boneMatrix = parentMatrix * offset;// *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix));
} else {
boneMatrix = parentMatrix *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix));
}
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
} else {
boneMatrix = offset * glm::inverse(bone->OffsetMatrix);
boneMatrices[bone->ID] = parentMatrix;
}
} else {
glm::vec3 finalPosInterp;
glm::quat finalRotInterp;
glm::vec3 finalScaleInterp;
float totalWeight = 0;
for (JointFrameTransform jointTransform : JointTransforms) {
totalWeight += jointTransform.Weight;
}
for (JointFrameTransform jointTransform : JointTransforms) {
if (jointTransform.Weight == 1.0f) {
finalPosInterp = jointTransform.PositionInterp;
finalRotInterp = jointTransform.RotationInterp;
finalScaleInterp = jointTransform.ScaleInterp;
break;
} else {
finalPosInterp += jointTransform.PositionInterp * (jointTransform.Weight/totalWeight);
finalRotInterp *= glm::slerp(glm::quat(), jointTransform.RotationInterp, (jointTransform.Weight/totalWeight));
finalScaleInterp += jointTransform.ScaleInterp * (jointTransform.Weight/totalWeight);
}
}
if (offset != glm::mat4(1)) {
boneMatrix = parentMatrix * ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset);
} else {
boneMatrix = parentMatrix * (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp));
}
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
}
for (auto &child : bone->Children) {
AccumulateBoneTransforms(noRootMotion, animations, animationOffset, boneMatrices, child, boneMatrix);
}
}
glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animationOffset)
{
const Animation* animation = animationOffset.animation;
float time = animationOffset.time;
glm::vec3 position = glm::vec3(0);
glm::quat rotation = glm::quat();
glm::vec3 scale = glm::vec3(1);
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
std::vector<Animation::Keyframe> boneKeyFrames = animation->JointAnimations.at(bone->ID);
@@ -364,37 +58,70 @@ glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animati
}
progress = glm::clamp(progress, 0.0f, 1.0f);
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties;
position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
glm::vec3 position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
glm::quat rotation = glm::normalize(glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress));
glm::vec3 scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
// Flag for no root motion
if (bone == RootBone && noRootMotion) {
position.x = 0;
position.z = 0;
}
poseData.Translation = position;
poseData.Orientation = rotation;
poseData.Scale = scale;
boneMatrices[bone->ID] = poseData;
} else { // 1 keyframes for the current bone
currentFrame = boneKeyFrames.at(0);
position = currentFrame.BoneProperties.Position;
rotation = currentFrame.BoneProperties.Rotation;
scale = currentFrame.BoneProperties.Scale;
poseData.Translation = currentFrame.BoneProperties.Position;
poseData.Orientation = currentFrame.BoneProperties.Rotation;
poseData.Scale = currentFrame.BoneProperties.Scale;
boneMatrices[bone->ID] = poseData;
}
}
return (glm::translate(position) * glm::toMat4(rotation) * glm::scale(scale));
for (auto &child : bone->Children) {
AccumulateBoneTransforms(noRootMotion, animation, time, boneMatrices, child);
}
}
glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animation, float time, glm::mat4 childMatrix)
void Skeleton::AdditiveBoneTransforms(const Animation* animation, double time, std::map<int, PoseData>& boneMatrices, const Bone* bone)
{
glm::mat4 boneMatrix;
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
PoseData refPose = GetAdditiveBonePose(bone, animation, 0.0);
PoseData srcPose = GetAdditiveBonePose(bone, animation, time + 1.0/60.0);
PoseData finalPose;
finalPose.Translation = srcPose.Translation - refPose.Translation;
finalPose.Orientation = srcPose.Orientation * glm::inverse(refPose.Orientation);
finalPose.Scale = srcPose.Scale - refPose.Scale;
Animation::Keyframe currentFrame;
Animation::Keyframe nextFrame;
boneMatrices[bone->ID] = finalPose;
}
for (auto &child : bone->Children) {
AdditiveBoneTransforms(animation, time, boneMatrices, child);
}
}
Skeleton::PoseData Skeleton::GetAdditiveBonePose(const Bone* bone, const Animation* animation, double time)
{
glm::vec3 position = glm::vec3(0);
glm::quat rotation = glm::quat();
glm::vec3 scale = glm::vec3(1);
if (animation->JointAnimations.find(bone->ID) != animation->JointAnimations.end()) {
std::vector<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) {
@@ -413,276 +140,148 @@ glm::mat4 Skeleton::GetBoneTransform(const Bone* bone, const Animation* animatio
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);
}
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;
position = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
rotation = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
scale = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
boneMatrix = (glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp)) * childMatrix;
} else { // 1 keyframes for the current bone
currentFrame = boneKeyFrames.at(0);
boneMatrix = (glm::translate(currentFrame.BoneProperties.Position) * glm::toMat4(currentFrame.BoneProperties.Rotation) * glm::scale(currentFrame.BoneProperties.Scale)) * childMatrix;
}
} else { // 0 keyframes for the current bone
if (bone->Parent) {
boneMatrix = bone->Parent->OffsetMatrix * glm::inverse(bone->OffsetMatrix) * childMatrix;
} else {
boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix;
position = currentFrame.BoneProperties.Position;
rotation = currentFrame.BoneProperties.Rotation;
scale = currentFrame.BoneProperties.Scale;
}
}
if (bone->Parent) {
return GetBoneTransform(bone->Parent, animation, time, boneMatrix);
} else {
return boneMatrix;
PoseData finalPose;
finalPose.Translation = position;
finalPose.Orientation = rotation;
finalPose.Scale = scale;
return finalPose;
}
std::map<int, Skeleton::PoseData> Skeleton::BlendPoses(const std::map<int, PoseData>& pose1, const std::map<int, PoseData>& pose2, double weight)
{
std::map<int, PoseData> finalPose;
float weight1 = (float)(1.0 - weight);
float weight2 = (float)(weight);
for (auto& b : Bones) {
int boneID = b.second->ID;
PoseData blendedPose;
blendedPose.Translation = glm::vec3(0);
blendedPose.Orientation = glm::quat();
blendedPose.Scale = glm::vec3(1);
if(pose1.find(boneID) != pose1.end() && pose2.find(boneID) != pose2.end()) {
blendedPose.Translation = pose1.at(boneID).Translation * weight1 + pose2.at(boneID).Translation * weight2;
blendedPose.Orientation = glm::slerp(pose1.at(boneID).Orientation, pose2.at(boneID).Orientation, weight2);
blendedPose.Scale = pose1.at(boneID).Scale * weight1 + pose2.at(boneID).Scale * weight2;
finalPose[boneID] = blendedPose;
} else if(pose1.find(boneID) != pose1.end()) {
finalPose[boneID] = pose1.at(boneID);
} else if (pose2.find(boneID) != pose2.end()) {
finalPose[boneID] = pose2.at(boneID);
}
}
return finalPose;
}
std::map<int, Skeleton::PoseData> Skeleton::OverridePose(const std::map<int, PoseData>& overridePose, const std::map<int, PoseData>& targetPose)
{
std::map<int, PoseData> finalPose;
for (auto& b : Bones) {
int boneID = b.second->ID;
if (overridePose.find(boneID) != overridePose.end()) {
finalPose[boneID] = overridePose.at(boneID);
} else if (targetPose.find(boneID) != targetPose.end()) {
finalPose[boneID] = targetPose.at(boneID);
}
}
return finalPose;
}
std::map<int, Skeleton::PoseData> Skeleton::BlendPoseAdditive(const std::map<int, PoseData>& additivePose, const std::map<int, PoseData>& targetPose)
{
std::map<int, PoseData> finalPose;
for (auto& b : Bones) {
int boneID = b.second->ID;
PoseData blendedPose;
blendedPose.Translation = glm::vec3(0);
blendedPose.Orientation = glm::quat();
blendedPose.Scale = glm::vec3(1);
if (additivePose.find(boneID) != additivePose.end() && targetPose.find(boneID) != targetPose.end()) {
blendedPose.Translation = additivePose.at(boneID).Translation + targetPose.at(boneID).Translation;
blendedPose.Orientation = additivePose.at(boneID).Orientation * targetPose.at(boneID).Orientation;
blendedPose.Scale = additivePose.at(boneID).Scale + targetPose.at(boneID).Scale;
finalPose[boneID] = blendedPose;
} else if (additivePose.find(boneID) != additivePose.end()) {
finalPose[boneID] = additivePose.at(boneID);
} else if (targetPose.find(boneID) != targetPose.end()) {
finalPose[boneID] = targetPose.at(boneID);
}
}
return finalPose;
}
void Skeleton::GetFinalPose(std::map<int, Skeleton::PoseData>& poseDatas, std::vector<glm::mat4>& finalPose, std::map<int, glm::mat4>& boneTransforms)
{
std::map<int, glm::mat4> boneMatrices;
AccumulateFinalPose(boneMatrices, poseDatas, boneTransforms, RootBone, glm::mat4(1));
for(auto& b : boneMatrices) {
finalPose.push_back(b.second);
}
}
glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector<AnimationData> animations, AnimationOffset animationOffset, glm::mat4 childMatrix)
std::vector<glm::mat4> Skeleton::GetTPose()
{
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
}
std::vector<glm::mat4> finalMatrices;
for (auto b : Bones) {
finalMatrices.push_back(glm::mat4(1));
}
glm::mat4 offset = GetOffsetTransform(bone, animationOffset);
if (JointTransforms.size() == 0) {
if (bone->Parent) {
if (offset != glm::mat4(1)) {
boneMatrix = offset * childMatrix;// *((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix));
} else {
boneMatrix = ((glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix)) * childMatrix;
}
} else {
boneMatrix = offset * glm::inverse(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);
}
}
if (offset != glm::mat4(1)) {
boneMatrix = ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset) * childMatrix;
} else {
boneMatrix = (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) * childMatrix;
}
}
if (bone->Parent != nullptr) {
return GetBoneTransform(noRootMotion, bone->Parent, animations, animationOffset, boneMatrix);
} else {
return boneMatrix;
}
return finalMatrices;
}
glm::mat4 Skeleton::GetBoneTransform(bool noRootMotion, const Bone* bone, std::vector<AnimationData> animations, glm::mat4 childMatrix)
void Skeleton::AccumulateFinalPose(std::map<int, glm::mat4>& boneMatrices, std::map<int, Skeleton::PoseData>& poseDatas, std::map<int, glm::mat4>& boneTransforms, 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 (poseDatas.find(bone->ID) != poseDatas.end()) {
boneMatrix = parentMatrix * (glm::translate(poseDatas.at(bone->ID).Translation) * glm::mat4(poseDatas.at(bone->ID).Orientation) * glm::scale(poseDatas.at(bone->ID).Scale));
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
} else {
if (bone->Parent) {
boneMatrix = glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix * childMatrix;
boneMatrix = parentMatrix * (glm::inverse(bone->OffsetMatrix) * bone->Parent->OffsetMatrix);
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
} else {
boneMatrix = glm::inverse(bone->OffsetMatrix) * childMatrix;
boneMatrix = glm::inverse(bone->OffsetMatrix);
boneMatrices[bone->ID] = parentMatrix;
}
} else if (JointTransforms.size() == 1) {
boneMatrix = (glm::translate(JointTransforms.at(0).PositionInterp) * glm::toMat4(JointTransforms.at(0).RotationInterp) * glm::scale(JointTransforms.at(0).ScaleInterp)) * childMatrix;
} 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 = (glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) * childMatrix;
}
boneTransforms[bone->ID] = boneMatrix;
if (bone->Parent != nullptr) {
return GetBoneTransform(noRootMotion, bone->Parent, animations, boneMatrix);
} else {
return boneMatrix;
for (auto &child : bone->Children) {
AccumulateFinalPose(boneMatrices, poseDatas, boneTransforms, child, boneMatrix);
}
}
@@ -695,46 +294,41 @@ int Skeleton::GetBoneID(std::string name)
}
}
void Skeleton::PrintSkeleton()
int Skeleton::CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix)
{
if (LOG_LEVEL < LOG_LEVEL_DEBUG) {
return;
}
PrintSkeleton(RootBone, 0);
if (m_BonesByName.find(name) != m_BonesByName.end()) {
return m_BonesByName.at(name)->ID;
} else {
Bone* bone;
if (parentID == -1) {
bone = new Bone(ID, nullptr, name, offsetMatrix);
RootBone = bone;
} else {
Bone* parent = Bones[parentID];
bone = new Bone(ID, parent, name, offsetMatrix);
parent->Children.push_back(bone);
}
Bones[ID] = bone;
m_BonesByName[name] = bone;
return ID;
}
}
void Skeleton::PrintSkeleton(const Bone* bone, int depthCount)
Skeleton::~Skeleton()
{
std::stringstream ss;
ss << std::string(depthCount, ' ');
ss << bone->ID << ": " << bone->Name;
std::cout << ss.str() << std::endl;
depthCount++;
for (auto &child : bone->Children) {
PrintSkeleton(child, depthCount);
}
for (auto &kv : Bones) {
delete kv.second;
}
}
int Skeleton::GetKeyframe(const Animation& animation, double time)
const Skeleton::Animation* Skeleton::GetAnimation(std::string name)
{
/*
if (time < 0) {
time = 0;
}
if (time >= animation.Duration) {
return animation..size() - 1;
}
for (int keyframe = 0; keyframe < animation.Keyframes.size(); ++keyframe) {
if (animation.Keyframes[keyframe].Time > time) {
return (keyframe - 1) % animation.Keyframes.size();
}
}
*/
return 0;
}
auto it = Animations.find(name);
if (it != Animations.end()) {
return const_cast<const Animation*>(&it->second);
} else {
return nullptr;
}
}
+10 -5
View File
@@ -18,7 +18,9 @@
#include "Game/Systems/PickupSpawnSystem.h"
#include "Game/Systems/AmmoPickupSystem.h"
#include "Game/Systems/DamageIndicatorSystem.h"
#include "Game/Systems/Weapon/AssaultWeaponBehaviour.h"
#include "Game/Systems/Weapon/DefenderWeaponBehaviour.h"
#include "Game/Systems/Weapon/SidearmWeaponBehaviour.h"
#include "Rendering/AnimationSystem.h"
#include "Game/Systems/HealthHUDSystem.h"
#include "Rendering/BoneAttachmentSystem.h"
@@ -26,12 +28,13 @@
#include "../Engine/Core/UniformScaleSystem.h"
#include "Rendering/AnimationSystem.h"
#include "Network/MultiplayerSnapshotFilter.h"
#include "Game/Systems/AmmunitionHUDSystem.h"
#include "Game/Systems/TextFieldReader.h"
#include "Game/Systems/AbilityCooldownHUDSystem.h"
#include "Game/Systems/CapturePointArrowHUDSystem.h"
#include "Game/Systems/KillFeedSystem.h"
#include "Game/Systems/BoostSystem.h"
#include "Game/Systems/BoostIconsHUDSystem.h"
#include "Game/Systems/ScoreScreenSystem.h"
#include "GUI/ButtonSystem.h"
#include "GUI/MainMenuSystem.h"
@@ -109,7 +112,7 @@ Game::Game(int argc, char* argv[])
// 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));
AABB boxContainingTheWorld = AABB::FromOriginSize(glm::vec3(0.f, 10.7f, 0.f), glm::vec3(140.f, 31.f, 190.f));
m_OctreeCollision = new Octree<EntityAABB>(boxContainingTheWorld, 4);
m_OctreeTrigger = new Octree<EntityAABB>(boxContainingTheWorld, 4);
m_OctreeFrustrumCulling = new Octree<EntityAABB>(boxContainingTheWorld, 4);
@@ -128,29 +131,31 @@ Game::Game(int argc, char* argv[])
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<AssaultWeaponBehaviour>(updateOrderLevel, m_Renderer, m_OctreeCollision);
m_SystemPipeline->AddSystem<DefenderWeaponBehaviour>(updateOrderLevel, m_Renderer, m_OctreeCollision);
m_SystemPipeline->AddSystem<SidearmWeaponBehaviour>(updateOrderLevel, m_Renderer, m_OctreeCollision);
m_SystemPipeline->AddSystem<LifetimeSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<CapturePointSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<CapturePointHUDSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PickupSpawnSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<AmmoPickupSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<DamageIndicatorSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<AmmunitionHUDSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<TextFieldReader>(updateOrderLevel);
m_SystemPipeline->AddSystem<AbilityCooldownHUDSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<CapturePointArrowHUDSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<KillFeedSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<LifetimeSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<CapturePointSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<CapturePointHUDSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PickupSpawnSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<AmmoPickupSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<DamageIndicatorSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<AmmunitionHUDSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<TextFieldReader>(updateOrderLevel);
m_SystemPipeline->AddSystem<KillFeedSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<BoostSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<ButtonSystem>(updateOrderLevel, m_Renderer);
m_SystemPipeline->AddSystem<MainMenuSystem>(updateOrderLevel, m_Renderer);
m_SystemPipeline->AddSystem<BoostIconsHUDSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<ScoreScreenSystem>(updateOrderLevel);
// Populate Octree with collidables
++updateOrderLevel;
m_SystemPipeline->AddSystem<FillOctreeSystem>(updateOrderLevel, m_OctreeCollision, "Collidable");
+63 -11
View File
@@ -11,20 +11,72 @@ void AbilityCooldownHUDSystem::Update(double dt)
for (auto& abilityHUDC : *abilityHUDs) {
EntityWrapper entity = EntityWrapper(m_World, abilityHUDC.EntityID);
EntityWrapper abilityEntity = entity.FirstParentWithComponent("DashAbility");
if (!abilityEntity.Valid())
return;
std::string abilityName = "";
if (!abilityEntity.Valid()) {
//If we dont have a dash ability on player, we check for Sprint ability
abilityEntity = entity.FirstParentWithComponent("SprintAbility");
if (!abilityEntity.Valid()) {
//If we dont have a sprint ability on player, we check for shield ability
abilityEntity = entity.FirstParentWithComponent("ShieldAbility");
if (!abilityEntity.Valid()) {
//If we dont have a shield ability, we return, since we cannot do anything.
return;
} else {
//If we have a shield ability, we set the right icon
abilityName = "ShieldAbility";
if (entity.HasComponent("Sprite")) {
(std::string&)entity["Sprite"]["DiffuseTexture"] = "Textures\\Icons\\Abilities\\SheildDots-01.png";
}
}
} else {
//If we do have a sprint ability, we change the icon
abilityName = "SprintAbility";
if (entity.HasComponent("Sprite")) {
(std::string&)entity["Sprite"]["DiffuseTexture"] = "Textures\\Icons\\Abilities\\Dash-01.png";
}
}
} else {
//If we have a dash ability, we set the icon to the correct one.
abilityName = "DashAbility";
if (entity.HasComponent("Sprite")) {
(std::string&)entity["Sprite"]["DiffuseTexture"] = "Textures\\Icons\\Abilities\\Superman-01.png";
}
}
EntityWrapper cooldownTextEntity = entity.FirstChildByName("Cooldown");
if(cooldownTextEntity.Valid()) {
if(cooldownTextEntity.HasComponent("Text"))
{
double maxAbilityCD = (double)abilityEntity["DashAbility"]["CoolDownMaxTimer"];
double currentAbilityCD = (double)abilityEntity["DashAbility"]["CoolDownTimer"];
currentAbilityCD = currentAbilityCD >= 0.0 ? currentAbilityCD : 0.0;
std::string t = (std::string&)cooldownTextEntity["Text"]["Content"] = std::to_string(currentAbilityCD).substr(0, 3);
if(entity.HasComponent("Fill")) {
entity["Fill"]["Percentage"] = currentAbilityCD/maxAbilityCD; //TODO: current time needs to be in the component.
//TODO: Fix so this track correctly for shield and sprint depending on how they work.
double maxAbilityCD, currentAbilityCD;
if (abilityName == "DashAbility") {
maxAbilityCD = (double)abilityEntity[abilityName]["CoolDownMaxTimer"];
currentAbilityCD = (double)abilityEntity[abilityName]["CoolDownTimer"];
currentAbilityCD = currentAbilityCD >= 0.0 ? currentAbilityCD : 0.0;
if (cooldownTextEntity.Valid()) {
if (cooldownTextEntity.HasComponent("Text")) {
std::string t = (std::string&)cooldownTextEntity["Text"]["Content"] = std::to_string(currentAbilityCD).substr(0, 3);
}
}
}
if (abilityName == "ShieldAbility") {
maxAbilityCD = 0.0;
currentAbilityCD = 1 - (bool)abilityEntity[abilityName]["Active"];
}
if (abilityName == "SprintAbility") {
maxAbilityCD = 0.0;
currentAbilityCD = 1 - (bool)abilityEntity[abilityName]["Active"];
}
if (entity.HasComponent("Fill")) {
entity["Fill"]["Percentage"] = currentAbilityCD/maxAbilityCD;
}
}
}
-36
View File
@@ -1,36 +0,0 @@
#include "Game/Systems/AmmunitionHUDSystem.h"
void AmmunitionHUDSystem::Update(double dt)
{
//Hud element for tracking ammunition from parent with AssaultWeapon component.Child with the name "MagazineAmmo" tracks clip ammunition.Child with the name "Ammo" tracks ammo.</xs:documentation>
auto ammunitionHUDs = m_World->GetComponents("AmmunitionHUD");
if (ammunitionHUDs == nullptr) {
return;
}
for (auto& ammunitionHUDComponent : *ammunitionHUDs) {
EntityWrapper entity = EntityWrapper(m_World, ammunitionHUDComponent.EntityID);
EntityWrapper playerEntity = entity.FirstParentWithComponent("AssaultWeapon");
if (!playerEntity.Valid()) {
return;
}
EntityWrapper magazineAmmo = entity.FirstChildByName("MagazineAmmo");
if(magazineAmmo.Valid()) {
if(magazineAmmo.HasComponent("Text")) {
(std::string&)magazineAmmo["Text"]["Content"] = std::to_string((int)playerEntity["AssaultWeapon"]["MagazineAmmo"]);
}
}
EntityWrapper ammo = entity.FirstChildByName("Ammo");
if (ammo.Valid()) {
if (ammo.HasComponent("Text")) {
(std::string&)ammo["Text"]["Content"] = std::to_string((int)playerEntity["AssaultWeapon"]["Ammo"]);
}
}
}
}
+8 -2
View File
@@ -11,10 +11,16 @@ bool BoostSystem::OnPlayerDamage(Events::PlayerDamage& e)
if (e.Victim.ID == e.Inflictor.ID) {
return false;
}
if (!e.Victim.Valid() && e.Victim != LocalPlayer && !e.Victim.IsChildOf(LocalPlayer)) {
if (!e.Victim.Valid() || !LocalPlayer.Valid()) {
return false;
}
if (!e.Inflictor.Valid() || !e.Victim.Valid()) {
if (e.Victim != LocalPlayer && !e.Victim.IsChildOf(LocalPlayer)) {
return false;
}
if (!e.Inflictor.Valid()) {
return false;
}
+3 -3
View File
@@ -9,7 +9,7 @@ CapturePointHUDSystem::CapturePointHUDSystem(SystemParams params)
void CapturePointHUDSystem::Update(double dt)
{
bool LoadCheck = true;
bool loadCheck = true;
int redTeam;
int blueTeam;
int spectatorTeam;
@@ -35,11 +35,11 @@ void CapturePointHUDSystem::Update(double dt)
//Check if the HUD corresponds to the Capture Point Number
if (HUD_ID == (int)entityCP["CapturePoint"]["CapturePointNumber"]) {
ComponentWrapper& teamComponent = entityCP["Team"];
if (LoadCheck) {
if (loadCheck) {
redTeam = (int)teamComponent["Team"].Enum("Red");
blueTeam = (int)teamComponent["Team"].Enum("Blue");
spectatorTeam = (int)teamComponent["Team"].Enum("Spectator");
LoadCheck = false;
loadCheck = false;
}
//Color hud with team color
auto capturePointTeam = (int)teamComponent["Team"];
+12
View File
@@ -69,6 +69,7 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp
int ownedBy = teamComponent["Team"];
int redTeamPlayersStandingInside = 0;
int blueTeamPlayersStandingInside = 0;
//note: old color system
if (capturePointEntity.HasComponent("Model")) {
//Now sets team color to the capturepoint, or white if it is uncaptured.
capturePointEntity["Model"]["Color"] = ownedBy == blueTeam ? glm::vec4(0, 0.0f, 1, 0.3) : ownedBy == redTeam ? glm::vec4(1, 0.0f, 0, 0.3) : glm::vec4(1, 1, 1, 0.3);
@@ -102,7 +103,18 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, Comp
nextPossibleCapturePoint["Blue"] = i - 1;
}
}
if (m_RecentlyCapturedNeedNextCapturePointNow) {
//change what model is displaying (change all in case 2 capturepoints has been captured on the same frame)
for (int i = 0; i < m_NumberOfCapturePoints; i++) {
auto owner = (int)m_CapturePointNumberToEntityMap[i]["Team"]["Team"];
if (m_CapturePointNumberToEntityMap[i].FirstChildByName("Red").ID != EntityID_Invalid) {
(bool&)m_CapturePointNumberToEntityMap[i].FirstChildByName("Red")["Model"]["Visible"] = owner == redTeam ? true : false;
(bool&)m_CapturePointNumberToEntityMap[i].FirstChildByName("Blue")["Model"]["Visible"] = owner == blueTeam ? true : false;
(bool&)m_CapturePointNumberToEntityMap[i].FirstChildByName("Spectator")["Model"]["Visible"] = owner == spectatorTeam ? true : false;
}
}
//save the next cap points and publish the captured event
m_CapturedEvent.BlueTeamNextCapturePoint = m_CapturePointNumberToEntityMap[nextPossibleCapturePoint["Blue"]];
m_CapturedEvent.RedTeamNextCapturePoint = m_CapturePointNumberToEntityMap[nextPossibleCapturePoint["Red"]];
m_EventBroker->Publish(m_CapturedEvent);
+11 -10
View File
@@ -12,15 +12,7 @@ HealthSystem::HealthSystem(SystemParams params)
}
void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cHealth, double dt)
{
double& health = cHealth["Health"];
if (health <= 0.0) {
Events::PlayerDeath ePlayerDeath;
ePlayerDeath.Player = entity;
m_EventBroker->Publish(ePlayerDeath);
//Note: we will delete the entity in PlayerDeathSystem
}
}
{ }
bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e)
{
@@ -35,7 +27,16 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e)
if (playerBoostDefenderEntity.Valid()) {
e.Damage -= (double)playerBoostDefenderEntity["BoostDefender"]["StrengthOfEffect"];
}
health -= e.Damage;
if (health > 0) {
health -= e.Damage;
if (health <= 0.0) {
Events::PlayerDeath ePlayerDeath;
ePlayerDeath.Player = e.Victim;
ePlayerDeath.Killer = e.Inflictor;
m_EventBroker->Publish(ePlayerDeath);
//Note: we will delete the entity in PlayerDeathSystem
}
}
return true;
}
-4
View File
@@ -45,10 +45,6 @@ void PlayerDeathSystem::createDeathEffect(EntityWrapper player)
//copy the data from player to explosioneffectmodel
playerEntityModel.Copy(deathEffectEW["Model"]);
playerEntityAnimation.Copy(deathEffectEW["Animation"]);
//freeze the animation
deathEffectEW["Animation"]["Speed1"] = 0.0;
deathEffectEW["Animation"]["Speed2"] = 0.0;
deathEffectEW["Animation"]["Speed3"] = 0.0;
//copy the models position,orientation
deathEffectEW["Transform"]["Position"] = (glm::vec3)player["Transform"]["Position"];
+242 -95
View File
@@ -2,6 +2,7 @@
PlayerMovementSystem::PlayerMovementSystem(SystemParams params)
: System(params)
, m_SprintEffectTimer(0.f)
{
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &PlayerMovementSystem::OnPlayerSpawned);
EVENT_SUBSCRIBE_MEMBER(m_EDoubleJump, &PlayerMovementSystem::OnDoubleJump);
@@ -18,14 +19,49 @@ PlayerMovementSystem::~PlayerMovementSystem()
void PlayerMovementSystem::Update(double dt)
{
updateMovementControllers(dt);
if (IsServer) {
for (auto& kv : m_PlayerInputControllers) {
updateVelocity(kv.first, dt);
}
} else {
if (LocalPlayer.Valid()) {
// Only do physics calculations on client and only for themselves.
if (IsClient) {
if (LocalPlayer.Valid()){
updateVelocity(LocalPlayer, dt);
}
m_SprintEffectTimer += dt;
if (m_SprintEffectTimer < 0.016f) {
return;
}
m_SprintEffectTimer = 0.f;
const ComponentPool* pool = m_World->GetComponents("SprintAbility");
if (pool == nullptr) {
return;
}
for (auto cSprint : *pool) {
if (cSprint.EntityID != LocalPlayer.ID && (bool)cSprint["Active"]) {
// Spawn one afterimage for each player that sprints.
EntityWrapper player(m_World, cSprint.EntityID);
auto entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/SprintEffect.xml");
EntityWrapper sprintEffect = entityFile->MergeInto(m_World);
auto playerModel = player.FirstChildByName("PlayerModel");
if (!playerModel.Valid()) {
continue;
}
if (!playerModel.HasComponent("Model")) {
continue;
}
if (!playerModel.HasComponent("Animation")) {
continue;
}
auto playerEntityModel = playerModel["Model"];
auto playerEntityAnimation = playerModel["Animation"];
playerEntityModel.Copy(sprintEffect["Model"]);
playerEntityAnimation.Copy(sprintEffect["Animation"]);
sprintEffect["ExplosionEffect"]["EndColor"] = (glm::vec4)playerEntityModel["Color"];
((glm::vec4&)sprintEffect["ExplosionEffect"]["EndColor"]).w = 0.f;
sprintEffect["Animation"]["Speed1"] = 0.0;
sprintEffect["Animation"]["Speed2"] = 0.0;
sprintEffect["Animation"]["Speed3"] = 0.0;
sprintEffect["Transform"]["Position"] = (glm::vec3)player["Transform"]["Position"];
sprintEffect["Transform"]["Orientation"] = (glm::vec3)player["Transform"]["Orientation"];
}
}
}
}
@@ -47,11 +83,25 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
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");
//Third-person aim
if (playerModel.Valid()) {
ComponentWrapper cAnimationOffset = playerModel["AnimationOffset"];
float pitch = cameraOrientation.x + 0.2f;
double time = (pitch + glm::half_pi<float>()) / glm::pi<float>();
cAnimationOffset["Time"] = time;
EntityWrapper aimPrimaryEntity = playerModel.FirstChildByName("AimPrimary");
if(aimPrimaryEntity.Valid()){
if(aimPrimaryEntity.HasComponent("Animation")) {
float pitch = cameraOrientation.x + 0.2f;
double time = (pitch + glm::half_pi<float>()) / glm::pi<float>();
(double&)aimPrimaryEntity["Animation"]["Time"] = time;
}
}
EntityWrapper aimSecondaryEntity = playerModel.FirstChildByName("AimSecondary");
if (aimSecondaryEntity.Valid()) {
if (aimSecondaryEntity.HasComponent("Animation")) {
float pitch = cameraOrientation.x + 0.2f;
double time = (pitch + glm::half_pi<float>()) / glm::pi<float>();
(double&)aimSecondaryEntity["Animation"]["Time"] = time;
}
}
}
}
@@ -67,7 +117,15 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
playerMovementSpeed *= (double)playerBoostAssaultEntity["BoostAssault"]["StrengthOfEffect"];
playerCrouchSpeed *= (double)playerBoostAssaultEntity["BoostAssault"]["StrengthOfEffect"];
}
bool sniperSprinting = false;
if (player.HasComponent("SprintAbility")) {
(bool)player["SprintAbility"]["Active"] = controller->SpecialAbilityKeyDown();
if (controller->SpecialAbilityKeyDown()) {
playerMovementSpeed *= (double)player["SprintAbility"]["StrengthOfEffect"];
playerCrouchSpeed *= (double)player["SprintAbility"]["StrengthOfEffect"];
sniperSprinting = true;
}
}
if (player.HasComponent("Physics")) {
ComponentWrapper cPhysics = player["Physics"];
@@ -123,6 +181,9 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
if (playerBoostAssaultEntity.Valid()) {
accelerationSpeed *= (double)playerBoostAssaultEntity["BoostAssault"]["StrengthOfEffect"];
}
if (sniperSprinting) {
accelerationSpeed *= (double)player["SprintAbility"]["StrengthOfEffect"];
}
velocity += accelerationSpeed * wishDirection;
ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity));
}
@@ -135,10 +196,64 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
if (isOnGround) {
(bool)cPhysics["IsOnGround"] = false;
velocity.y = player["Player"]["JumpSpeed"];
if (player.Valid()) {
EntityWrapper playerModel = player.FirstChildByName("PlayerModel");
if (playerModel.Valid()) {
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.15;
aeb.NodeName = "Jump";
aeb.RootNode = playerModel;
aeb.Start = true;
aeb.Restart = true;
m_EventBroker->Publish(aeb);
}
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.25;
aeb.NodeName = "StandCrouchBlend";
aeb.RootNode = playerModel;
aeb.Start = true;
aeb.Restart = false;
aeb.AnimationEntity = playerModel.FirstChildByName("Jump");
m_EventBroker->Publish(aeb);
}
}
}
} else if (player.HasComponent("DoubleJump") && !controller->DoubleJumping()) {
//Enter here if player can double jump and is doing so.
(bool)cPhysics["IsOnGround"] = false;
velocity.y = player["DoubleJump"]["DoubleJumpSpeed"];
if (player.Valid()) {
EntityWrapper playerModel = player.FirstChildByName("PlayerModel");
if (playerModel.Valid()) {
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.15;
aeb.NodeName = "Jump";
aeb.RootNode = playerModel;
aeb.Start = true;
aeb.Restart = true;
m_EventBroker->Publish(aeb);
}
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.25;
aeb.NodeName = "StandCrouchBlend";
aeb.RootNode = playerModel;
aeb.Start = true;
aeb.Restart = false;
aeb.AnimationEntity = playerModel.FirstChildByName("Jump");
m_EventBroker->Publish(aeb);
}
}
}
// If IsServer and network is off this will not work
if (IsClient) {
//put a hexagon at the players feet
@@ -161,81 +276,7 @@ void PlayerMovementSystem::updateMovementControllers(double dt)
}
}
// Animations
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) {
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 {
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()) {
animationName1 = "Crouch";
animationName2 = "";
animationSpeed1 = 1.0;
animationSpeed2 = 0.0;
animationWeight1 = 1.0;
animationWeight2 = 0.0;
} else {
animationName1 = "Idle";
animationName2 = "";
animationSpeed1 = 1.f;
animationSpeed2 = 0.0;
animationWeight1 = 1.0;
animationWeight2 = 0.0;
//cAnimation["AnimationName2"] = "Idle";
}
}
}
// TODO: Animations
}
controller->Reset();
@@ -303,7 +344,7 @@ void PlayerMovementSystem::playerStep(double dt)
bool PlayerMovementSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
{
// When a player spawns, create an input controller for them
m_PlayerInputControllers[e.Player] = new FirstPersonInputController<PlayerMovementSystem>(m_EventBroker, e.PlayerID);
m_PlayerInputControllers[e.Player] = new FirstPersonInputController<PlayerMovementSystem>(m_EventBroker, e.PlayerID, e.Player);
if (e.PlayerID == -1) {
// Keep track of the local player
m_LocalPlayer = e.Player;
@@ -336,23 +377,129 @@ void PlayerMovementSystem::spawnHexagon(EntityWrapper target)
bool PlayerMovementSystem::OnDashAbility(Events::DashAbility & e)
{
EntityWrapper player(m_World, e.Player);
if (!player.Valid() || !IsClient || player.ID == LocalPlayer.ID) {
if (!player.Valid() || !IsClient){// || player.ID == LocalPlayer.ID) {
return false;
}
auto entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/DashEffect.xml");
EntityWrapper dashEffect = entityFile->MergeInto(m_World);
auto playerModel = player.FirstChildByName("PlayerModel");
auto playerEntityModel = playerModel["Model"];
EntityWrapper playerModel = player.FirstChildByName("PlayerModel");
for (auto& kv : m_PlayerInputControllers) {
EntityWrapper player = kv.first;
auto& controller = kv.second;
if (!player.Valid()) {
continue;
}
if (player.Valid()) {
EntityWrapper playerModel = player.FirstChildByName("PlayerModel");
if (playerModel.Valid()) {
if (glm::abs(controller->Movement().x) > glm::abs(controller->Movement().z)) {
if (controller->Movement().x > 0) {
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.NodeName = "DashRight";
aeb.RootNode = playerModel;
aeb.Restart = true;
aeb.Start = true;
m_EventBroker->Publish(aeb);
}
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.NodeName = "StandCrouchBlend";
aeb.RootNode = playerModel;
aeb.Delay = -0.3;
aeb.Start = true;
aeb.Restart = false;
aeb.AnimationEntity = playerModel.FirstChildByName("DashForward");
m_EventBroker->Publish(aeb);
}
} else {
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.NodeName = "DashLeft";
aeb.RootNode = playerModel;
aeb.Restart = true;
aeb.Start = true;
m_EventBroker->Publish(aeb);
}
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.NodeName = "StandCrouchBlend";
aeb.RootNode = playerModel;
aeb.Delay = -0.3;
aeb.Start = true;
aeb.Restart = false;
aeb.AnimationEntity = playerModel.FirstChildByName("DashForward");
m_EventBroker->Publish(aeb);
}
}
} else {
if (controller->Movement().z < 0) {
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.NodeName = "DashForward";
aeb.RootNode = playerModel;
aeb.Restart = true;
aeb.Start = true;
m_EventBroker->Publish(aeb);
}
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.NodeName = "StandCrouchBlend";
aeb.RootNode = playerModel;
aeb.Delay = -0.3;
aeb.Start = true;
aeb.Restart = false;
aeb.AnimationEntity = playerModel.FirstChildByName("DashForward");
m_EventBroker->Publish(aeb);
}
} else {
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.NodeName = "DashBackward";
aeb.RootNode = playerModel;
aeb.Restart = true;
aeb.Start = true;
m_EventBroker->Publish(aeb);
}
{
Events::AutoAnimationBlend aeb;
aeb.Duration = 0.3;
aeb.NodeName = "StandCrouchBlend";
aeb.RootNode = playerModel;
aeb.Delay = -0.3;
aeb.Start = true;
aeb.Restart = false;
aeb.AnimationEntity = playerModel.FirstChildByName("DashForward");
m_EventBroker->Publish(aeb);
}
}
}
}
}
}
/*
auto playerEntityAnimation = playerModel["Animation"];
playerEntityModel.Copy(dashEffect["Model"]);
playerEntityAnimation.Copy(dashEffect["Animation"]);
dashEffect["ExplosionEffect"]["EndColor"] = (glm::vec4)playerEntityModel["Color"];
((glm::vec4&)dashEffect["ExplosionEffect"]["EndColor"]).w = 0.f;
dashEffect["Animation"]["Speed1"] = 0.0;
dashEffect["Animation"]["Speed2"] = 0.0;
dashEffect["Animation"]["Speed3"] = 0.0;
dashEffect["Transform"]["Position"] = (glm::vec3)player["Transform"]["Position"];
dashEffect["Transform"]["Orientation"] = (glm::vec3)player["Transform"]["Orientation"];
*/
return true;
}
+14 -5
View File
@@ -105,7 +105,7 @@ void PlayerSpawnSystem::Update(double dt)
bool PlayerSpawnSystem::OnInputCommand(Events::InputCommand& e)
{
if (e.Command != "PickTeam") {
if (e.Command != "PickTeam" && e.Command != "SwapToClassPick") {
return false;
}
@@ -113,11 +113,12 @@ bool PlayerSpawnSystem::OnInputCommand(Events::InputCommand& e)
return false;
}
// A dead client should be able to swap to the spectator camera.
// A dead client should be able to swap to the overwatch camera.
if (IsClient && !LocalPlayer.Valid()) {
// Set the spectator camera as active, if it exists.
// Find the camera.
EntityWrapper spectatorCam = m_World->GetFirstEntityByName("SpectatorCamera");
// Set the camera as active, if it exists.
// Find the respawn camera or class pick camera.
std::string camName = e.Command == "SwapToClassPick" ? "PickClassCamera" : "SpectatorCamera";
EntityWrapper spectatorCam = m_World->GetFirstEntityByName(camName);
if (spectatorCam.Valid() && spectatorCam.HasComponent("Camera")) {
Events::SetCamera eSetCamera;
eSetCamera.CameraEntity = spectatorCam;
@@ -135,10 +136,18 @@ bool PlayerSpawnSystem::OnInputCommand(Events::InputCommand& e)
auto iter = m_SpawnRequests.begin();
for (; iter != m_SpawnRequests.end(); ++iter) {
if (iter->PlayerID == e.PlayerID) {
// If player wants to switch class, remove their spawn request.
if (e.Command == "SwapToClassPick") {
m_SpawnRequests.erase(iter);
}
break;
}
}
if (e.Command == "SwapToClassPick") {
return true;
}
if (iter != m_SpawnRequests.end()) {
// If player is in queue to spawn, then change their team affiliation in the request.
iter->Team = (ComponentInfo::EnumType)e.Value;
+158
View File
@@ -0,0 +1,158 @@
#include "Game/Systems/ScoreScreenSystem.h"
ScoreScreenSystem::ScoreScreenSystem(SystemParams params)
: System(params)
, PureSystem("ScoreScreen")
{
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDeath, &ScoreScreenSystem::OnPlayerDeath);
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &ScoreScreenSystem::OnPlayerSpawn);
EVENT_SUBSCRIBE_MEMBER(m_EPlayerConnected, &ScoreScreenSystem::OnPlayerConnected);
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDisconnected, &ScoreScreenSystem::OnPlayerDisconnected);
}
void ScoreScreenSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& scoreScreen, double dt)
{
if (!IsServer) {
return;
}
if(!entity.HasComponent("ScoreScreen")){
return;
}
int currentTeam = 0;
if(entity.HasComponent("Team")) {
currentTeam = (int)entity["Team"]["Team"];
} else {
return;
}
auto children = entity.ChildrenWithComponent("ScoreIdentity");
float position = 0.f;
for (auto it = m_PlayerIdentities.begin(); it != m_PlayerIdentities.end(); ++it) {
bool found = false;
for (auto& child : children) {
int ID = (int)child["ScoreIdentity"]["ID"];
if (it->first == ID) {
if (it->second.Team != currentTeam) {
m_World->DeleteEntity(child.ID);
(int&)entity["ScoreScreen"]["TotalIdentities"] -= 1;
break;
}
for (auto it2 = m_DisconnectedIdentities.begin(); it2 != m_DisconnectedIdentities.end(); ++it2) {
if (ID == *it2) {
m_World->DeleteEntity(child.ID);
(int&)entity["ScoreScreen"]["TotalIdentities"] -= 1;
it2 = m_DisconnectedIdentities.erase(it2);
it = m_PlayerIdentities.erase(it);
//Remove from m_playerIdentities
break;
}
}
found = true;
if(!child.Valid()) {
break;
}
//Update Deaths for child
(int&)child["ScoreIdentity"]["Kills"] = it->second.Kills;
//Update Kills for child
(int&)child["ScoreIdentity"]["Deaths"] = it->second.Deaths;
//KD is not updated at the moment.
if (it->second.Deaths != 0) {
(double&)child["ScoreIdentity"]["KD"] = it->second.Kills/it->second.Deaths;
}
//Update position for child
glm::vec3 offset = (glm::vec3)entity["ScoreScreen"]["Offset"];
(glm::vec3&) child["Transform"]["Position"] = offset * position;
position += 1.f;
break;
}
}
if (it == m_PlayerIdentities.end()) {
break;
}
if(found == false) {
if(it->second.Team != currentTeam) {
//This player is not the same team as this scoreboard should show.
continue;
}
//There is no entry for this player, create one.
auto entityFile = ResourceManager::Load<EntityFile>("Schema/Entities/ScoreIdentity.xml");
EntityWrapper scoreIdentity = entityFile->MergeInto(m_World);
glm::vec3 offset = (glm::vec3)entity["ScoreScreen"]["Offset"];
int newPosition = (int)entity["ScoreScreen"]["TotalIdentities"];
(glm::vec3&) scoreIdentity["Transform"]["Position"] = offset * (float)newPosition;
auto cScoreIdentity = scoreIdentity["ScoreIdentity"];
auto data = it->second;
(std::string&)cScoreIdentity["Name"] = data.Name;
(int&)cScoreIdentity["ID"] = data.ID;
m_World->SetParent(scoreIdentity.ID, entity.ID);
(int&)entity["ScoreScreen"]["TotalIdentities"] += 1;
}
}
//Local player should have an icon, compare with LocalPlayer somthing
}
bool ScoreScreenSystem::OnPlayerDeath(const Events::KillDeath& e)
{
//When player die, add it to his score, and when possible the player who killed him.
std::unordered_map<int, PlayerData>::iterator got;
got = m_PlayerIdentities.find(e.Casualty);
if(got != m_PlayerIdentities.end()) {
got->second.Deaths++;
}
got = m_PlayerIdentities.find(e.Killer);
if (got != m_PlayerIdentities.end()) {
got->second.Kills++;
}
return 0;
}
bool ScoreScreenSystem::OnPlayerSpawn(const Events::PlayerSpawned& e)
{
//When a player spawn, add data to the list entry with the same ID.
std::unordered_map<int, PlayerData>::iterator got;
got = m_PlayerIdentities.find(e.PlayerID);
if(got == m_PlayerIdentities.end()) {
LOG_ERROR("Player spawned without having an entry on score screen");
return 0;
}
auto& data = got->second;
data.Player = e.Player;
data.Team = (int)data.Player["Team"]["Team"];
return 0;
}
bool ScoreScreenSystem::OnPlayerConnected(const Events::PlayerConnected& e)
{
//player has connected, add his data to the list of ScoreIdentities
PlayerData data;
data.ID = e.PlayerID;
data.Name = e.PlayerName;
m_PlayerIdentities.insert( {data.ID, data} );
return 0;
}
bool ScoreScreenSystem::OnPlayerDisconnected(const Events::PlayerDisconnected& e)
{
//player has disconnected, remove him from list of ScoreIdentities
m_DisconnectedIdentities.push_back(e.PlayerID);
return 0;
}
+54
View File
@@ -0,0 +1,54 @@
#include "Game/Systems/TextFieldReader.h"
void TextFieldReader::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cAmmunitionHUD, double dt)
{
if (!entity.HasComponent("Text")) {
return;
}
// Find the entity to read from
const std::string& parentEntityName = cAmmunitionHUD["ParentEntityName"];
EntityWrapper readEntity = entity;
if (!parentEntityName.empty()) {
readEntity = entity.FirstParentByName(parentEntityName);
if (!readEntity.Valid()) {
return;
}
}
// Find the component to read from
const std::string& componentType = cAmmunitionHUD["ComponentType"];
if (componentType.empty() || !readEntity.HasComponent(componentType)) {
return;
}
ComponentWrapper component = readEntity[componentType];
// Find the field to read from
const std::string& fieldName = cAmmunitionHUD["Field"];
if (fieldName.empty() || component.Info.Fields.count(fieldName) == 0) {
return;
}
const ComponentInfo::Field_t& field = component.Info.Fields.at(fieldName);
std::string& text = entity["Text"]["Content"];
if (field.Type == "int") {
text = boost::lexical_cast<std::string>((const int&)component[fieldName]);
} else if (field.Type == "float") {
std::ostringstream ss;
float f = (float)component[fieldName];
ss << std::fixed << std::setprecision(2);
ss << f;
text = ss.str();
} else if (field.Type == "double") {
std::ostringstream ss;
double d = (double)component[fieldName];
ss << std::fixed << std::setprecision(1);
ss << d;
text = ss.str();
} else if (field.Type == "bool") {
text = boost::lexical_cast<std::string>((const bool&)component[fieldName]);
} else if (field.Type == "string") {
text = (const std::string&)component[fieldName];
}
}
@@ -0,0 +1,295 @@
#include "Systems/Weapon/AssaultWeaponBehaviour.h"
void AssaultWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt)
{
double& fireCooldown = cWeapon["FireCooldown"];
fireCooldown = glm::max(0.0, fireCooldown - dt);
WeaponBehaviour::UpdateComponent(entity, cWeapon, dt);
}
void AssaultWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt)
{
// Start reloading automatically if at 0 mag ammo
int& magAmmo = cWeapon["MagazineAmmo"];
if (m_ConfigAutoReload && magAmmo <= 0) {
OnReload(cWeapon, wi);
}
// Only start reloading once we're done firing
bool& reloadQueued = cWeapon["ReloadQueued"];
double& fireCooldown = cWeapon["FireCooldown"];
bool& isReloading = cWeapon["IsReloading"];
if (reloadQueued && fireCooldown <= 0) {
reloadQueued = fireCooldown;
isReloading = true;
}
// Decrement reload timer
double& reloadTimer = cWeapon["ReloadTimer"];
if (isReloading) {
reloadTimer = glm::max(0.0, reloadTimer - dt);
}
// Handle reloading
if (isReloading && reloadTimer <= 0.0) {
int& magSize = cWeapon["MagazineSize"];
int& ammo = cWeapon["Ammo"];
ammo = glm::max(0, ammo - (magSize - magAmmo));
magAmmo = glm::min(magSize, ammo);
isReloading = false;
if (wi.FirstPersonEntity.Valid()) {
wi.FirstPersonEntity["Model"]["Visible"] = true;
}
if (wi.ThirdPersonEntity.Valid()) {
wi.ThirdPersonEntity["Model"]["Visible"] = true;
}
}
// Restore view angle
if (IsClient) {
float& currentTravel = cWeapon["CurrentTravel"];
float& returnSpeed = cWeapon["ViewReturnSpeed"];
if (currentTravel > 0) {
float change = returnSpeed * dt;
currentTravel = glm::max(0.f, currentTravel - change);
EntityWrapper camera = wi.Player.FirstChildByName("Camera");
if (camera.Valid()) {
glm::vec3& cameraOrientation = camera["Transform"]["Orientation"];
cameraOrientation.x -= change;
}
}
}
// Update first person run animation
ComponentWrapper cPlayer = wi.Player["Player"];
ComponentWrapper cPhysics = wi.Player["Physics"];
const float& movementSpeed = cPlayer["MovementSpeed"];
float speed = glm::length((const glm::vec3&)cPhysics["Velocity"]);
float animationWeight = glm::min(speed, movementSpeed) / movementSpeed;
EntityWrapper rootNode = wi.FirstPersonEntity.FirstParentWithComponent("Model");
if (rootNode.Valid()) {
EntityWrapper blend = rootNode.FirstChildByName("MovementBlend");
if (blend.Valid()) {
(double&)blend["Blend"]["Weight"] = animationWeight;
}
}
// Fire if we're able to fire
if (canFire(cWeapon, wi)) {
fireBullet(cWeapon, wi);
}
}
void AssaultWeaponBehaviour::OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi)
{
cWeapon["TriggerHeld"] = true;
if (canFire(cWeapon, wi)) {
fireBullet(cWeapon, wi);
}
}
void AssaultWeaponBehaviour::OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi)
{
cWeapon["TriggerHeld"] = false;
}
void AssaultWeaponBehaviour::OnReload(ComponentWrapper cWeapon, WeaponInfo& wi)
{
bool& reloadQueued = cWeapon["ReloadQueued"];
bool& isReloading = cWeapon["IsReloading"];
if (reloadQueued || isReloading) {
return;
}
int& magAmmo = cWeapon["MagazineAmmo"];
int& magSize = cWeapon["MagazineSize"];
if (magAmmo >= magSize) {
return;
}
int& ammo = cWeapon["Ammo"];
if (ammo <= 0) {
return;
}
double reloadTime = cWeapon["ReloadTime"];
double& reloadTimer = cWeapon["ReloadTimer"];
// Start reload
reloadQueued = true;
reloadTimer = reloadTime;
// Play animation
playAnimationAndReturn(wi.FirstPersonEntity, "BlendTreeAssaultWeapon", "Reload");
if (IsClient) {
// Spawn explosion effect
EntityWrapper reloadEffectSpawner = wi.FirstPersonEntity.FirstChildByName("FirstPersonReloadSpawner");
if (reloadEffectSpawner.Valid()) {
SpawnerSystem::Spawn(reloadEffectSpawner, reloadEffectSpawner);
}
if (wi.FirstPersonEntity.Valid()) {
wi.FirstPersonEntity["Model"]["Visible"] = false;
}
if (wi.ThirdPersonEntity.Valid()) {
wi.ThirdPersonEntity["Model"]["Visible"] = false;
}
}
// Sound
Events::PlaySoundOnEntity e;
e.EmitterID = wi.Player.ID;
e.FilePath = "Audio/weapon/Assault/AssaultWeaponReload.wav";
m_EventBroker->Publish(e);
}
void AssaultWeaponBehaviour::OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi)
{
cWeapon["FireCooldown"] = (double)cWeapon["EquipTime"];
}
void AssaultWeaponBehaviour::OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi)
{
// Make sure the trigger is released if weapon is holstered while firing
cWeapon["TriggerHeld"] = false;
// Cancel any reload
cWeapon["IsReloading"] = false;
cWeapon["ReloadTimer"] = 0.0;
}
void AssaultWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi)
{
cWeapon["FireCooldown"] = 60.0 / (double)cWeapon["RPM"];
// Ammo
int& magAmmo = cWeapon["MagazineAmmo"];
if (magAmmo <= 0) {
return;
} else {
magAmmo -= 1;
}
// View punch
if (IsClient) {
EntityWrapper camera = wi.Player.FirstChildByName("Camera");
if (camera.Valid()) {
glm::vec3& cameraOrientation = camera["Transform"]["Orientation"];
float viewPunch = cWeapon["ViewPunch"];
float maxTravelAngle = cWeapon["MaxTravelAngle"];
float& currentTravel = cWeapon["CurrentTravel"];
if (currentTravel < maxTravelAngle) {
float change = viewPunch;
if (currentTravel + change > maxTravelAngle) {
change = maxTravelAngle - currentTravel;
}
cameraOrientation.x += change;
currentTravel += change;
}
}
}
// Get weapon model based on current person
EntityWrapper weaponModelEntity = getRelevantWeaponModelEntity(wi);
if (!weaponModelEntity.Valid()) {
return;
}
// Tracer
EntityWrapper tracerSpawner = weaponModelEntity.FirstChildByName("WeaponMuzzle");
if (tracerSpawner.Valid()) {
glm::vec3 origin = Transform::AbsolutePosition(tracerSpawner);
glm::vec3 direction = glm::quat(Transform::AbsoluteOrientationEuler(tracerSpawner)) * glm::vec3(0, 0, -1);
float distance = traceRayDistance(origin, direction);
EntityWrapper ray = SpawnerSystem::Spawn(tracerSpawner);
if (ray.Valid()) {
((glm::vec3&)ray["Transform"]["Scale"]).z = distance;
}
}
// Deal damage
if (dealDamage(cWeapon, wi)) {
// Show hit marker
EntityWrapper hitMarkerSpawner = wi.Player.FirstChildByName("HitMarkerSpawner");
if (hitMarkerSpawner.Valid()) {
SpawnerSystem::Spawn(hitMarkerSpawner, hitMarkerSpawner);
Events::PlaySoundOnEntity e;
e.EmitterID = wi.Player.ID;
e.FilePath = "Audio/weapon/hitclick.wav";
m_EventBroker->Publish(e);
}
}
// Play animation
playAnimationAndReturn(wi.FirstPersonEntity, "BlendTreeAssaultWeapon", "Fire");
// Sound
Events::PlaySoundOnEntity e;
e.EmitterID = wi.Player.ID;
e.FilePath = "Audio/weapon/Assault/AssaultWeaponFire.wav";
m_EventBroker->Publish(e);
}
bool AssaultWeaponBehaviour::canFire(ComponentWrapper cWeapon, WeaponInfo& wi)
{
bool triggerHeld = cWeapon["TriggerHeld"];
bool cooldownPassed = (double)cWeapon["FireCooldown"] <= 0.0;
bool isNotReloading = !(bool)cWeapon["IsReloading"];
return triggerHeld && cooldownPassed && isNotReloading;
}
bool AssaultWeaponBehaviour::dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi)
{
// Only deal damage client side
if (!IsClient) {
return false;
}
// Only handle damage for the local player
if (wi.Player != LocalPlayer) {
return false;
}
// Make sure the player isn't shooting from the grave
if (!wi.Player.Valid()) {
return false;
}
// 3D-pick middle of screen
Rectangle viewport = m_Renderer->GetViewportSize();
glm::vec2 centerScreen(viewport.Width / 2, viewport.Height / 2);
// TODO: Some horizontal spread
PickData pickData = m_Renderer->Pick(centerScreen);
EntityWrapper victim(m_World, pickData.Entity);
if (!victim.Valid()) {
return false;
}
// Don't let us somehow shoot ourselves in the foot
if (victim == LocalPlayer) {
return false;
}
// Only care about players being hit
if (!victim.HasComponent("Player")) {
victim = victim.FirstParentWithComponent("Player");
}
if (!victim.Valid()) {
return false;
}
double damage = cWeapon["BaseDamage"];
// If friendly fire, reduce damage to 0 (needed to make Boosts, Ammosharing work)
if ((ComponentInfo::EnumType)victim["Team"]["Team"] == (ComponentInfo::EnumType)wi.Player["Team"]["Team"]) {
damage = 0;
}
// Deal damage!
Events::PlayerDamage ePlayerDamage;
ePlayerDamage.Inflictor = wi.Player;
ePlayerDamage.Victim = victim;
ePlayerDamage.Damage = damage;
m_EventBroker->Publish(ePlayerDamage);
return damage > 0;
}
@@ -2,48 +2,157 @@
void DefenderWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt)
{
(double&)cWeapon["TimeSinceLastFire"] += dt;
double& fireCooldown = cWeapon["FireCooldown"];
fireCooldown = glm::max(0.0, fireCooldown - dt);
WeaponBehaviour::UpdateComponent(entity, cWeapon, dt);
}
void DefenderWeaponBehaviour::UpdateWeapon(WeaponInfo& wi, double dt)
void DefenderWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt)
{
ComponentWrapper cWeapon = wi.GetComponent();
// Decrement reload timer
double& reloadTimer = cWeapon["ReloadTimer"];
reloadTimer = glm::max(0.0, reloadTimer - dt);
bool isFiring = cWeapon["IsFiring"];
bool cooldownPassed = (double)cWeapon["TimeSinceLastFire"] >= (60.0 / (double)cWeapon["RPM"]);
bool isNotShielding = wi.Player.ChildrenWithComponent("Shield").size() == 0;
if (isFiring && cooldownPassed && isNotShielding) {
fireShell(wi);
// Start reloading automatically if at 0 mag ammo
int& magAmmo = cWeapon["MagazineAmmo"];
if (m_ConfigAutoReload && magAmmo <= 0) {
OnReload(cWeapon, wi);
}
// Handle reloading
bool& isReloading = cWeapon["IsReloading"];
if (isReloading && reloadTimer <= 0.0) {
double reloadTime = cWeapon["ReloadTime"];
int& magSize = cWeapon["MagazineSize"];
int& ammo = cWeapon["Ammo"];
if (magAmmo < magSize && ammo > 0) {
ammo -= 1;
magAmmo += 1;
reloadTimer = reloadTime;
Events::PlaySoundOnEntity e;
e.EmitterID = wi.Player.ID;
e.FilePath = "Audio/weapon/Zoom.wav";
m_EventBroker->Publish(e);
} else {
isReloading = false;
playAnimationAndReturn(wi.FirstPersonEntity, "FinalBlend", "Idle");
}
}
// Restore view angle
if (IsClient) {
float& currentTravel = cWeapon["CurrentTravel"];
float& returnSpeed = cWeapon["ViewReturnSpeed"];
if (currentTravel > 0) {
float change = returnSpeed * dt;
currentTravel = glm::max(0.f, currentTravel - change);
EntityWrapper camera = wi.Player.FirstChildByName("Camera");
if (camera.Valid()) {
glm::vec3& cameraOrientation = camera["Transform"]["Orientation"];
cameraOrientation.x -= change;
}
}
}
// Fire if we're able to fire
if (canFire(cWeapon, wi)) {
fireShell(cWeapon, wi);
}
}
void DefenderWeaponBehaviour::OnPrimaryFire(WeaponInfo& wi)
void DefenderWeaponBehaviour::OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi)
{
ComponentWrapper cWeapon = wi.GetComponent();
cWeapon["IsFiring"] = true;
bool cooldownPassed = (double)cWeapon["TimeSinceLastFire"] >= (60.0 / (double)cWeapon["RPM"]);
bool isNotShielding = wi.Player.ChildrenWithComponent("Shield").size() == 0;
if (cooldownPassed && isNotShielding) {
fireShell(wi);
cWeapon["TriggerHeld"] = true;
if (canFire(cWeapon, wi)) {
fireShell(cWeapon, wi);
}
}
void DefenderWeaponBehaviour::OnCeasePrimaryFire(WeaponInfo& wi)
void DefenderWeaponBehaviour::OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi)
{
ComponentWrapper cWeapon = wi.GetComponent();
cWeapon["IsFiring"] = false;
cWeapon["TriggerHeld"] = false;
}
bool DefenderWeaponBehaviour::OnInputCommand(WeaponInfo& wi, const Events::InputCommand& e)
void DefenderWeaponBehaviour::OnReload(ComponentWrapper cWeapon, WeaponInfo& wi)
{
bool& isReloading = cWeapon["IsReloading"];
if (isReloading) {
return;
}
int& magAmmo = cWeapon["MagazineAmmo"];
int& magSize = cWeapon["MagazineSize"];
if (magAmmo >= magSize) {
return;
}
int& ammo = cWeapon["Ammo"];
if (ammo <= 0) {
return;
}
double reloadTime = cWeapon["ReloadTime"];
double& reloadTimer = cWeapon["ReloadTimer"];
// Start reload
isReloading = true;
reloadTimer = reloadTime;
// Play animation
playAnimationAndReturn(wi.FirstPersonEntity, "FinalBlend", "Reload");
}
void DefenderWeaponBehaviour::OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi)
{
// Make sure the trigger is released if weapon is holstered while firing
cWeapon["TriggerHeld"] = false;
// Cancel any reload
cWeapon["IsReloading"] = false;
cWeapon["ReloadTimer"] = 0.0;
}
bool DefenderWeaponBehaviour::OnInputCommand(ComponentWrapper cWeapon, WeaponInfo& wi, const Events::InputCommand& e)
{
if (e.Command == "SpecialAbility" && IsServer) {
EntityWrapper attachment = wi.Player.FirstChildByName("ShieldAttachment");
if (attachment.Valid()) {
if (e.Value > 0) {
SpawnerSystem::Spawn(attachment, attachment);
EntityWrapper root = wi.FirstPersonEntity.FirstParentWithComponent("Model");
if (root.Valid()) {
EntityWrapper subTree = root.FirstChildByName("FinalBlend");
if (subTree.Valid()) {
EntityWrapper animationNode = subTree.FirstChildByName("Shield");
if (animationNode.Valid()) {
Events::AutoAnimationBlend eFireBlend;
eFireBlend.RootNode = root;
eFireBlend.NodeName = "Shield";
eFireBlend.Restart = true;
eFireBlend.Start = true;
m_EventBroker->Publish(eFireBlend);
}
}
}
} else {
attachment.DeleteChildren();
EntityWrapper root = wi.FirstPersonEntity.FirstParentWithComponent("Model");
if (root.Valid()) {
EntityWrapper subTree = root.FirstChildByName("FinalBlend");
if (subTree.Valid()) {
EntityWrapper animationNode = subTree.FirstChildByName("ActionBlend");
if (animationNode.Valid()) {
Events::AutoAnimationBlend eFireBlend;
eFireBlend.RootNode = root;
eFireBlend.NodeName = "ActionBlend";
eFireBlend.Restart = true;
eFireBlend.Start = true;
m_EventBroker->Publish(eFireBlend);
}
}
}
}
}
}
@@ -51,17 +160,22 @@ bool DefenderWeaponBehaviour::OnInputCommand(WeaponInfo& wi, const Events::Input
return false;
}
bool DefenderWeaponBehaviour::OnSetCamera(const Events::SetCamera& e)
void DefenderWeaponBehaviour::fireShell(ComponentWrapper cWeapon, WeaponInfo& wi)
{
m_CurrentCamera = e.CameraEntity;
return true;
}
cWeapon["FireCooldown"] = 60.0 / (double)cWeapon["RPM"];
void DefenderWeaponBehaviour::fireShell(WeaponInfo& wi)
{
ComponentWrapper cWeapon = wi.GetComponent();
// Stop reloading
bool& isReloading = cWeapon["IsReloading"];
isReloading = false;
// Ammo
int& magAmmo = cWeapon["MagazineAmmo"];
if (magAmmo <= 0) {
return;
} else {
magAmmo -= 1;
}
cWeapon["TimeSinceLastFire"] = 0.0;
int numPellets = cWeapon["NumPellets"];
float spreadAngle = cWeapon["SpreadAngle"];
std::uniform_real_distribution<float> randomSpreadAngle(-spreadAngle, spreadAngle);
@@ -72,11 +186,29 @@ void DefenderWeaponBehaviour::fireShell(WeaponInfo& wi)
std::vector<glm::vec2> pelletAngles;
for (int i = 0; i < numPellets; i++) {
pelletAngles.push_back(glm::vec2(randomSpreadAngle(m_RandomEngine), randomSpreadAngle(m_RandomEngine)));
LOG_DEBUG("%f %f", pelletAngles[i].x, pelletAngles[i].y);
}
double pelletDamage = (double)cWeapon["BaseDamage"] / numPellets;
// View punch
if (IsClient) {
EntityWrapper camera = wi.Player.FirstChildByName("Camera");
if (camera.Valid()) {
glm::vec3& cameraOrientation = camera["Transform"]["Orientation"];
float viewPunch = cWeapon["ViewPunch"];
float maxTravelAngle = cWeapon["MaxTravelAngle"];
float& currentTravel = cWeapon["CurrentTravel"];
if (currentTravel < maxTravelAngle) {
float change = viewPunch;
if (currentTravel + change > maxTravelAngle) {
change = maxTravelAngle - currentTravel;
}
cameraOrientation.x += change;
currentTravel += change;
}
}
}
// Tracers
EntityWrapper weaponModelEntity;
if (wi.Player == LocalPlayer) {
@@ -95,13 +227,21 @@ void DefenderWeaponBehaviour::fireShell(WeaponInfo& wi)
orientation.x += angles.x;
orientation.y += angles.y;
glm::vec3 trajectory = direction * distance;
dealDamage(wi, direction, pelletDamage);
dealDamage(cWeapon, wi, direction, pelletDamage);
}
}
// Play animation
playAnimationAndReturn(wi.FirstPersonEntity, "BlendTreeDefenderWeapon", "Fire");
// Sound
Events::PlaySoundOnEntity e;
e.EmitterID = wi.Player.ID;
e.FilePath = "Audio/weapon/Blast.wav";
m_EventBroker->Publish(e);
}
void DefenderWeaponBehaviour::dealDamage(WeaponInfo& wi, glm::vec3 direction, double damage)
void DefenderWeaponBehaviour::dealDamage(ComponentWrapper cWeapon, WeaponInfo& wi, glm::vec3 direction, double damage)
{
// Only deal damage client side
if (!IsClient) {
@@ -160,16 +300,12 @@ void DefenderWeaponBehaviour::dealDamage(WeaponInfo& wi, glm::vec3 direction, do
LOG_DEBUG("Damage: %f", damage);
}
float DefenderWeaponBehaviour::traceRayDistance(glm::vec3 origin, glm::vec3 direction)
bool DefenderWeaponBehaviour::canFire(ComponentWrapper cWeapon, WeaponInfo& wi)
{
float distance;
glm::vec3 pos;
auto entity = Collision::EntityFirstHitByRay(Ray(origin, direction), m_CollisionOctree, distance, pos);
if (entity) {
return distance;
} else {
return 100.f;
}
bool triggerHeld = cWeapon["TriggerHeld"];
bool cooldownPassed = (double)cWeapon["FireCooldown"] <= 0.0;
bool isNotShielding = wi.Player.ChildrenWithComponent("Shield").size() == 0;
return triggerHeld && cooldownPassed && isNotShielding;
}
Camera DefenderWeaponBehaviour::cameraFromEntity(EntityWrapper camera)
@@ -0,0 +1,77 @@
#include "Systems/Weapon/SidearmWeaponBehaviour.h"
void SidearmWeaponBehaviour::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cWeapon, double dt)
{
double& cooldown = cWeapon["FireCooldown"];
if (cooldown > 0) {
cooldown -= dt;
if (cooldown < 0) {
cooldown = 0;
}
}
WeaponBehaviour::UpdateComponent(entity, cWeapon, dt);
}
void SidearmWeaponBehaviour::UpdateWeapon(ComponentWrapper cWeapon, WeaponInfo& wi, double dt)
{
if ((bool)cWeapon["Automatic"] && canFire(cWeapon)) {
fireBullet(cWeapon, wi);
}
}
void SidearmWeaponBehaviour::OnPrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi)
{
cWeapon["TriggerHeld"] = true;
if (canFire(cWeapon)) {
fireBullet(cWeapon, wi);
}
}
void SidearmWeaponBehaviour::OnCeasePrimaryFire(ComponentWrapper cWeapon, WeaponInfo& wi)
{
cWeapon["TriggerHeld"] = false;
}
void SidearmWeaponBehaviour::OnEquip(ComponentWrapper cWeapon, WeaponInfo& wi)
{
cWeapon["FireCooldown"] = (double)cWeapon["EquipTime"];
}
void SidearmWeaponBehaviour::OnHolster(ComponentWrapper cWeapon, WeaponInfo& wi)
{
// Make sure the trigger is released if weapon is holstered while firing
cWeapon["TriggerHeld"] = false;
// Cancel any reload
cWeapon["IsReloading"] = false;
cWeapon["ReloadTimer"] = 0.0;
}
void SidearmWeaponBehaviour::fireBullet(ComponentWrapper cWeapon, WeaponInfo& wi)
{
cWeapon["FireCooldown"] = 60.0 / (double)cWeapon["RPM"];
// Get weapon model based on current person
EntityWrapper weaponModelEntity = getRelevantWeaponModelEntity(wi);
if (!weaponModelEntity.Valid()) {
return;
}
// Tracer
EntityWrapper tracerSpawner = weaponModelEntity.FirstChildByName("WeaponMuzzle");
if (tracerSpawner.Valid()) {
glm::vec3 origin = Transform::AbsolutePosition(tracerSpawner);
glm::vec3 direction = Transform::AbsoluteOrientation(tracerSpawner) * glm::vec3(0, 0, -1);
float distance = traceRayDistance(origin, direction);
EntityWrapper ray = SpawnerSystem::Spawn(tracerSpawner);
((glm::vec3&)ray["Transform"]["Scale"]).z = (distance / 100.f);
}
}
bool SidearmWeaponBehaviour::canFire(ComponentWrapper cWeapon)
{
bool triggerHeld = cWeapon["TriggerHeld"];
double& cooldown = cWeapon["FireCooldown"];
// TODO: Ammo checks
return triggerHeld && cooldown <= 0.0;
}