Merge remote-tracking branch 'origin/master' into TCPConnections
This commit is contained in:
@@ -8,7 +8,7 @@ void CollidableOctreeSystem::Update(double dt)
|
||||
void CollidableOctreeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
||||
{
|
||||
if (entity.HasComponent("AABB")) {
|
||||
boost::optional<AABB> absoluteAABB = Collision::EntityAbsoluteAABB(entity);
|
||||
boost::optional<EntityAABB> absoluteAABB = Collision::EntityAbsoluteAABB(entity);
|
||||
if (absoluteAABB) {
|
||||
m_Octree->AddDynamicObject(*absoluteAABB);
|
||||
}
|
||||
|
||||
@@ -239,20 +239,6 @@ bool AABBvsTriangles(const AABB& box, const std::vector<RawModel::Vertex>& model
|
||||
return hit;
|
||||
}
|
||||
|
||||
bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon)
|
||||
{
|
||||
const glm::vec3& ma1 = first.MaxCorner();
|
||||
const glm::vec3& ma2 = second.MaxCorner();
|
||||
const glm::vec3& mi1 = first.MinCorner();
|
||||
const glm::vec3& mi2 = second.MinCorner();
|
||||
return (std::abs(ma1.x - ma2.x) < epsilon) &&
|
||||
(std::abs(mi1.x - mi2.x) < epsilon) &&
|
||||
(std::abs(ma1.z - ma2.z) < epsilon) &&
|
||||
(std::abs(mi1.z - mi2.z) < epsilon) &&
|
||||
(std::abs(ma1.y - ma2.y) < epsilon) &&
|
||||
(std::abs(mi1.y - mi2.y) < epsilon);
|
||||
}
|
||||
|
||||
bool attachAABBComponentFromModel(World* world, EntityID id)
|
||||
{
|
||||
if (!world->HasComponent(id, "Model")) {
|
||||
@@ -283,7 +269,7 @@ bool attachAABBComponentFromModel(World* world, EntityID id)
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::optional<AABB> EntityAbsoluteAABB(EntityWrapper& entity)
|
||||
boost::optional<EntityAABB> EntityAbsoluteAABB(EntityWrapper& entity)
|
||||
{
|
||||
if (!entity.HasComponent("AABB")) {
|
||||
return boost::none;
|
||||
@@ -294,7 +280,11 @@ boost::optional<AABB> EntityAbsoluteAABB(EntityWrapper& entity)
|
||||
glm::vec3 absScale = Transform::AbsoluteScale(entity.World, entity.ID);
|
||||
glm::vec3 origin = absPosition + (glm::vec3)cAABB["Origin"];
|
||||
glm::vec3 size = (glm::vec3)cAABB["Size"] * absScale;
|
||||
return AABB::FromOriginSize(origin, size);
|
||||
|
||||
EntityAABB aabb = EntityAABB::FromOriginSize(origin, size);
|
||||
aabb.Entity = entity;
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,29 +9,27 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
|
||||
}
|
||||
ComponentWrapper& cPhysics = entity["Physics"];
|
||||
|
||||
boost::optional<AABB> boundingBox = Collision::EntityAbsoluteAABB(entity);
|
||||
boost::optional<EntityAABB> boundingBox = Collision::EntityAbsoluteAABB(entity);
|
||||
if (!boundingBox) {
|
||||
return;
|
||||
}
|
||||
ComponentWrapper& cTransform = entity["Transform"];
|
||||
AABB& boxA = *boundingBox;
|
||||
EntityAABB& boxA = *boundingBox;
|
||||
|
||||
//Press 'Z' to enable/disable collision.
|
||||
if (zPress) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Collide against octree
|
||||
std::vector<AABB> octreeResult;
|
||||
m_Octree->ObjectsInSameRegion(*boundingBox, octreeResult);
|
||||
for (auto& boxB : octreeResult) {
|
||||
// Collide against octree items
|
||||
m_OctreeResult.clear();
|
||||
m_Octree->ObjectsInSameRegion(*boundingBox, m_OctreeResult);
|
||||
for (auto& boxB : m_OctreeResult) {
|
||||
glm::vec3 resolutionVector;
|
||||
if (Collision::IsSameBoxProbably(boxA, boxB)) {
|
||||
if (boxA.Entity == boxB.Entity) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) {
|
||||
(glm::vec3&)cTransform["Position"] += resolutionVector;
|
||||
((glm::vec3&)cPhysics["Velocity"]).y = 0.f;
|
||||
if (resolutionVector.y > 0) {
|
||||
((glm::vec3&)cPhysics["Velocity"]).y = 0.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,12 +54,4 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
|
||||
// (glm::vec3&)cTransform["Position"] += resolutionVector;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
bool CollisionSystem::OnKeyUp(const Events::KeyUp & event)
|
||||
{
|
||||
if (event.KeyCode == GLFW_KEY_Z) {
|
||||
zPress = !zPress;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,79 +3,72 @@
|
||||
#include "Core/AABB.h"
|
||||
#include "Rendering/Model.h"
|
||||
|
||||
void TriggerSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
||||
void TriggerSystem::UpdateComponent(EntityWrapper& triggerEntity, ComponentWrapper& cTrigger, double dt)
|
||||
{
|
||||
//Currently only players can trigger things.
|
||||
auto players = m_World->GetComponents("Player");
|
||||
if (players == nullptr) {
|
||||
return;
|
||||
}
|
||||
EntityID tId = component.EntityID;
|
||||
boost::optional<AABB> triggerBox = Collision::EntityAbsoluteAABB(entity);
|
||||
//The trigger *should* have a bounding box, or something, to test against so it can be triggered.
|
||||
// The trigger *should* have a bounding box, or something, to test against so it can be triggered.
|
||||
boost::optional<EntityAABB> triggerBox = Collision::EntityAbsoluteAABB(triggerEntity);
|
||||
if (!triggerBox) {
|
||||
return;
|
||||
}
|
||||
for (auto& pc : *players) {
|
||||
EntityID pId = pc.EntityID;
|
||||
boost::optional<AABB> playerBox = Collision::EntityAbsoluteAABB(EntityWrapper(m_World, pId));
|
||||
//The player can't trigger anything without an AABB.
|
||||
if (!playerBox) {
|
||||
continue;
|
||||
}
|
||||
if (!Collision::AABBVsAABB(*triggerBox, *playerBox)) {
|
||||
//Entity is not touching the trigger,
|
||||
//Throw event if it was previously.
|
||||
if (throwLeaveIfWasInTrigger(m_EntitiesTouchingTrigger[tId], pId, tId)) {
|
||||
continue;
|
||||
}
|
||||
//This only occurs if the entity was completely inside the trigger one frame,
|
||||
//then completely outside the trigger, e.g. when dying and respawning.
|
||||
throwLeaveIfWasInTrigger(m_EntitiesCompletelyInTrigger[tId], pId, tId);
|
||||
} else {
|
||||
//Entity is at least touching the trigger.
|
||||
|
||||
m_OctreeOut.clear();
|
||||
m_Octree->ObjectsInSameRegion(*triggerBox, m_OctreeOut);
|
||||
|
||||
for (EntityAABB& colliderBox : m_OctreeOut) {
|
||||
EntityWrapper colliderEntity = colliderBox.Entity;
|
||||
|
||||
if (Collision::AABBVsAABB(*triggerBox, colliderBox)) {
|
||||
AABB completelyInsideBox;
|
||||
bool playerFitsInTrigger = glm::all(glm::greaterThan((*triggerBox).Size(), (*playerBox).Size()));
|
||||
if (playerFitsInTrigger) {
|
||||
completelyInsideBox = AABB::FromOriginSize((*triggerBox).Origin(), (*triggerBox).Size() - 2.0f * (*playerBox).Size());
|
||||
bool colliderFitsInTrigger = glm::all(glm::greaterThan((*triggerBox).Size(), colliderBox.Size()));
|
||||
if (colliderFitsInTrigger) {
|
||||
completelyInsideBox = AABB::FromOriginSize((*triggerBox).Origin(), (*triggerBox).Size() - 2.0f * colliderBox.Size());
|
||||
}
|
||||
if (playerFitsInTrigger && Collision::AABBVsAABB(completelyInsideBox, *playerBox)) {
|
||||
//Entity is completely inside the trigger.
|
||||
//If it was only touching before, it is erased.
|
||||
m_EntitiesTouchingTrigger[tId].erase(pId);
|
||||
std::unordered_set<EntityID>& completeSet = m_EntitiesCompletelyInTrigger[tId];
|
||||
if (completeSet.count(pId) == 0) {
|
||||
//If it wasn't completely in the trigger, throw Enter and add to the set.
|
||||
completeSet.insert(pId);
|
||||
publish<Events::TriggerEnter>(pId, tId);
|
||||
if (colliderFitsInTrigger && Collision::AABBVsAABB(completelyInsideBox, colliderBox)) {
|
||||
// Entity is completely inside the trigger.
|
||||
// If it was only touching before, it is erased.
|
||||
m_EntitiesTouchingTrigger[triggerEntity].erase(colliderEntity);
|
||||
auto& completeSet = m_EntitiesCompletelyInTrigger[triggerEntity];
|
||||
if (completeSet.count(colliderEntity) == 0) {
|
||||
// If it wasn't completely in the trigger, throw Enter and add to the set.
|
||||
completeSet.insert(colliderEntity);
|
||||
publish<Events::TriggerEnter>(colliderEntity, triggerEntity);
|
||||
}
|
||||
} else {
|
||||
//Entity is only touching the trigger.
|
||||
std::unordered_set<EntityID>& touchSet = m_EntitiesTouchingTrigger[tId];
|
||||
std::unordered_set<EntityID>& completeSet = m_EntitiesCompletelyInTrigger[tId];
|
||||
const auto& it = completeSet.find(pId);
|
||||
// Entity is only touching the trigger.
|
||||
auto& touchSet = m_EntitiesTouchingTrigger[triggerEntity];
|
||||
auto& completeSet = m_EntitiesCompletelyInTrigger[triggerEntity];
|
||||
const auto& it = completeSet.find(colliderEntity);
|
||||
//If it was completely inside before.
|
||||
if (it != completeSet.end()) {
|
||||
completeSet.erase(it);
|
||||
touchSet.insert(pId);
|
||||
touchSet.insert(colliderEntity);
|
||||
//If it was completely outside before.
|
||||
} else if (touchSet.count(pId) == 0) {
|
||||
publish<Events::TriggerTouch>(pId, tId);
|
||||
touchSet.insert(pId);
|
||||
} else if (touchSet.count(colliderEntity) == 0) {
|
||||
publish<Events::TriggerTouch>(colliderEntity, triggerEntity);
|
||||
touchSet.insert(colliderEntity);
|
||||
}
|
||||
//Else, it was touching the trigger last frame too and nothing is done.
|
||||
// Else, it was touching the trigger last frame too and nothing is done.
|
||||
}
|
||||
} else {
|
||||
// Entity is not touching the trigger,
|
||||
// Throw event if it was previously.
|
||||
if (throwLeaveIfWasInTrigger(m_EntitiesTouchingTrigger[triggerEntity], colliderEntity, triggerEntity)) {
|
||||
continue;
|
||||
}
|
||||
// This only occurs if the entity was completely inside the trigger one frame,
|
||||
// then completely outside the trigger, e.g. when dying and respawning.
|
||||
throwLeaveIfWasInTrigger(m_EntitiesCompletelyInTrigger[triggerEntity], colliderEntity, triggerEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& triggerSet, EntityID pId, EntityID tId)
|
||||
bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set<EntityWrapper>& triggerSet, EntityWrapper colliderEntity, EntityWrapper triggerEntity)
|
||||
{
|
||||
const auto& it = triggerSet.find(pId);
|
||||
const auto& it = triggerSet.find(colliderEntity);
|
||||
if (it != triggerSet.end()) {
|
||||
//If it was in the trigger, but not anymore, throw leaveEvent and erase from the set.
|
||||
triggerSet.erase(it);
|
||||
publish<Events::TriggerLeave>(pId, tId);
|
||||
publish<Events::TriggerLeave>(colliderEntity, triggerEntity);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -83,18 +76,18 @@ bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& trigg
|
||||
|
||||
bool TriggerSystem::OnTouch(const Events::TriggerTouch &event)
|
||||
{
|
||||
LOG_INFO("Player entity %i touched trigger entity %i.", event.Entity, event.Trigger);
|
||||
LOG_INFO("Player entity %i touched trigger entity %i.", event.Entity.ID, event.Trigger.ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TriggerSystem::OnEnter(const Events::TriggerEnter &event)
|
||||
{
|
||||
LOG_INFO("Player entity %i entered trigger entity %i.", event.Entity, event.Trigger);
|
||||
LOG_INFO("Player entity %i entered trigger entity %i.", event.Entity.ID, event.Trigger.ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TriggerSystem::OnLeave(const Events::TriggerLeave &event)
|
||||
{
|
||||
LOG_INFO("Player entity %i left trigger entity %i.", event.Entity, event.Trigger);
|
||||
LOG_INFO("Player entity %i left trigger entity %i.", event.Entity.ID, event.Trigger.ID);
|
||||
return true;
|
||||
}
|
||||
@@ -20,10 +20,6 @@ AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos)
|
||||
}
|
||||
}
|
||||
|
||||
AABB::AABB(const glm::vec4& minPos, const glm::vec4& maxPos)
|
||||
: AABB(glm::vec3(minPos), glm::vec3(maxPos))
|
||||
{ }
|
||||
|
||||
AABB AABB::FromOriginSize(const glm::vec3& origin, const glm::vec3& size)
|
||||
{
|
||||
return AABB(origin - (size/2.f), origin + (size/2.f));
|
||||
|
||||
@@ -20,7 +20,7 @@ void EntityFile::Parse(const EntityFileHandler* handler) const
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
EntityFileSAXHandler saxHandler(handler, nullptr);
|
||||
EntityFileSAXHandler saxHandler(handler, m_SAX2XMLReader);
|
||||
setReaderFeatures(m_SAX2XMLReader);
|
||||
m_SAX2XMLReader->setContentHandler(&saxHandler);
|
||||
m_SAX2XMLReader->setErrorHandler(&saxHandler);
|
||||
@@ -37,11 +37,12 @@ void EntityFile::setReaderFeatures(xercesc::SAX2XMLReader* reader)
|
||||
reader->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
|
||||
reader->setFeature(XMLUni::fgXercesSchema, true);
|
||||
reader->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
|
||||
reader->setFeature(XMLUni::fgXercesCalculateSrcOfs, true);
|
||||
}
|
||||
|
||||
std::size_t EntityFile::GetTypeStride(std::string typeName)
|
||||
unsigned int EntityFile::GetTypeStride(std::string typeName)
|
||||
{
|
||||
std::map<std::string, size_t> typeStrides{
|
||||
std::map<std::string, unsigned int> typeStrides{
|
||||
{ "bool", sizeof(bool) },
|
||||
{ "int", sizeof(int) },
|
||||
{ "float", sizeof(float) },
|
||||
@@ -111,8 +112,9 @@ void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& fie
|
||||
} catch (const boost::bad_lexical_cast&) { }
|
||||
}
|
||||
|
||||
EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader) : m_Handler(handler)
|
||||
, m_Reader(reader)
|
||||
EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader)
|
||||
: m_Handler(handler)
|
||||
, m_Reader(reader)
|
||||
{
|
||||
// 0 is imaginary base parent
|
||||
m_EntityStack.push(0);
|
||||
@@ -188,21 +190,29 @@ void EntityFileSAXHandler::characters(const XMLCh* const chars, const XMLSize_t
|
||||
|
||||
void EntityFileSAXHandler::fatalError(const xercesc::SAXParseException& e)
|
||||
{
|
||||
XS::ToString s(e.getMessage());
|
||||
LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str());
|
||||
//throw e;
|
||||
std::string message = XS::ToString(e.getMessage());
|
||||
std::string systemId = XS::ToString(e.getSystemId());
|
||||
XMLFileLoc line = e.getLineNumber();
|
||||
XMLFileLoc column = e.getColumnNumber();
|
||||
LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tFatal Error: %s", systemId.c_str(), line, column, message.c_str());
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::error(const xercesc::SAXParseException& e)
|
||||
{
|
||||
XS::ToString s(e.getMessage());
|
||||
LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str());
|
||||
std::string message = XS::ToString(e.getMessage());
|
||||
std::string systemId = XS::ToString(e.getSystemId());
|
||||
XMLFileLoc line = e.getLineNumber();
|
||||
XMLFileLoc column = e.getColumnNumber();
|
||||
LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tError: %s", systemId.c_str(), line, column, message.c_str());
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::warning(const xercesc::SAXParseException& e)
|
||||
{
|
||||
XS::ToString s(e.getMessage());
|
||||
LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str());
|
||||
std::string message = XS::ToString(e.getMessage());
|
||||
std::string systemId = XS::ToString(e.getSystemId());
|
||||
XMLFileLoc line = e.getLineNumber();
|
||||
XMLFileLoc column = e.getColumnNumber();
|
||||
LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tWarning: %s", systemId.c_str(), line, column, message.c_str());
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onStartEntity(const xercesc::Attributes& attrs)
|
||||
|
||||
@@ -65,6 +65,7 @@ void EntityFilePreprocessor::parseComponentInfo()
|
||||
|
||||
// Name
|
||||
compInfo.Name = XS::ToString(element->getName());
|
||||
bool brk = compInfo.Name == "HiddenForLocalPlayer";
|
||||
// Known allocation
|
||||
compInfo.Meta->Allocation = m_ComponentCounts[compInfo.Name];
|
||||
// Annotation
|
||||
@@ -90,7 +91,7 @@ void EntityFilePreprocessor::parseComponentInfo()
|
||||
// <xs:all>
|
||||
auto modelGroupParticle = complexTypeDefinition->getParticle();
|
||||
if (modelGroupParticle == nullptr || modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) {
|
||||
//LOG_ERROR("Failed to parse component definition for \"%s\": Model group particle was null or wasn't TERM_MODELGROUP!", compInfo.Name.c_str());
|
||||
LOG_ERROR("Failed to parse component definition for \"%s\": Model group particle was null or wasn't TERM_MODELGROUP!", compInfo.Name.c_str());
|
||||
continue;
|
||||
}
|
||||
auto modelGroup = modelGroupParticle->getModelGroupTerm();
|
||||
@@ -113,7 +114,7 @@ void EntityFilePreprocessor::parseComponentInfo()
|
||||
std::string baseType = XS::ToString(elementDeclaration->getTypeDefinition()->getBaseType()->getName());
|
||||
|
||||
std::string effectiveType = type;
|
||||
size_t stride = EntityFile::GetTypeStride(type);
|
||||
unsigned int stride = EntityFile::GetTypeStride(type);
|
||||
if (stride == 0) {
|
||||
stride = EntityFile::GetTypeStride(baseType);
|
||||
if (stride == 0) {
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
|
||||
const EntityWrapper EntityWrapper::Invalid = EntityWrapper(nullptr, EntityID_Invalid);
|
||||
|
||||
const std::string EntityWrapper::Name()
|
||||
{
|
||||
return World->GetName(ID);
|
||||
}
|
||||
|
||||
bool EntityWrapper::HasComponent(const std::string& componentName)
|
||||
{
|
||||
if (!Valid()) {
|
||||
@@ -22,18 +27,7 @@ EntityWrapper EntityWrapper::Parent()
|
||||
|
||||
EntityWrapper EntityWrapper::FirstChildByName(const std::string& name)
|
||||
{
|
||||
auto itPair = this->World->GetChildren(this->ID);
|
||||
if (itPair.first == itPair.second) {
|
||||
return EntityWrapper::Invalid;
|
||||
}
|
||||
|
||||
for (auto it = itPair.first; it != itPair.second; ++it) {
|
||||
if (this->World->GetName(it->second) == name) {
|
||||
return EntityWrapper(this->World, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
return EntityWrapper::Invalid;
|
||||
return firstChildByNameRecursive(name, this->ID);
|
||||
}
|
||||
|
||||
EntityWrapper EntityWrapper::FirstParentWithComponent(const std::string& componentType)
|
||||
@@ -103,8 +97,29 @@ EntityWrapper::operator EntityID() const
|
||||
return this->ID;
|
||||
}
|
||||
|
||||
EntityWrapper::operator bool()
|
||||
EntityWrapper EntityWrapper::firstChildByNameRecursive(const std::string& name, EntityID parent)
|
||||
{
|
||||
return this->Valid();
|
||||
if (!this->World->ValidEntity(parent)) {
|
||||
return EntityWrapper::Invalid;
|
||||
}
|
||||
|
||||
auto itPair = this->World->GetChildren(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) {
|
||||
EntityWrapper result = firstChildByNameRecursive(name, it->second);
|
||||
if (result != EntityWrapper::Invalid) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EntityWrapper::Invalid;
|
||||
}
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ void InputManager::PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis
|
||||
void InputManager::PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button)
|
||||
{
|
||||
bool currentState = m_CurrentGamepadButtonState[gamepadID][static_cast<int>(button)];
|
||||
float lastState = m_LastGamepadButtonState[gamepadID][static_cast<int>(button)];
|
||||
bool lastState = m_LastGamepadButtonState[gamepadID][static_cast<int>(button)];
|
||||
if (currentState != lastState) {
|
||||
if (currentState == true) {
|
||||
Events::GamepadButtonDown e;
|
||||
|
||||
@@ -105,8 +105,7 @@ bool Child::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const
|
||||
for (int i : m_DynamicObjIndices) {
|
||||
if (!m_DynamicObjectsRef[i].Checked) {
|
||||
const AABB& objBox = *m_DynamicObjectsRef[i].Box;
|
||||
if (!Collision::IsSameBoxProbably(boxToTest, objBox) &&
|
||||
Collision::AABBVsAABB(boxToTest, objBox)) {
|
||||
if (Collision::AABBVsAABB(boxToTest, objBox)) {
|
||||
outBoxIntersected = objBox;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
#include "Core/Transform.h"
|
||||
|
||||
glm::mat4 Transform::AbsoluteTransformation(EntityWrapper entity)
|
||||
{
|
||||
glm::mat4 t = glm::mat4(1.f);
|
||||
|
||||
while (entity.Valid()) {
|
||||
t = glm::translate((glm::vec3&)entity["Transform"]["Position"]) * glm::toMat4(glm::quat((glm::vec3&)entity["Transform"]["Orientation"])) * glm::scale((glm::vec3&)entity["Transform"]["Scale"]) * t;
|
||||
entity = entity.Parent();
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
glm::vec3 Transform::AbsolutePosition(EntityWrapper entity)
|
||||
{
|
||||
return AbsolutePosition(entity.World, entity.ID);
|
||||
@@ -19,6 +31,19 @@ glm::vec3 Transform::AbsolutePosition(World* world, EntityID entity)
|
||||
return position;
|
||||
}
|
||||
|
||||
glm::vec3 Transform::AbsoluteOrientationEuler(EntityWrapper entity)
|
||||
{
|
||||
glm::vec3 orientation;
|
||||
|
||||
while (entity.Valid()) {
|
||||
ComponentWrapper transform = entity["Transform"];
|
||||
orientation += (glm::vec3)transform["Orientation"];
|
||||
entity = entity.Parent();
|
||||
}
|
||||
|
||||
return orientation;
|
||||
}
|
||||
|
||||
glm::quat Transform::AbsoluteOrientation(EntityWrapper entity)
|
||||
{
|
||||
return AbsoluteOrientation(entity.World, entity.ID);
|
||||
@@ -62,6 +87,8 @@ glm::mat4 Transform::ModelMatrix(EntityWrapper entity)
|
||||
|
||||
glm::mat4 Transform::ModelMatrix(EntityID entity, World* world)
|
||||
{
|
||||
return AbsoluteTransformation(EntityWrapper(world, entity));
|
||||
|
||||
glm::vec3 position = Transform::AbsolutePosition(world, entity);
|
||||
glm::quat orientation = Transform::AbsoluteOrientation(world, entity);
|
||||
glm::vec3 scale = Transform::AbsoluteScale(world, entity);
|
||||
|
||||
@@ -4,4 +4,40 @@
|
||||
_LOG_LEVEL LOG_LEVEL = LOG_LEVEL_DEBUG;
|
||||
#else
|
||||
_LOG_LEVEL LOG_LEVEL = LOG_LEVEL_INFO;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const char* _LOG_LEVEL_PREFIX[] =
|
||||
{
|
||||
"EE: ",
|
||||
"",
|
||||
"WW: ",
|
||||
"DD: "
|
||||
};
|
||||
|
||||
void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int line, const char* format, ...)
|
||||
{
|
||||
if (logLevel > LOG_LEVEL) {
|
||||
return;
|
||||
}
|
||||
|
||||
char* message = nullptr;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
size_t size = vsnprintf(message, 0, format, args) + 1;
|
||||
va_end(args);
|
||||
|
||||
va_start(args, format);
|
||||
message = new char[size];
|
||||
vsnprintf(message, size, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (logLevel == LOG_LEVEL_ERROR) {
|
||||
std::cerr << file << ":" << line << " " << func << std::endl;
|
||||
std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;
|
||||
} else {
|
||||
std::cout << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;
|
||||
}
|
||||
|
||||
delete[] message;
|
||||
}
|
||||
@@ -54,8 +54,12 @@ ComponentWrapper World::AttachComponent(EntityID entity, const std::string& comp
|
||||
|
||||
bool World::HasComponent(EntityID entity, const std::string& componentType) const
|
||||
{
|
||||
ComponentPool* pool = m_ComponentPools.at(componentType);
|
||||
return pool->KnowsEntity(entity);
|
||||
auto it = m_ComponentPools.find(componentType);
|
||||
if (it == m_ComponentPools.end()) {
|
||||
return false;
|
||||
} else {
|
||||
return it->second->KnowsEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
ComponentWrapper World::GetComponent(EntityID entity, const std::string& componentType)
|
||||
@@ -92,6 +96,13 @@ EntityID World::GetParent(EntityID entity)
|
||||
|
||||
void World::SetParent(EntityID entity, EntityID parent)
|
||||
{
|
||||
// Don't allow an entity to be a child to itself!
|
||||
if (entity == parent) {
|
||||
// HACK: We purposely don't check the whole hierarchy of children here, since it would be way too slow.
|
||||
// This might result in infinite loops if an entity somehow ends up as a child.
|
||||
return;
|
||||
}
|
||||
|
||||
EntityID lastParent = m_EntityParents.at(entity);
|
||||
auto parentChildren = m_EntityChildren.equal_range(lastParent);
|
||||
for (auto it = parentChildren.first; it != parentChildren.second; it++) {
|
||||
|
||||
+150
-26
@@ -1,10 +1,16 @@
|
||||
#include "Editor/EditorGUI.h"
|
||||
#include "Rendering/ESetCamera.h"
|
||||
|
||||
EditorGUI::EditorGUI(World* world, EventBroker* eventBroker)
|
||||
: m_World(world)
|
||||
, m_EventBroker(eventBroker)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &EditorGUI::OnKeyDown);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorGUI::OnFileDropped);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPause, &EditorGUI::OnPause);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EResume, &EditorGUI::OnResume);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &EditorGUI::OnLockMouse);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &EditorGUI::OnUnlockMouse);
|
||||
}
|
||||
|
||||
void EditorGUI::Draw()
|
||||
@@ -36,39 +42,60 @@ void EditorGUI::drawTools()
|
||||
return;
|
||||
}
|
||||
|
||||
// Widget modes
|
||||
createWidgetToolButton(WidgetMode::Translate);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Translate");
|
||||
ImGui::SetTooltip("Translate (W)");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
createWidgetToolButton(WidgetMode::Rotate);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Rotate");
|
||||
ImGui::SetTooltip("Rotate (E)");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
createWidgetToolButton(WidgetMode::Scale);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Scale");
|
||||
ImGui::SetTooltip("Scale (R)");
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::ItemSize(ImVec2(5, 0));
|
||||
|
||||
// Widget space
|
||||
ImGui::SameLine();
|
||||
GLuint spaceTexture = 0;
|
||||
if (m_CurrentWidgetSpace == WidgetSpace::Global) {
|
||||
spaceTexture = tryLoadTexture("Textures/Icons/Global.png");
|
||||
} else if (m_CurrentWidgetSpace == WidgetSpace::Local) {
|
||||
spaceTexture = tryLoadTexture("Textures/Icons/Local.png");
|
||||
}
|
||||
if (ImGui::ImageButton(reinterpret_cast<void*>(spaceTexture), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1))) {
|
||||
toggleWidgetSpace();
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
if (m_CurrentWidgetSpace == WidgetSpace::Global) {
|
||||
ImGui::SetTooltip("Widget space: Global (X)");
|
||||
} else if (m_CurrentWidgetSpace == WidgetSpace::Local) {
|
||||
ImGui::SetTooltip("Widget space: Local (X)");
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::ItemSize(ImVec2(5, 0));
|
||||
|
||||
// Play button
|
||||
ImGui::SameLine();
|
||||
static bool paused = false;
|
||||
if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Play.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (!paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) {
|
||||
if (ImGui::ImageButton(reinterpret_cast<void*>(tryLoadTexture("Textures/Icons/Play.png")), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (!m_Paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) {
|
||||
Events::Resume e;
|
||||
e.World = m_World;
|
||||
m_EventBroker->Publish(e);
|
||||
paused = false;
|
||||
}
|
||||
// Pause button
|
||||
ImGui::SameLine();
|
||||
if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Pause.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) {
|
||||
if (ImGui::ImageButton(reinterpret_cast<void*>(tryLoadTexture("Textures/Icons/Pause.png")), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (m_Paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) {
|
||||
Events::Pause e;
|
||||
e.World = m_World;
|
||||
m_EventBroker->Publish(e);
|
||||
paused = true;
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
@@ -167,10 +194,7 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity)
|
||||
ImGui::Text(formatEntityName(entity).c_str());
|
||||
ImGui::End();
|
||||
}
|
||||
}/* else if (m_CurrentlyDragging == entity) {
|
||||
LOG_DEBUG("Stopped dragging %i", entity.ID);
|
||||
m_CurrentlyDragging = EntityWrapper::Invalid;
|
||||
}*/
|
||||
}
|
||||
// Entity context menu
|
||||
std::string contextMenuUniqueID = std::string("EntityContextMenu") + std::to_string(entity.ID);
|
||||
if (hovered && ImGui::IsMouseClicked(1)) {
|
||||
@@ -233,10 +257,12 @@ void EditorGUI::drawComponents(EntityWrapper entity)
|
||||
componentTypes.push_back(pair.first.c_str());
|
||||
}
|
||||
}
|
||||
// Sort components in alphabetical order
|
||||
std::sort(componentTypes.begin(), componentTypes.end(), compareCharArray);
|
||||
// Draw combo box
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() - 10.f);
|
||||
int selectedItem = -1;
|
||||
if (ImGui::Combo("", &selectedItem, componentTypes.data(), componentTypes.size())) {
|
||||
if (ImGui::Combo("", &selectedItem, componentTypes.data(), static_cast<int>(componentTypes.size()), static_cast<int>(componentTypes.size()))) {
|
||||
if (selectedItem != -1) {
|
||||
if (m_OnComponentAttach != nullptr) {
|
||||
std::string chosenComponentType(componentTypes.at(selectedItem));
|
||||
@@ -282,9 +308,8 @@ bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci)
|
||||
|
||||
// Draw component fields
|
||||
ComponentWrapper& component = entity.World->GetComponent(entity.ID, ci.Name);
|
||||
for (auto& kv : ci.Fields) {
|
||||
const std::string& fieldName = kv.first;
|
||||
const ComponentInfo::Field_t& field = kv.second;
|
||||
for (auto& fieldName : ci.FieldsInOrder) {
|
||||
const ComponentInfo::Field_t& field = ci.Fields.at(fieldName);
|
||||
|
||||
// Draw the field widget based on its type
|
||||
bool dirty = drawComponentField(component, field);
|
||||
@@ -305,6 +330,14 @@ bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci)
|
||||
}
|
||||
}
|
||||
|
||||
if (ci.Name == "Camera") {
|
||||
if (ImGui::Button("Activate")) {
|
||||
Events::SetCamera e;
|
||||
e.CameraEntity = entity;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -426,18 +459,31 @@ bool EditorGUI::drawComponentField_bool(ComponentWrapper &c, const ComponentInfo
|
||||
|
||||
bool EditorGUI::drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
auto& val = c.Field<std::string>(field.Name);
|
||||
|
||||
char tempString[1024]; // Let's just hope this is an sufficiently large buffer for strings :)
|
||||
tempString[1023] = '\0'; // Null terminator just in case the string is larger than the buffer
|
||||
// Copy the string into the buffer, taking the null terminator into account
|
||||
memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString) - 1));
|
||||
if (ImGui::InputText("", tempString, sizeof(tempString))) {
|
||||
val = std::string(tempString);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
result = true;
|
||||
}
|
||||
// TODO: Handle drag and drop of files
|
||||
|
||||
// Handle file drag and drop
|
||||
if (ImGui::IsItemHovered() && !m_DroppedFile.empty()) {
|
||||
// Unset potential input focus or our newly set value will be overwritten!
|
||||
if (ImGui::IsItemActive()) {
|
||||
ImGui::SetActiveID(0, nullptr);
|
||||
}
|
||||
// Set the actual dropped value
|
||||
val = m_DroppedFile;
|
||||
m_DroppedFile = "";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void EditorGUI::drawModals()
|
||||
@@ -519,7 +565,7 @@ void EditorGUI::createWidgetToolButton(WidgetMode mode)
|
||||
break;
|
||||
}
|
||||
if (ImGui::ImageButton(
|
||||
(void*)texture,
|
||||
reinterpret_cast<void*>(texture),
|
||||
ImVec2(24, 24),
|
||||
ImVec2(0, 1),
|
||||
ImVec2(1, 0),
|
||||
@@ -528,10 +574,7 @@ void EditorGUI::createWidgetToolButton(WidgetMode mode)
|
||||
(m_CurrentWidgetMode == mode) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1)
|
||||
)
|
||||
) {
|
||||
if (m_OnWidgetMode != nullptr) {
|
||||
m_OnWidgetMode(mode);
|
||||
}
|
||||
m_CurrentWidgetMode = mode;
|
||||
setWidgetMode(mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,6 +604,61 @@ bool EditorGUI::OnKeyDown(const Events::KeyDown& e)
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_MouseLocked) {
|
||||
if (e.KeyCode == GLFW_KEY_W) {
|
||||
setWidgetMode(WidgetMode::Translate);
|
||||
}
|
||||
if (e.KeyCode == GLFW_KEY_E) {
|
||||
setWidgetMode(WidgetMode::Rotate);
|
||||
}
|
||||
if (e.KeyCode == GLFW_KEY_R) {
|
||||
setWidgetMode(WidgetMode::Scale);
|
||||
}
|
||||
|
||||
if (e.KeyCode == GLFW_KEY_X) {
|
||||
toggleWidgetSpace();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorGUI::OnFileDropped(const Events::FileDropped& e)
|
||||
{
|
||||
// Make a best effort to make the path relative to the working directory of the executable
|
||||
m_DroppedFile = boost::filesystem::path(e.Path).lexically_relative(boost::filesystem::current_path()).string();
|
||||
// Compensate for Windows retardedness
|
||||
std::replace(m_DroppedFile.begin(), m_DroppedFile.end(), '\\', '/');
|
||||
// Special case for when people drop from the asset folder instead of from the symlink to the asset folders in bin
|
||||
boost::algorithm::replace_first(m_DroppedFile, "../assets/", "");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorGUI::OnPause(const Events::Pause& e)
|
||||
{
|
||||
if (e.World == m_World) {
|
||||
m_Paused = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorGUI::OnResume(const Events::Resume& e)
|
||||
{
|
||||
if (e.World == m_World) {
|
||||
m_Paused = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorGUI::OnLockMouse(const Events::LockMouse& e)
|
||||
{
|
||||
m_MouseLocked = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorGUI::OnUnlockMouse(const Events::UnlockMouse& e)
|
||||
{
|
||||
m_MouseLocked = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -635,6 +733,32 @@ void EditorGUI::openModal(const std::string& modal)
|
||||
m_ModalsToOpen.insert(modal);
|
||||
}
|
||||
|
||||
void EditorGUI::setWidgetMode(WidgetMode mode)
|
||||
{
|
||||
if (m_OnWidgetMode != nullptr) {
|
||||
m_OnWidgetMode(mode);
|
||||
}
|
||||
m_CurrentWidgetMode = mode;
|
||||
}
|
||||
|
||||
void EditorGUI::toggleWidgetSpace()
|
||||
{
|
||||
if (m_CurrentWidgetSpace == WidgetSpace::Global) {
|
||||
m_CurrentWidgetSpace = WidgetSpace::Local;
|
||||
} else if (m_CurrentWidgetSpace == WidgetSpace::Local) {
|
||||
m_CurrentWidgetSpace = WidgetSpace::Global;
|
||||
}
|
||||
|
||||
if (m_OnWidgetSpace != nullptr) {
|
||||
m_OnWidgetSpace(m_CurrentWidgetSpace);
|
||||
}
|
||||
}
|
||||
|
||||
bool EditorGUI::compareCharArray(const char* c1, const char* c2)
|
||||
{
|
||||
return strcmp(c1, c2) < 0;
|
||||
}
|
||||
|
||||
void EditorGUI::SetDirty(EntityWrapper entity)
|
||||
{
|
||||
EntityWrapper baseParent = entity;
|
||||
@@ -722,7 +846,7 @@ void EditorGUI::entityDelete(EntityWrapper entity)
|
||||
|
||||
void EditorGUI::entityChangeParent(EntityWrapper entity, EntityWrapper parent)
|
||||
{
|
||||
if (entity == parent) {
|
||||
if (entity == parent || parent.IsChildOf(entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ EditorRenderSystem::EditorRenderSystem(World* m_World, EventBroker* eventBroker,
|
||||
|
||||
void EditorRenderSystem::Update(double dt)
|
||||
{
|
||||
if (m_CurrentCamera) {
|
||||
if (m_CurrentCamera.Valid()) {
|
||||
ComponentWrapper cameraTransform = m_CurrentCamera["Transform"];
|
||||
m_EditorCamera->SetPosition(cameraTransform["Position"]);
|
||||
m_EditorCamera->SetOrientation(glm::quat((const glm::vec3&)cameraTransform["Orientation"]));
|
||||
@@ -48,8 +48,12 @@ void EditorRenderSystem::Update(double dt)
|
||||
EntityWrapper entity(m_World, cModel.EntityID);
|
||||
glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World);
|
||||
for (auto matGroup : model->MaterialGroups()) {
|
||||
std::shared_ptr<ModelJob> modelJob = std::make_shared<ModelJob>(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World);
|
||||
scene.ForwardJobs.push_back(modelJob);
|
||||
std::shared_ptr<ModelJob> modelJob = std::make_shared<ModelJob>(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World, glm::vec4(0), 0.f);
|
||||
if(cModel["Transparent"]) {
|
||||
scene.TransparentObjects.push_back(modelJob);
|
||||
} else {
|
||||
scene.OpaqueObjects.push_back(modelJob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,9 +80,9 @@ bool EditorRenderSystem::OnSetCamera(Events::SetCamera& e)
|
||||
{
|
||||
ComponentWrapper cTransform = e.CameraEntity["Transform"];
|
||||
ComponentWrapper cCamera = e.CameraEntity["Camera"];
|
||||
m_EditorCamera->SetFOV((double)cCamera["FOV"]);
|
||||
m_EditorCamera->SetNearClip((double)cCamera["NearClip"]);
|
||||
m_EditorCamera->SetFarClip((double)cCamera["FarClip"]);
|
||||
m_EditorCamera->SetFOV(static_cast<float>((double)cCamera["FOV"]));
|
||||
m_EditorCamera->SetNearClip(static_cast<float>((double)cCamera["NearClip"]));
|
||||
m_EditorCamera->SetFarClip(static_cast<float>((double)cCamera["FarClip"]));
|
||||
m_EditorCamera->SetPosition(cTransform["Position"]);
|
||||
m_EditorCamera->SetOrientation(glm::quat((const glm::vec3&)cTransform["Orientation"]));
|
||||
m_CurrentCamera = e.CameraEntity;
|
||||
|
||||
@@ -31,6 +31,7 @@ EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* re
|
||||
m_EditorGUI->SetComponentAttachCallback(std::bind(&EditorSystem::OnComponentAttach, this, std::placeholders::_1, std::placeholders::_2));
|
||||
m_EditorGUI->SetComponentDeleteCallback(std::bind(&EditorSystem::OnComponentDelete, this, std::placeholders::_1, std::placeholders::_2));
|
||||
m_EditorGUI->SetWidgetModeCallback(std::bind(&EditorSystem::setWidgetMode, this, std::placeholders::_1));
|
||||
m_EditorGUI->SetWidgetSpaceCallback(std::bind(&EditorSystem::OnWidgetSpace, this, std::placeholders::_1));
|
||||
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EWidgetDelta, &EditorSystem::OnWidgetDelta);
|
||||
@@ -65,7 +66,12 @@ void EditorSystem::Update(double dt)
|
||||
m_EditorStats->Draw(actualDelta);
|
||||
|
||||
if (m_CurrentSelection.Valid() && m_Widget.Valid()) {
|
||||
(glm::vec3&)m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID);
|
||||
(glm::vec3&)m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection);
|
||||
if (m_WidgetSpace == EditorGUI::WidgetSpace::Local) {
|
||||
(glm::vec3&)m_Widget["Transform"]["Orientation"] = Transform::AbsoluteOrientationEuler(m_CurrentSelection);
|
||||
} else {
|
||||
(glm::vec3&)m_Widget["Transform"]["Orientation"] = glm::vec3(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
m_EditorWorldSystemPipeline->Update(actualDelta);
|
||||
@@ -82,11 +88,22 @@ void EditorSystem::Update(double dt)
|
||||
void EditorSystem::Enable()
|
||||
{
|
||||
m_EditorCameraInputController->Enable();
|
||||
|
||||
m_EventBroker->Publish(Events::UnlockMouse());
|
||||
Events::SetCamera e;
|
||||
e.CameraEntity = m_EditorCamera;
|
||||
m_EventBroker->Publish(e);
|
||||
(glm::vec3&)m_EditorCamera["Transform"]["Position"] = Transform::AbsolutePosition(m_ActualCamera);
|
||||
|
||||
// Enable editor camera
|
||||
Events::SetCamera eSetCamera;
|
||||
eSetCamera.CameraEntity = m_EditorCamera;
|
||||
m_EventBroker->Publish(eSetCamera);
|
||||
if (m_ActualCamera.Valid()) {
|
||||
(glm::vec3&)m_EditorCamera["Transform"]["Position"] = Transform::AbsolutePosition(m_ActualCamera);
|
||||
}
|
||||
|
||||
// Pause the world we're editing
|
||||
Events::Pause ePause;
|
||||
ePause.World = m_World;
|
||||
m_EventBroker->Publish(ePause);
|
||||
|
||||
m_Enabled = true;
|
||||
}
|
||||
|
||||
@@ -154,6 +171,11 @@ void EditorSystem::OnComponentDelete(EntityWrapper entity, const std::string& co
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSystem::OnWidgetSpace(EditorGUI::WidgetSpace widgetSpace)
|
||||
{
|
||||
m_WidgetSpace = widgetSpace;
|
||||
}
|
||||
|
||||
bool EditorSystem::OnMousePress(const Events::MousePress& e)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
@@ -170,12 +192,18 @@ bool EditorSystem::OnMousePress(const Events::MousePress& e)
|
||||
bool EditorSystem::OnWidgetDelta(const Events::WidgetDelta& e)
|
||||
{
|
||||
if (m_CurrentSelection.Valid()) {
|
||||
glm::quat parentOrientation;
|
||||
EntityWrapper parent = m_CurrentSelection.Parent();
|
||||
if (parent.Valid()) {
|
||||
parentOrientation = glm::inverse(Transform::AbsoluteOrientation(parent.World, parent.ID));
|
||||
if (m_WidgetSpace == EditorGUI::WidgetSpace::Global) {
|
||||
glm::quat parentOrientation;
|
||||
EntityWrapper parent = m_CurrentSelection.Parent();
|
||||
if (parent.Valid()) {
|
||||
parentOrientation = glm::inverse(Transform::AbsoluteOrientation(parent));
|
||||
}
|
||||
(glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation;
|
||||
} else if (m_WidgetSpace == EditorGUI::WidgetSpace::Local) {
|
||||
glm::quat selectionOri = glm::quat((glm::vec3)m_CurrentSelection["Transform"]["Orientation"]);
|
||||
glm::vec3 localTranslation = selectionOri * e.Translation;
|
||||
(glm::vec3&)m_CurrentSelection["Transform"]["Position"] += localTranslation;
|
||||
}
|
||||
(glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation;
|
||||
m_EditorGUI->SetDirty(m_CurrentSelection);
|
||||
}
|
||||
return true;
|
||||
@@ -203,7 +231,7 @@ bool EditorSystem::OnSetCamera(const Events::SetCamera& e)
|
||||
m_ActualCamera = e.CameraEntity;
|
||||
Events::SetCamera e2;
|
||||
e2.CameraEntity = m_EditorCamera;
|
||||
m_EventBroker->Publish(e2);
|
||||
//m_EventBroker->Publish(e2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -23,14 +23,18 @@ void EditorWidgetSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper
|
||||
|
||||
Events::WidgetDelta e;
|
||||
|
||||
EntityWrapper moveEntity = entity.Parent();
|
||||
if (!moveEntity.Valid()) {
|
||||
moveEntity = entity;
|
||||
// Widget axes should have a common parent
|
||||
EntityWrapper widgetBase = entity.Parent();
|
||||
if (!widgetBase.Valid()) {
|
||||
widgetBase = entity;
|
||||
}
|
||||
glm::vec3 widgetBasePos = widgetBase["Transform"]["Position"];
|
||||
glm::quat widgetBaseOri = glm::quat((glm::vec3)widgetBase["Transform"]["Orientation"]);
|
||||
|
||||
auto camera = m_PickData.Camera;
|
||||
glm::vec3 axis = cEditorWidget["Axis"];
|
||||
glm::vec2 axisScreen = camera->WorldToScreen(axis, m_Renderer->Resolution()) - camera->WorldToScreen(glm::vec3(0, 0, 0), m_Renderer->Resolution());
|
||||
glm::vec3 axis = (glm::vec3)cEditorWidget["Axis"];
|
||||
glm::vec3 axisOriented = widgetBaseOri * axis;
|
||||
glm::vec2 axisScreen = camera->WorldToScreen(widgetBasePos + axisOriented, m_Renderer->GetViewportSize()) - camera->WorldToScreen(widgetBasePos, m_Renderer->GetViewportSize());
|
||||
float dot = glm::dot(m_MouseDelta, glm::normalize(axisScreen)) / glm::length(axisScreen);
|
||||
glm::vec3 worldMovement = dot * axis;
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ bool MouseInputHandler::OnMouseMove(const Events::MouseMove& e)
|
||||
Events::InputCommand ic;
|
||||
ic.PlayerID = -1;
|
||||
std::tie(ic.Command, ic.Value) = it->second;
|
||||
ic.Value *= e.DeltaX;
|
||||
ic.Value *= static_cast<float>(e.DeltaX);
|
||||
m_InputProxy->Publish(ic);
|
||||
}
|
||||
}
|
||||
@@ -109,7 +109,7 @@ bool MouseInputHandler::OnMouseMove(const Events::MouseMove& e)
|
||||
Events::InputCommand ic;
|
||||
ic.PlayerID = -1;
|
||||
std::tie(ic.Command, ic.Value) = it->second;
|
||||
ic.Value *= e.DeltaY;
|
||||
ic.Value *= static_cast<float>(e.DeltaY);
|
||||
m_InputProxy->Publish(ic);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ bool Client::OnPlayerDamage(const Events::PlayerDamage & e)
|
||||
{
|
||||
Packet packet(MessageType::OnPlayerDamage, m_SendPacketID);
|
||||
packet.WritePrimitive(e.Damage);
|
||||
packet.WritePrimitive(e.Player.ID);
|
||||
packet.WritePrimitive(m_ClientIDToServerID.at(e.Player.ID));
|
||||
send(packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -269,6 +269,7 @@ void Server::parseOnInputCommand(Packet& packet)
|
||||
Events::InputCommand e;
|
||||
e.Command = packet.ReadString();
|
||||
e.PlayerID = player; // Set correct player id
|
||||
e.Player = EntityWrapper(m_World, m_ConnectedPlayers.at(player).EntityID);
|
||||
e.Value = packet.ReadPrimitive<float>();
|
||||
m_EventBroker->Publish(e);
|
||||
LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "Rendering/AnimationSystem.h"
|
||||
|
||||
void AnimationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt)
|
||||
{
|
||||
if(!entity.HasComponent("Model")) {
|
||||
return;
|
||||
}
|
||||
|
||||
Model* model;
|
||||
try {
|
||||
model = ResourceManager::Load<::Model, true>(entity["Model"]["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Skeleton* skeleton = model->m_RawModel->m_Skeleton;
|
||||
const Skeleton::Animation* animation = skeleton->GetAnimation(animationComponent["Name"]);
|
||||
|
||||
if(animation != nullptr) {
|
||||
double animationSpeed = (double)animationComponent["Speed"];
|
||||
|
||||
if (animationSpeed != 0.0) {
|
||||
double nextTime = (double)animationComponent["Time"] + animationSpeed * dt;
|
||||
|
||||
|
||||
if (!(bool)animationComponent["Loop"] && glm::abs(nextTime) > animation->Duration) {
|
||||
(double&)animationComponent["Time"] = glm::sign(nextTime) * animation->Duration;
|
||||
(double&)animationComponent["Speed"] = 0.0;
|
||||
Events::AnimationComplete e;
|
||||
e.Entity = entity;
|
||||
e.Name = (std::string)animationComponent["Name"];
|
||||
m_EventBroker->Publish(e);
|
||||
} else {
|
||||
if (glm::abs(nextTime) > animation->Duration) {
|
||||
(double&)animationComponent["Time"] = glm::abs(nextTime) - animation->Duration;
|
||||
} else {
|
||||
(double&)animationComponent["Time"] = nextTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ DrawBloomPass::DrawBloomPass(IRenderer* renderer)
|
||||
|
||||
void DrawBloomPass::InitializeTextures()
|
||||
{
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png");
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/White.png");
|
||||
}
|
||||
|
||||
void DrawBloomPass::InitializeShaderPrograms()
|
||||
@@ -34,12 +34,12 @@ void DrawBloomPass::InitializeShaderPrograms()
|
||||
|
||||
void DrawBloomPass::InitializeBuffers()
|
||||
{
|
||||
GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
|
||||
m_GaussianFrameBuffer_horiz.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_GaussianTexture_horiz, GL_COLOR_ATTACHMENT0)));
|
||||
m_GaussianFrameBuffer_horiz.Generate();
|
||||
|
||||
GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
|
||||
m_GaussianFrameBuffer_vert.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_GaussianTexture_vert, GL_COLOR_ATTACHMENT0)));
|
||||
m_GaussianFrameBuffer_vert.Generate();
|
||||
|
||||
@@ -11,21 +11,23 @@ DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCulling
|
||||
|
||||
void DrawFinalPass::InitializeTextures()
|
||||
{
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png");
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/White.png");
|
||||
m_BlackTexture = ResourceManager::Load<Texture>("Textures/Core/Black.png");
|
||||
m_NeutralNormalTexture = ResourceManager::Load<Texture>("Textures/Core/NeutralNormalMap.png");
|
||||
m_GreyTexture = ResourceManager::Load<Texture>("Textures/Core/Grey.png");
|
||||
}
|
||||
|
||||
void DrawFinalPass::InitializeFrameBuffers()
|
||||
{
|
||||
glGenRenderbuffers(1, &m_DepthBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);
|
||||
|
||||
GenerateTexture(&m_SceneTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
//GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
//GenerateMipMapTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_FLOAT, 4);
|
||||
|
||||
GenerateTexture(&m_SceneTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
//GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
//GenerateMipMapTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_FLOAT, 4);
|
||||
|
||||
m_FinalPassFrameBuffer.AddResource(std::shared_ptr<BufferResource>(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT)));
|
||||
m_FinalPassFrameBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_SceneTexture, GL_COLOR_ATTACHMENT0)));
|
||||
m_FinalPassFrameBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_BloomTexture, GL_COLOR_ATTACHMENT1)));
|
||||
@@ -42,6 +44,15 @@ void DrawFinalPass::InitializeShaderPrograms()
|
||||
m_ForwardPlusProgram->BindFragDataLocation(0, "sceneColor");
|
||||
m_ForwardPlusProgram->BindFragDataLocation(1, "bloomColor");
|
||||
m_ForwardPlusProgram->Link();
|
||||
|
||||
m_ExplosionEffectProgram = ResourceManager::Load<ShaderProgram>("#ExplosionEffectProgram");
|
||||
m_ExplosionEffectProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/ForwardPlus.vert.glsl")));
|
||||
m_ExplosionEffectProgram->AddShader(std::shared_ptr<Shader>(new GeometryShader("Shaders/ExplosionEffect.geom.glsl")));
|
||||
m_ExplosionEffectProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ForwardPlus.frag.glsl")));
|
||||
m_ExplosionEffectProgram->Compile();
|
||||
m_ExplosionEffectProgram->BindFragDataLocation(0, "sceneColor");
|
||||
m_ExplosionEffectProgram->BindFragDataLocation(1, "bloomColor");
|
||||
m_ExplosionEffectProgram->Link();
|
||||
}
|
||||
|
||||
void DrawFinalPass::Draw(RenderScene& scene)
|
||||
@@ -49,68 +60,15 @@ void DrawFinalPass::Draw(RenderScene& scene)
|
||||
GLERROR("DrawFinalPass::Draw: Pre");
|
||||
|
||||
DrawFinalPassState* state = new DrawFinalPassState(m_FinalPassFrameBuffer.GetHandle());
|
||||
|
||||
m_ForwardPlusProgram->Bind();
|
||||
GLuint shaderHandle = m_ForwardPlusProgram->GetHandle();
|
||||
|
||||
if (scene.ClearDepth) {
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO());
|
||||
DrawModelRenderQueues(scene.OpaqueObjects, scene);
|
||||
GLERROR("DrawFinalPass::Draw: OpaqueObjects");
|
||||
DrawModelRenderQueues(scene.TransparentObjects, scene);
|
||||
GLERROR("DrawFinalPass::Draw: TransparentObjects");
|
||||
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
|
||||
|
||||
//TODO: Render: Add code for more jobs than modeljobs.
|
||||
for (auto &job : scene.ForwardJobs) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
if(modelJob) {
|
||||
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color));
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(modelJob->DiffuseColor));
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if(modelJob->DiffuseTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
if (modelJob->IncandescenceTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, modelJob->IncandescenceTexture->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture);
|
||||
}
|
||||
|
||||
/*if(modelJob->GlowMap != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, modelJob->GlowMap->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture);
|
||||
}*/
|
||||
|
||||
//TODO: Fixa så att modelsJobs kan spela upp olika animationer och så att den kan få in en tid istället för 1.0f - Hälsningar Johan och Andreas :)
|
||||
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
|
||||
auto animation = modelJob->Model->m_RawModel->m_Skeleton->GetAnimation("running");
|
||||
if (animation != nullptr) {
|
||||
std::vector<glm::mat4> frameBones = modelJob->Model->m_RawModel->m_Skeleton->GetFrameBones(
|
||||
*animation,
|
||||
0.0f
|
||||
);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(modelJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||
glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int)));
|
||||
}
|
||||
}
|
||||
GLERROR("DrawFinalPass::Draw: END");
|
||||
delete state;
|
||||
}
|
||||
@@ -148,4 +106,153 @@ void DrawFinalPass::GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm:
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
GLERROR("MipMap Texture initialization failed");
|
||||
}
|
||||
}
|
||||
|
||||
void DrawFinalPass::DrawModelRenderQueues(std::list<std::shared_ptr<RenderJob>>& job, RenderScene& scene)
|
||||
{
|
||||
GLuint forwardHandle = m_ForwardPlusProgram->GetHandle();
|
||||
GLuint explosionHandle = m_ExplosionEffectProgram->GetHandle();
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO());
|
||||
|
||||
for(auto &job : job)
|
||||
{
|
||||
auto explosionEffectJob = std::dynamic_pointer_cast<ExplosionEffectJob>(job);
|
||||
if(explosionEffectJob) {
|
||||
//Bind program
|
||||
m_ExplosionEffectProgram->Bind();
|
||||
|
||||
//Bind uniforms
|
||||
BindExplosionUniforms(explosionHandle, explosionEffectJob, scene);
|
||||
|
||||
if (explosionEffectJob->Model->m_RawModel->m_Skeleton != nullptr) {
|
||||
|
||||
if (explosionEffectJob->Animation != nullptr) {
|
||||
std::vector<glm::mat4> frameBones = explosionEffectJob->Skeleton->GetFrameBones(*explosionEffectJob->Animation, explosionEffectJob->AnimationTime);
|
||||
glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
}
|
||||
}
|
||||
|
||||
//bind textures
|
||||
BindExplosionTextures(explosionEffectJob);
|
||||
//draw
|
||||
glBindVertexArray(explosionEffectJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, explosionEffectJob->Model->ElementBuffer);
|
||||
glDrawElements(GL_TRIANGLES, explosionEffectJob->EndIndex - explosionEffectJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(explosionEffectJob->StartIndex*sizeof(unsigned int)));
|
||||
|
||||
} else {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
if (modelJob) {
|
||||
//bind forward program
|
||||
m_ForwardPlusProgram->Bind();
|
||||
glUniform2f(glGetUniformLocation(forwardHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);
|
||||
|
||||
//bind uniforms
|
||||
BindModelUniforms(forwardHandle, modelJob, scene);
|
||||
|
||||
//bind textures
|
||||
BindModelTextures(modelJob);
|
||||
|
||||
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
|
||||
|
||||
if (modelJob->Animation != nullptr) {
|
||||
std::vector<glm::mat4> frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime);
|
||||
glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
}
|
||||
}
|
||||
|
||||
//draw
|
||||
glBindVertexArray(modelJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||
glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex*sizeof(unsigned int)));
|
||||
GLERROR("DrawFinalPass::Model: END");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr<ExplosionEffectJob>& job, RenderScene& scene)
|
||||
{
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix));
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color));
|
||||
glUniform3fv(glGetUniformLocation(shaderHandle, "ExplosionOrigin"), 1, glm::value_ptr(job->ExplosionOrigin));
|
||||
glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), job->TimeSinceDeath);
|
||||
glUniform1f(glGetUniformLocation(shaderHandle, "ExplosionDuration"), job->ExplosionDuration);
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "EndColor"), 1, glm::value_ptr(job->EndColor));
|
||||
glUniform1i(glGetUniformLocation(shaderHandle, "Randomness"), job->Randomness);
|
||||
glUniform1f(glGetUniformLocation(shaderHandle, "RandomnessScalar"), job->RandomnessScalar);
|
||||
glUniform2fv(glGetUniformLocation(shaderHandle, "Velocity"), 1, glm::value_ptr(job->Velocity));
|
||||
glUniform1i(glGetUniformLocation(shaderHandle, "ColorByDistance"), job->ColorByDistance);
|
||||
glUniform1i(glGetUniformLocation(shaderHandle, "ExponentialAccelaration"), job->ExponentialAccelaration);
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(job->DiffuseColor));
|
||||
glUniform1fv(glGetUniformLocation(shaderHandle, "RandomNumbers"), 50, job->RandomNumbers.data());
|
||||
}
|
||||
|
||||
void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptr<ModelJob>& job, RenderScene& scene)
|
||||
{
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix));
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color));
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(job->DiffuseColor));
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(job->FillColor));
|
||||
glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), job->FillPercentage);
|
||||
}
|
||||
|
||||
|
||||
void DrawFinalPass::BindExplosionTextures(std::shared_ptr<ExplosionEffectJob>& job)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if (job->DiffuseTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
if (job->IncandescenceTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawFinalPass::BindModelTextures(std::shared_ptr<ModelJob>& job)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if (job->DiffuseTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
if (job->NormalTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->NormalTexture->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
if (job->SpecularTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->SpecularTexture->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
if (job->IncandescenceTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -134,8 +134,8 @@ bool ImGuiRenderPass::OnMouseRelease(const Events::MouseRelease& e)
|
||||
bool ImGuiRenderPass::OnMouseMove(const Events::MouseMove& e)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MousePos.x = e.X;
|
||||
io.MousePos.y = e.Y;
|
||||
io.MousePos.x = static_cast<float>(e.X);
|
||||
io.MousePos.y = static_cast<float>(e.Y);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ bool ImGuiRenderPass::createFontsTexture()
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void*)g_FontTexture;
|
||||
io.Fonts->TexID = reinterpret_cast<void*>(g_FontTexture);
|
||||
|
||||
// Restore state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
@@ -291,7 +291,7 @@ void ImGuiRenderPass::newFrame()
|
||||
io.DisplaySize = ImVec2((float)w, (float)h);
|
||||
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
|
||||
|
||||
io.DeltaTime = g_DeltaTime;
|
||||
io.DeltaTime = static_cast<float>(g_DeltaTime);
|
||||
|
||||
io.KeyCtrl = glfwGetKey(g_Window, GLFW_KEY_LEFT_CONTROL) || glfwGetKey(g_Window, GLFW_KEY_RIGHT_CONTROL);
|
||||
io.KeyShift = glfwGetKey(g_Window, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(g_Window, GLFW_KEY_RIGHT_SHIFT);
|
||||
|
||||
@@ -25,8 +25,8 @@ void LightCullingPass::GenerateNewFrustum(RenderScene& scene)
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
glDispatchCompute((int)(m_Renderer->Resolution().Width/(TILE_SIZE*TILE_SIZE) + 1), (int)(m_Renderer->Resolution().Height/(TILE_SIZE*TILE_SIZE) + 1), 1);
|
||||
glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);
|
||||
glDispatchCompute((int)(m_Renderer->GetViewportSize().Width/(TILE_SIZE*TILE_SIZE) + 1), (int)(m_Renderer->GetViewportSize().Height/(TILE_SIZE*TILE_SIZE) + 1), 1);
|
||||
|
||||
GLERROR("CalculateFrustum Error: End");
|
||||
}
|
||||
@@ -40,7 +40,7 @@ void LightCullingPass::OnResolutionChange()
|
||||
|
||||
void LightCullingPass::SetSSBOSizes()
|
||||
{
|
||||
m_NumberOfTiles = (int)(m_Renderer->Resolution().Width/TILE_SIZE) * (int)(m_Renderer->Resolution().Height/TILE_SIZE);
|
||||
m_NumberOfTiles = (int)(m_Renderer->GetViewportSize().Width/TILE_SIZE) * (int)(m_Renderer->GetViewportSize().Height/TILE_SIZE);
|
||||
|
||||
m_Frustums = new Frustum[m_NumberOfTiles];
|
||||
m_LightGrid = new LightGrid[m_NumberOfTiles];
|
||||
@@ -67,14 +67,14 @@ void LightCullingPass::CullLights(RenderScene& scene)
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
m_LightCullProgram->Bind();
|
||||
glUniform2f(glGetUniformLocation(m_LightCullProgram->GetHandle(), "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
glUniform2f(glGetUniformLocation(m_LightCullProgram->GetHandle(), "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_LightCullProgram->GetHandle(), "V"), 1, false, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO);
|
||||
glDispatchCompute(glm::ceil(m_Renderer->Resolution().Width / TILE_SIZE), glm::ceil(m_Renderer->Resolution().Height / TILE_SIZE), 1);
|
||||
glDispatchCompute(glm::ceil(m_Renderer->GetViewportSize().Width/ TILE_SIZE), glm::ceil(m_Renderer->GetViewportSize().Height / TILE_SIZE), 1);
|
||||
|
||||
GLERROR("CullLights Error: End");
|
||||
}
|
||||
|
||||
@@ -71,12 +71,12 @@ PNG::PNG(std::string path)
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
}
|
||||
|
||||
unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
std::size_t row_bytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
this->Data = new unsigned char[height * row_bytes];
|
||||
png_bytep* row_pointers = new png_bytep[height];
|
||||
|
||||
// Point each row to the continuous data array
|
||||
for (int i = 0; i < height; ++i) {
|
||||
for (unsigned int i = 0; i < height; ++i) {
|
||||
// Invert Y for OpenGL
|
||||
row_pointers[height - 1 - i] = this->Data + i * row_bytes;
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ PickingPass::~PickingPass()
|
||||
void PickingPass::InitializeTextures()
|
||||
{
|
||||
GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR,
|
||||
glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
|
||||
glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
|
||||
}
|
||||
|
||||
void PickingPass::InitializeFrameBuffers()
|
||||
{
|
||||
glGenRenderbuffers(1, &m_DepthBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height);
|
||||
|
||||
m_PickingBuffer.AddResource(std::shared_ptr<BufferResource>(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT)));
|
||||
m_PickingBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_PickingTexture, GL_COLOR_ATTACHMENT0)));
|
||||
@@ -48,7 +48,7 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
PickingPassState* state = new PickingPassState(m_PickingBuffer.GetHandle());
|
||||
|
||||
//TODO: Render: Add code for more jobs than modeljobs.
|
||||
GLuint ShaderHandle = m_PickingProgram->GetHandle();
|
||||
GLuint shaderHandle = m_PickingProgram->GetHandle();
|
||||
m_PickingProgram->Bind();
|
||||
|
||||
if (scene.ClearDepth) {
|
||||
@@ -56,7 +56,7 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
}
|
||||
m_Camera = scene.Camera;
|
||||
|
||||
for (auto &job : scene.ForwardJobs) {
|
||||
for (auto &job : scene.OpaqueObjects) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
|
||||
if (modelJob) {
|
||||
@@ -75,22 +75,76 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
m_EntityColors[std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)] = glm::ivec2(pickColor[0], pickColor[1]);
|
||||
if (m_ColorCounter[0] > 255) {
|
||||
m_ColorCounter[0] = 0;
|
||||
m_ColorCounter[1]++;
|
||||
m_ColorCounter[1] += 5;
|
||||
} else {
|
||||
m_ColorCounter[0]++;
|
||||
m_ColorCounter[0] += 50;
|
||||
}
|
||||
}
|
||||
|
||||
m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo;
|
||||
|
||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
glUniform2fv(glGetUniformLocation(ShaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
||||
|
||||
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
|
||||
|
||||
if (modelJob->Animation != nullptr) {
|
||||
std::vector<glm::mat4> frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(modelJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, nullptr, modelJob->StartIndex);
|
||||
glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int)));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &job : scene.TransparentObjects) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
|
||||
if (modelJob) {
|
||||
int pickColor[2] = { m_ColorCounter[0], m_ColorCounter[1] };
|
||||
|
||||
PickingInfo pickInfo;
|
||||
pickInfo.Entity = modelJob->Entity;
|
||||
pickInfo.World = modelJob->World;
|
||||
pickInfo.Camera = scene.Camera;
|
||||
|
||||
auto color = m_EntityColors.find(std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera));
|
||||
if (color != m_EntityColors.end()) {
|
||||
pickColor[0] = color->second[0];
|
||||
pickColor[1] = color->second[1];
|
||||
} else {
|
||||
m_EntityColors[std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)] = glm::ivec2(pickColor[0], pickColor[1]);
|
||||
if (m_ColorCounter[0] > 255) {
|
||||
m_ColorCounter[0] = 0;
|
||||
m_ColorCounter[1] += 5;
|
||||
} else {
|
||||
m_ColorCounter[0] += 50;
|
||||
}
|
||||
}
|
||||
|
||||
m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo;
|
||||
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
||||
|
||||
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
|
||||
|
||||
if (modelJob->Animation != nullptr) {
|
||||
std::vector<glm::mat4> frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(modelJob->Model->VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
|
||||
glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,42 +22,42 @@ void RawModelCustom::ReadMeshFile(std::string filePath)
|
||||
if (!in.is_open()) {
|
||||
throw Resource::FailedLoadingException("Open mesh file failed");
|
||||
}
|
||||
unsigned int fileByteSize = in.tellg();
|
||||
unsigned int fileByteSize = static_cast<unsigned int>(in.tellg());
|
||||
in.seekg(0, std::ios_base::beg);
|
||||
|
||||
fileData = new char[fileByteSize];
|
||||
in.read(fileData, fileByteSize);
|
||||
in.close();
|
||||
|
||||
unsigned int offset = 0;
|
||||
std::size_t offset = 0;
|
||||
if (fileByteSize > 0) {
|
||||
ReadMeshFileHeader(offset, fileData, fileByteSize);
|
||||
ReadMeshFileHeader(offset, fileData);
|
||||
ReadMesh(offset, fileData, fileByteSize);
|
||||
}
|
||||
delete fileData;
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadMeshFileHeader(unsigned int& offset, char* fileData, unsigned int& fileByteSize)
|
||||
void RawModelCustom::ReadMeshFileHeader(std::size_t& offset, char* fileData)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
m_Vertices.resize(*(unsigned int*)(fileData + offset));
|
||||
m_Vertices.resize(static_cast<std::size_t>(*(unsigned int*)(fileData + offset)));
|
||||
offset += sizeof(unsigned int);
|
||||
m_Indices.resize(*(unsigned int*)(fileData + offset));
|
||||
m_Indices.resize(static_cast<std::size_t>(*(unsigned int*)(fileData + offset)));
|
||||
offset += sizeof(unsigned int);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadMesh(unsigned int& offset, char* fileData, unsigned int& fileByteSize)
|
||||
void RawModelCustom::ReadMesh(std::size_t& offset, char* fileData, const unsigned int& fileByteSize)
|
||||
{
|
||||
ReadVertices(offset, fileData, fileByteSize);
|
||||
ReadIndices(offset, fileData, fileByteSize);
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadVertices(unsigned int& offset, char* fileData, unsigned int& fileByteSize)
|
||||
void RawModelCustom::ReadVertices(std::size_t& offset, char* fileData, const unsigned int& fileByteSize)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
if (offset + m_Vertices.size() * sizeof(Vertex) > fileByteSize) {
|
||||
if (offset + m_Vertices.size() * sizeof(Vertex) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading vertices failed");
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ void RawModelCustom::ReadVertices(unsigned int& offset, char* fileData, unsigned
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadIndices(unsigned int& offset, char* fileData, unsigned int& fileByteSize)
|
||||
void RawModelCustom::ReadIndices(std::size_t& offset, char* fileData, const unsigned int& fileByteSize)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
if (offset + m_Indices.size() * sizeof(unsigned int) > fileByteSize) {
|
||||
@@ -90,35 +90,36 @@ void RawModelCustom::ReadMaterialFile(std::string filePath)
|
||||
if (!in.is_open()) {
|
||||
throw Resource::FailedLoadingException("Open material file failed");
|
||||
}
|
||||
unsigned int fileByteSize = in.tellg();
|
||||
|
||||
unsigned int fileByteSize = static_cast<unsigned int>(in.tellg());
|
||||
in.seekg(0, std::ios_base::beg);
|
||||
|
||||
fileData = new char[fileByteSize];
|
||||
in.read(fileData, fileByteSize);
|
||||
in.close();
|
||||
|
||||
unsigned int offset = 0;
|
||||
std::size_t offset = 0;
|
||||
if (fileByteSize > 0) {
|
||||
ReadMaterials(offset, fileData, fileByteSize);
|
||||
}
|
||||
delete fileData;
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadMaterials(unsigned int& offset, char* fileData, unsigned int& fileByteSize)
|
||||
void RawModelCustom::ReadMaterials(std::size_t& offset, char* fileData, const unsigned int& fileByteSize)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
unsigned int* numMaterials = (unsigned int*)(fileData);
|
||||
MaterialGroups.reserve(*numMaterials);
|
||||
offset += sizeof(unsigned int);
|
||||
|
||||
for (int i = 0; i < *numMaterials; i++) {
|
||||
for (unsigned int i = 0; i < *numMaterials; i++) {
|
||||
ReadMaterialSingle(offset, fileData, fileByteSize);
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadMaterialSingle(unsigned int &offset, char* fileData, unsigned int& fileByteSize)
|
||||
void RawModelCustom::ReadMaterialSingle(std::size_t& offset, char* fileData, const unsigned int& fileByteSize)
|
||||
{
|
||||
MaterialGroup newMaterial;
|
||||
|
||||
@@ -210,14 +211,14 @@ void RawModelCustom::ReadAnimationFile(std::string filePath)
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int fileByteSize = in.tellg();
|
||||
unsigned int fileByteSize = static_cast<unsigned int>(in.tellg());
|
||||
in.seekg(0, std::ios_base::beg);
|
||||
|
||||
fileData = new char[fileByteSize];
|
||||
in.read(fileData, fileByteSize);
|
||||
in.close();
|
||||
|
||||
unsigned int offset = 0;
|
||||
std::size_t offset = 0;
|
||||
if (fileByteSize > 0) {
|
||||
m_Skeleton = new Skeleton();
|
||||
|
||||
@@ -235,7 +236,7 @@ void RawModelCustom::ReadAnimationFile(std::string filePath)
|
||||
delete fileData;
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadAnimationBindPoses(unsigned int &offset, char* fileData, unsigned int& fileByteSize)
|
||||
void RawModelCustom::ReadAnimationBindPoses(std::size_t& offset, char* fileData, const unsigned int& fileByteSize)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
unsigned int* numBones = (unsigned int*)(fileData + offset);
|
||||
@@ -248,7 +249,7 @@ void RawModelCustom::ReadAnimationBindPoses(unsigned int &offset, char* fileData
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadAnimationJoint(unsigned int &offset, char* fileData, unsigned int& fileByteSize)
|
||||
void RawModelCustom::ReadAnimationJoint(std::size_t& offset, char* fileData, const unsigned int& fileByteSize)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
if (offset + sizeof(unsigned int) > fileByteSize) {
|
||||
@@ -290,14 +291,14 @@ void RawModelCustom::ReadAnimationJoint(unsigned int &offset, char* fileData, un
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadAnimationClips(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int numberOfClips)
|
||||
void RawModelCustom::ReadAnimationClips(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int numberOfClips)
|
||||
{
|
||||
for (unsigned int i = 0; i < numberOfClips; i++) {
|
||||
ReadAnimationClipSingle(offset, fileData, fileByteSize, i);
|
||||
}
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadAnimationClipSingle(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int clipIndex)
|
||||
void RawModelCustom::ReadAnimationClipSingle(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int clipIndex)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
Skeleton::Animation newAnimation;
|
||||
@@ -342,7 +343,7 @@ void RawModelCustom::ReadAnimationClipSingle(unsigned int &offset, char* fileDat
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadAnimationKeyFrame(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int nrOfJoints, Skeleton::Animation& animation)
|
||||
void RawModelCustom::ReadAnimationKeyFrame(std::size_t& offset, char* fileData, const unsigned int& fileByteSize, unsigned int numberOfJoints, Skeleton::Animation& animation)
|
||||
{
|
||||
Skeleton::Animation::Keyframe newKeyFrame;
|
||||
|
||||
@@ -358,12 +359,12 @@ void RawModelCustom::ReadAnimationKeyFrame(unsigned int &offset, char* fileData,
|
||||
newKeyFrame.Time = *(float*)(fileData + offset);
|
||||
offset += sizeof(float);
|
||||
|
||||
if (offset + sizeof(Skeleton::Animation::Keyframe::BoneProperty) * nrOfJoints> fileByteSize) {
|
||||
if (offset + sizeof(Skeleton::Animation::Keyframe::BoneProperty) * numberOfJoints> fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading AnimationKeyFrame joints failed");
|
||||
}
|
||||
|
||||
Skeleton::Animation::Keyframe::BoneProperty newBone;
|
||||
for (unsigned int i = 0; i < nrOfJoints; i++) {
|
||||
for (unsigned int i = 0; i < numberOfJoints; i++) {
|
||||
memcpy(&newBone, (fileData + offset), sizeof(Skeleton::Animation::Keyframe::BoneProperty));
|
||||
offset += sizeof(Skeleton::Animation::Keyframe::BoneProperty);
|
||||
newKeyFrame.BoneProperties[newBone.ID] = newBone;
|
||||
|
||||
@@ -4,6 +4,7 @@ RenderSystem::RenderSystem(World* world, EventBroker* eventBroker, const IRender
|
||||
: System(world, eventBroker)
|
||||
, m_Renderer(renderer)
|
||||
, m_RenderFrame(renderFrame)
|
||||
, m_World(world)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &RenderSystem::OnSetCamera);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &RenderSystem::OnInputCommand);
|
||||
@@ -30,27 +31,41 @@ bool RenderSystem::OnSetCamera(Events::SetCamera& e)
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs)
|
||||
bool RenderSystem::isChildOfACamera(EntityWrapper entity)
|
||||
{
|
||||
return entity.FirstParentWithComponent("Camera").Valid();
|
||||
}
|
||||
bool RenderSystem::isChildOfCurrentCamera(EntityWrapper entity)
|
||||
{
|
||||
return entity == m_CurrentCamera || entity.IsChildOf(m_CurrentCamera);
|
||||
}
|
||||
|
||||
void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& opaqueJobs, std::list<std::shared_ptr<RenderJob>>& transparentJobs)
|
||||
{
|
||||
auto models = m_World->GetComponents("Model");
|
||||
if (models == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& modelComponent : *models) {
|
||||
bool visible = modelComponent["Visible"];
|
||||
for (auto& cModel : *models) {
|
||||
bool visible = cModel["Visible"];
|
||||
if (!visible) {
|
||||
continue;
|
||||
}
|
||||
std::string resource = modelComponent["Resource"];
|
||||
std::string resource = cModel["Resource"];
|
||||
if (resource.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EntityWrapper entity(m_World, modelComponent.EntityID);
|
||||
EntityWrapper entity(m_World, cModel.EntityID);
|
||||
|
||||
// Don't render the local player
|
||||
if (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer)) {
|
||||
// Only render children of a camera if that camera is currently active
|
||||
if (isChildOfACamera(entity) && !isChildOfCurrentCamera(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Hide things parented to local player if they have the HiddenFromLocalPlayer component
|
||||
if (entity.HasComponent("HiddenForLocalPlayer") && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -68,10 +83,58 @@ void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs)
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 modelMatrix = Transform::ModelMatrix(modelComponent.EntityID, m_World);
|
||||
float fillPercentage = 0.f;
|
||||
glm::vec4 fillColor = glm::vec4(0);
|
||||
if(m_World->HasComponent(cModel.EntityID, "Fill")) {
|
||||
auto fillComponent = m_World->GetComponent(cModel.EntityID, "Fill");
|
||||
fillPercentage = (float)(double)fillComponent["Percentage"];
|
||||
fillColor = (glm::vec4)fillComponent["Color"];
|
||||
}
|
||||
|
||||
glm::mat4 modelMatrix = Transform::ModelMatrix(cModel.EntityID, m_World);
|
||||
for (auto matGroup : model->MaterialGroups()) {
|
||||
std::shared_ptr<ModelJob> modelJob = std::shared_ptr<ModelJob>(new ModelJob(model, m_Camera, modelMatrix, matGroup, modelComponent, m_World));
|
||||
jobs.push_back(modelJob);
|
||||
if (m_World->HasComponent(cModel.EntityID, "ExplosionEffect")) {
|
||||
auto explosionEffectComponent = m_World->GetComponent(cModel.EntityID, "ExplosionEffect");
|
||||
std::shared_ptr<ExplosionEffectJob> explosionEffectJob = std::shared_ptr<ExplosionEffectJob>(new ExplosionEffectJob(
|
||||
explosionEffectComponent,
|
||||
model,
|
||||
m_Camera,
|
||||
modelMatrix,
|
||||
matGroup,
|
||||
cModel,
|
||||
m_World,
|
||||
fillColor,
|
||||
fillPercentage
|
||||
));
|
||||
if(explosionEffectJob->Color.a != 1.f || explosionEffectJob->EndColor.a != 1.f || explosionEffectJob->DiffuseColor.a != 1.f) {
|
||||
cModel["Transparent"] = true;
|
||||
}
|
||||
|
||||
if (cModel["Transparent"]) {
|
||||
transparentJobs.push_back(explosionEffectJob);
|
||||
} else {
|
||||
opaqueJobs.push_back(explosionEffectJob);
|
||||
}
|
||||
} else {
|
||||
std::shared_ptr<ModelJob> modelJob = std::shared_ptr<ModelJob>(new ModelJob(
|
||||
model,
|
||||
m_Camera,
|
||||
modelMatrix,
|
||||
matGroup,
|
||||
cModel,
|
||||
m_World,
|
||||
fillColor,
|
||||
fillPercentage
|
||||
));
|
||||
if (modelJob->Color.a != 1.f || modelJob->DiffuseColor.a != 1.f) {
|
||||
cModel["Transparent"] = true;
|
||||
}
|
||||
if (cModel["Transparent"]) {
|
||||
transparentJobs.push_back(modelJob);
|
||||
} else {
|
||||
opaqueJobs.push_back(modelJob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,8 +219,8 @@ void RenderSystem::fillText(std::list<std::shared_ptr<RenderJob>>& jobs, World*
|
||||
}
|
||||
|
||||
glm::mat4 modelMatrix = Transform::ModelMatrix(textComponent.EntityID, world);
|
||||
std::shared_ptr<TextJob> modelJob = std::shared_ptr<TextJob>(new TextJob(modelMatrix, font, textComponent));
|
||||
jobs.push_back(modelJob);
|
||||
std::shared_ptr<TextJob> textJob = std::shared_ptr<TextJob>(new TextJob(modelMatrix, font, textComponent));
|
||||
jobs.push_back(textJob);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -177,12 +240,11 @@ void RenderSystem::Update(double dt)
|
||||
m_Camera->SetOrientation(Transform::AbsoluteOrientation(m_CurrentCamera));
|
||||
}
|
||||
|
||||
//Only supports opaque geometry atm
|
||||
|
||||
RenderScene scene;
|
||||
scene.Camera = m_Camera;
|
||||
scene.Viewport = Rectangle(1280, 720);
|
||||
fillModels(scene.ForwardJobs);
|
||||
fillModels(scene.OpaqueObjects, scene.TransparentObjects);
|
||||
fillPointLights(scene.PointLightJobs, m_World);
|
||||
fillDirectionalLights(scene.DirectionalLightJobs, m_World);
|
||||
fillText(scene.TextJobs, m_World);
|
||||
|
||||
@@ -58,11 +58,24 @@ void Renderer::InitializeWindow()
|
||||
LOG_ERROR("GLEW: Initialization failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int windowSize[2];
|
||||
glfwGetWindowSize(m_Window, &windowSize[0], &windowSize[1]);
|
||||
m_ViewportSize = Rectangle(windowSize[0], windowSize[1]);
|
||||
}
|
||||
|
||||
void Renderer::InitializeShaders()
|
||||
{
|
||||
m_BasicForwardProgram = ResourceManager::Load<ShaderProgram>("#m_BasicForwardProgram");
|
||||
m_ExplosionEffectProgram = ResourceManager::Load<ShaderProgram>("#ExplosionEffectProgram");
|
||||
//m_ExplosionEffectProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/ExplosionEffect.vert.glsl")));
|
||||
//m_ExplosionEffectProgram->AddShader(std::shared_ptr<Shader>(new GeometryShader("Shaders/ExplosionEffect.geom.glsl")));
|
||||
//m_ExplosionEffectProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ExplosionEffect.frag.glsl")));
|
||||
//m_ExplosionEffectProgram->Compile();
|
||||
//m_ExplosionEffectProgram->Link();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Renderer::InputUpdate(double dt)
|
||||
@@ -98,6 +111,7 @@ void Renderer::Draw(RenderFrame& frame)
|
||||
m_LightCullingPass->FillLightList(*scene);
|
||||
m_LightCullingPass->CullLights(*scene);
|
||||
m_DrawFinalPass->Draw(*scene);
|
||||
//m_DrawScenePass->Draw(*scene);
|
||||
|
||||
GLERROR("Renderer::Draw m_DrawScenePass->Draw");
|
||||
|
||||
@@ -133,14 +147,14 @@ PickData Renderer::Pick(glm::vec2 screenCoord)
|
||||
void Renderer::InitializeTextures()
|
||||
{
|
||||
m_ErrorTexture = ResourceManager::Load<Texture>("Textures/Core/ErrorTexture.png");
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png");
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/White.png");
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SortRenderJobsByDepth(RenderScene &scene)
|
||||
{
|
||||
//Sort all forward jobs so transparency is good.
|
||||
scene.ForwardJobs.sort(Renderer::DepthSort);
|
||||
scene.TransparentObjects.sort(Renderer::DepthSort);
|
||||
}
|
||||
|
||||
void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type)
|
||||
|
||||
@@ -21,7 +21,7 @@ GLuint Shader::CompileShader(GLenum shaderType, std::string fileName)
|
||||
return 0;
|
||||
|
||||
const GLchar* shaderFiles = shaderFile.c_str();
|
||||
const GLint length = shaderFile.length();
|
||||
const GLint length = static_cast<GLint>(shaderFile.length());
|
||||
glShaderSource(shader, 1, &shaderFiles, &length);
|
||||
if (GLERROR("glShaderSource"))
|
||||
return 0;
|
||||
|
||||
@@ -53,11 +53,11 @@ std::vector<glm::mat4> Skeleton::GetFrameBones(const Animation& animation, doubl
|
||||
|
||||
const Animation::Keyframe& currentFrame = animation.Keyframes[currentKeyframeIndex];
|
||||
const Animation::Keyframe& nextFrame = animation.Keyframes[(currentKeyframeIndex + 1) % animation.Keyframes.size()];
|
||||
float alpha = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
|
||||
double alpha = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
|
||||
|
||||
//auto animationFrame = Animations[""].Keyframes[frame];
|
||||
std::map<int, glm::mat4> frameBones;
|
||||
AccumulateBoneTransforms(noRootMotion, currentFrame, nextFrame, alpha, frameBones, RootBone, glm::mat4(1));
|
||||
AccumulateBoneTransforms(noRootMotion, currentFrame, nextFrame, static_cast<float>(alpha), frameBones, RootBone, glm::mat4(1));
|
||||
|
||||
std::vector<glm::mat4> finalMatrices;
|
||||
for (auto &kv : frameBones) {
|
||||
|
||||
@@ -116,7 +116,11 @@ void SoundSystem::updateEmitters(double dt)
|
||||
setSourcePos(it->second->ALsource, nextPos);
|
||||
setSourceVel(it->second->ALsource, velocity);
|
||||
float gain;
|
||||
(bool)(it->second->Type) ? gain = m_SFXVolumeChannel : gain = m_BGMVolumeChannel;
|
||||
if (it->second->Type == SoundType::SFX) {
|
||||
gain = m_SFXVolumeChannel;
|
||||
} else if (it->second->Type == SoundType::BGM) {
|
||||
gain = m_BGMVolumeChannel;
|
||||
}
|
||||
auto emitter = m_World->GetComponent(it->first, "SoundEmitter");
|
||||
setSoundProperties(it->second->ALsource, &emitter);
|
||||
|
||||
|
||||
+19
-7
@@ -1,5 +1,6 @@
|
||||
#include "Game.h"
|
||||
#include "Collision/CollidableOctreeSystem.h"
|
||||
#include "Collision/EntityAABB.h"
|
||||
#include "Collision/TriggerSystem.h"
|
||||
#include "Collision/CollisionSystem.h"
|
||||
#include "Systems/RaptorCopterSystem.h"
|
||||
@@ -10,6 +11,9 @@
|
||||
#include "Core/EntityFileWriter.h"
|
||||
#include "Game/Systems/CapturePointSystem.h"
|
||||
#include "Game/Systems/WeaponSystem.h"
|
||||
#include "Game/Systems/PlayerHUD.h"
|
||||
#include "Game/Systems/LifetimeSystem.h"
|
||||
#include "../Engine/Rendering/AnimationSystem.h"
|
||||
|
||||
Game::Game(int argc, char* argv[])
|
||||
{
|
||||
@@ -39,7 +43,7 @@ Game::Game(int argc, char* argv[])
|
||||
0,
|
||||
m_Config->Get<int>("Video.Width", 1280),
|
||||
m_Config->Get<int>("Video.Height", 720)
|
||||
));
|
||||
));
|
||||
m_Renderer->Initialize();
|
||||
//m_Renderer->Camera()->SetFOV(glm::radians(m_Config->Get<float>("Video.FOV", 90.f)));
|
||||
m_RenderFrame = new RenderFrame();
|
||||
@@ -69,29 +73,36 @@ Game::Game(int argc, char* argv[])
|
||||
|
||||
|
||||
// Create Octrees
|
||||
m_OctreeCollision = new Octree<AABB>(AABB(glm::vec3(-100), glm::vec3(100)), 4);
|
||||
m_OctreeFrustrumCulling = new Octree<AABB>(AABB(glm::vec3(-100), glm::vec3(100)), 4);
|
||||
m_OctreeCollision = new Octree<EntityAABB>(AABB(glm::vec3(-100), glm::vec3(100)), 4);
|
||||
m_OctreeTrigger = new Octree<EntityAABB>(AABB(glm::vec3(-100), glm::vec3(100)), 4);
|
||||
m_OctreeFrustrumCulling = new Octree<EntityAABB>(AABB(glm::vec3(-100), glm::vec3(100)), 4);
|
||||
// Create system pipeline
|
||||
m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker);
|
||||
|
||||
// All systems with orderlevel 0 will be updated first.
|
||||
unsigned int updateOrderLevel = 0;
|
||||
m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel);
|
||||
//m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<ExplosionEffectSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer);
|
||||
m_SystemPipeline->AddSystem<LifetimeSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<CapturePointSystem>(updateOrderLevel);
|
||||
// Populate Octree with collidables
|
||||
++updateOrderLevel;
|
||||
m_SystemPipeline->AddSystem<CollidableOctreeSystem>(updateOrderLevel, m_OctreeCollision);
|
||||
m_SystemPipeline->AddSystem<CollidableOctreeSystem>(updateOrderLevel, m_OctreeCollision, "Collidable");
|
||||
m_SystemPipeline->AddSystem<CollidableOctreeSystem>(updateOrderLevel, m_OctreeTrigger, "Player");
|
||||
m_SystemPipeline->AddSystem<PlayerHUD>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<AnimationSystem>(updateOrderLevel);
|
||||
|
||||
// Collision and TriggerSystem should update after player.
|
||||
++updateOrderLevel;
|
||||
m_SystemPipeline->AddSystem<CollisionSystem>(updateOrderLevel, m_OctreeCollision);
|
||||
m_SystemPipeline->AddSystem<TriggerSystem>(updateOrderLevel, m_OctreeCollision);
|
||||
m_SystemPipeline->AddSystem<TriggerSystem>(updateOrderLevel, m_OctreeTrigger);
|
||||
++updateOrderLevel;
|
||||
m_SystemPipeline->AddSystem<CapturePointSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<RenderSystem>(updateOrderLevel, m_Renderer, m_RenderFrame);
|
||||
++updateOrderLevel;
|
||||
m_SystemPipeline->AddSystem<EditorSystem>(updateOrderLevel, m_Renderer, m_RenderFrame);
|
||||
@@ -114,6 +125,7 @@ Game::~Game()
|
||||
delete m_SoundSystem;
|
||||
delete m_OctreeFrustrumCulling;
|
||||
delete m_OctreeCollision;
|
||||
delete m_OctreeTrigger;
|
||||
delete m_World;
|
||||
delete m_FrameStack;
|
||||
delete m_InputProxy;
|
||||
|
||||
@@ -13,27 +13,27 @@ CapturePointSystem::CapturePointSystem(World* world, EventBroker* eventBroker)
|
||||
|
||||
//here all capturepoints will update their component
|
||||
//NOTE: needs to run each frame, since we're possibly modifying the captureTimer for the capturePoints by dt
|
||||
void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& capturePoint, double dt)
|
||||
void CapturePointSystem::UpdateComponent(EntityWrapper& capturePointEntity, ComponentWrapper& cCapturePoint, double dt)
|
||||
{
|
||||
if (m_WinnerWasFound) {
|
||||
return;
|
||||
}
|
||||
const int capturePointNumber = capturePoint["CapturePointNumber"];
|
||||
const bool hasTeamComponent = m_World->HasComponent(capturePoint.EntityID, "Team");
|
||||
const int capturePointNumber = cCapturePoint["CapturePointNumber"];
|
||||
const bool hasTeamComponent = capturePointEntity.HasComponent("Team");
|
||||
|
||||
//if point doesnt have a teamComponent yet, add one. since:
|
||||
//what if capture point has no team -> we cant get/use the team enum from it...
|
||||
if (!hasTeamComponent) {
|
||||
m_World->AttachComponent(capturePoint.EntityID, "Team");
|
||||
ComponentWrapper& teamComponent = m_World->GetComponent(capturePoint.EntityID, "Team");
|
||||
m_World->AttachComponent(cCapturePoint.EntityID, "Team");
|
||||
ComponentWrapper& teamComponent = capturePointEntity["Team"];
|
||||
teamComponent["Team"] = (int)teamComponent["Team"].Enum("Spectator");
|
||||
}
|
||||
ComponentWrapper& teamComponent = m_World->GetComponent(capturePoint.EntityID, "Team");
|
||||
ComponentWrapper& teamComponent = capturePointEntity["Team"];
|
||||
const int redTeam = (int)teamComponent["Team"].Enum("Red");
|
||||
const int blueTeam = (int)teamComponent["Team"].Enum("Blue");
|
||||
const int spectatorTeam = (int)teamComponent["Team"].Enum("Spectator");
|
||||
|
||||
int homePointForTeam = (int)capturePoint["HomePointForTeam"];
|
||||
int homePointForTeam = (int)cCapturePoint["HomePointForTeam"];
|
||||
if (m_NumberOfCapturePoints == 0 && capturePointNumber != 0 && (homePointForTeam == redTeam || homePointForTeam == blueTeam)) {
|
||||
m_NumberOfCapturePoints = capturePointNumber + 1;//ex 2 -> 0,1,2 = 3
|
||||
if (homePointForTeam == redTeam) {
|
||||
@@ -46,8 +46,8 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper
|
||||
}
|
||||
|
||||
//if we havent received all capturepoints yet, just return
|
||||
if (m_NumberOfCapturePoints == 0 || m_NumberOfCapturePoints != m_CapturePointNumberToEntityIDMap.size()) {
|
||||
m_CapturePointNumberToEntityIDMap.insert(std::make_pair(capturePointNumber, capturePoint.EntityID));
|
||||
if (m_NumberOfCapturePoints == 0 || m_NumberOfCapturePoints != m_CapturePointNumberToEntityMap.size()) {
|
||||
m_CapturePointNumberToEntityMap.insert(std::make_pair(capturePointNumber, capturePointEntity));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -55,21 +55,21 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper
|
||||
int ownedBy = teamComponent["Team"];
|
||||
int redTeamPlayersStandingInside = 0;
|
||||
int blueTeamPlayersStandingInside = 0;
|
||||
if (entity.HasComponent("Model")) {
|
||||
if (capturePointEntity.HasComponent("Model")) {
|
||||
//Now sets team color to the capturepoint, or white if it is uncaptured.
|
||||
entity["Model"]["Color"] = ownedBy == blueTeam ? glm::vec4(0, 0.2f, 1, 1) : ownedBy == redTeam ? glm::vec4(1, 0.2f, 0, 1) : glm::vec4(1, 1, 1, 1);
|
||||
capturePointEntity["Model"]["Color"] = ownedBy == blueTeam ? glm::vec4(0, 0.2f, 1, 1) : ownedBy == redTeam ? glm::vec4(1, 0.2f, 0, 1) : glm::vec4(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
//calculate next possible capturePoint for both teams
|
||||
std::map<std::string, int> nextPossibleCapturePoint;
|
||||
nextPossibleCapturePoint["Red"] = -1;
|
||||
nextPossibleCapturePoint["Blue"] = -1;
|
||||
for (size_t i = 0; i < m_NumberOfCapturePoints; i++)
|
||||
for (int i = 0; i < m_NumberOfCapturePoints; i++)
|
||||
{
|
||||
if (!m_World->HasComponent(m_CapturePointNumberToEntityIDMap[i], "Team")) {
|
||||
if (!m_CapturePointNumberToEntityMap[i].HasComponent("Team")) {
|
||||
continue;
|
||||
}
|
||||
ComponentWrapper& capturePointOwnedBy = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team");
|
||||
ComponentWrapper& capturePointOwnedBy = m_CapturePointNumberToEntityMap[i]["Team"];
|
||||
if ((int)capturePointOwnedBy["Team"] == redTeam && m_RedTeamHomeCapturePoint == 0) {
|
||||
nextPossibleCapturePoint["Red"] = i + 1;
|
||||
}
|
||||
@@ -79,10 +79,10 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper
|
||||
}
|
||||
for (int i = m_NumberOfCapturePoints - 1; i >= 0; i--)
|
||||
{
|
||||
if (!m_World->HasComponent(m_CapturePointNumberToEntityIDMap[i], "Team")) {
|
||||
if (!m_CapturePointNumberToEntityMap[i].HasComponent("Team")) {
|
||||
continue;
|
||||
}
|
||||
ComponentWrapper& capturePointOwnedBy = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team");
|
||||
ComponentWrapper& capturePointOwnedBy = m_CapturePointNumberToEntityMap[i]["Team"];
|
||||
if ((int)capturePointOwnedBy["Team"] == redTeam && m_RedTeamHomeCapturePoint != 0) {
|
||||
nextPossibleCapturePoint["Red"] = i - 1;
|
||||
}
|
||||
@@ -93,9 +93,9 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper
|
||||
|
||||
//reset timers and reset the bool that triggers this
|
||||
if (m_ResetTimers) {
|
||||
for (size_t i = 0; i < m_NumberOfCapturePoints; i++)
|
||||
for (int i = 0; i < m_NumberOfCapturePoints; i++)
|
||||
{
|
||||
ComponentWrapper& capturePoint = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "CapturePoint");
|
||||
ComponentWrapper& capturePoint = m_CapturePointNumberToEntityMap[i]["CapturePoint"];
|
||||
if ((int)capturePoint["CapturePointNumber"] != nextPossibleCapturePoint["Red"] &&
|
||||
(int)capturePoint["CapturePointNumber"] != nextPossibleCapturePoint["Blue"]) {
|
||||
capturePoint["CaptureTimer"] = 0.0;
|
||||
@@ -106,34 +106,35 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper
|
||||
|
||||
//colorize next possible capturepoint
|
||||
if (nextPossibleCapturePoint["Red"] == capturePointNumber) {
|
||||
entity["Model"]["Color"] = glm::vec4(1, 1, 0, 1);
|
||||
capturePointEntity["Model"]["Color"] = glm::vec4(1, 1, 0, 1);
|
||||
}
|
||||
if (nextPossibleCapturePoint["Blue"] == capturePointNumber) {
|
||||
entity["Model"]["Color"] = glm::vec4(0, 1, 1, 1);
|
||||
capturePointEntity["Model"]["Color"] = glm::vec4(0, 1, 1, 1);
|
||||
}
|
||||
|
||||
//check how many players are standing inside and are healthy
|
||||
for (size_t i = m_ETriggerTouchVector.size(); i > 0; i--)
|
||||
{
|
||||
auto triggerTouched = m_ETriggerTouchVector[i - 1];
|
||||
if (std::get<1>(triggerTouched) == capturePoint.EntityID) {
|
||||
if (std::get<1>(triggerTouched) == capturePointEntity) {
|
||||
//some player has touched this - lets figure out: what team, health
|
||||
EntityID playerID = std::get<0>(triggerTouched);
|
||||
if (!m_World->HasComponent(playerID, "Player")) {
|
||||
EntityWrapper player = std::get<0>(triggerTouched);
|
||||
//check if its really a player that has triggered the touch
|
||||
if (!player.HasComponent("Player")) {
|
||||
//if a non-player has entered the capturePoint, just erase that event and continue
|
||||
m_ETriggerTouchVector.erase(m_ETriggerTouchVector.begin() + i - 1);
|
||||
continue;
|
||||
}
|
||||
bool hasHealthComponent = m_World->HasComponent(playerID, "Health");
|
||||
bool hasHealthComponent = player.HasComponent("Health");
|
||||
if (hasHealthComponent) {
|
||||
double currentHealth = m_World->GetComponent(playerID, "Health")["Health"];
|
||||
double currentHealth = player["Health"]["Health"];
|
||||
//check if player is dead
|
||||
if ((int)currentHealth == 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//check team - spectatorNumber = "no team"
|
||||
int teamNumber = m_World->GetComponent(playerID, "Team")["Team"];
|
||||
int teamNumber = player["Team"]["Team"];
|
||||
if (teamNumber == redTeam) {
|
||||
redTeamPlayersStandingInside++;
|
||||
} else if (teamNumber == blueTeam) {
|
||||
@@ -169,24 +170,24 @@ void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper
|
||||
//B. at most one of the teams have players inside
|
||||
//if capturePoint is not owned by the take-over team, just modify the CaptureTimer accordingly
|
||||
if (ownedBy != currentTeam && canCapture) {
|
||||
if (abs((double)capturePoint["CaptureTimer"]) < 0.001f) {
|
||||
if (abs((double)cCapturePoint["CaptureTimer"]) < 0.001f) {
|
||||
LOG_DEBUG("Point is being captured by team %i", currentTeam); //Remove when we tested sufficiently.
|
||||
}
|
||||
capturePoint["CaptureTimer"] = (double)capturePoint["CaptureTimer"] + timerDeltaChange;
|
||||
cCapturePoint["CaptureTimer"] = (double)cCapturePoint["CaptureTimer"] + timerDeltaChange;
|
||||
}
|
||||
//if capturePoint is owned by the team, and the other team has been trying to take it, then increase/decrease the timer towards 0.0
|
||||
if ((ownedBy == currentTeam && currentTeam == redTeam && (double)capturePoint["CaptureTimer"] < 0.0) ||
|
||||
(ownedBy == currentTeam && currentTeam == blueTeam && (double)capturePoint["CaptureTimer"] > 0.0)) {
|
||||
capturePoint["CaptureTimer"] = (double)capturePoint["CaptureTimer"] + timerDeltaChange;
|
||||
if ((ownedBy == currentTeam && currentTeam == redTeam && (double)cCapturePoint["CaptureTimer"] < 0.0) ||
|
||||
(ownedBy == currentTeam && currentTeam == blueTeam && (double)cCapturePoint["CaptureTimer"] > 0.0)) {
|
||||
cCapturePoint["CaptureTimer"] = (double)cCapturePoint["CaptureTimer"] + timerDeltaChange;
|
||||
}
|
||||
//check if captureTimer > m_CaptureTimeToTakeOver and if so change owner and publish the eCaptured event
|
||||
if (abs((double)capturePoint["CaptureTimer"]) > abs(m_CaptureTimeToTakeOver) && canCapture) {
|
||||
if (abs((double)cCapturePoint["CaptureTimer"]) > abs(m_CaptureTimeToTakeOver) && canCapture) {
|
||||
teamComponent["Team"] = currentTeam;
|
||||
capturePoint["CaptureTimer"] = 0.0;
|
||||
cCapturePoint["CaptureTimer"] = 0.0;
|
||||
//publish Captured event
|
||||
LOG_DEBUG("Point is captured by team %i!", currentTeam); //Remove when we tested sufficiently.
|
||||
Events::Captured e;
|
||||
e.CapturePointID = capturePoint.EntityID;
|
||||
e.CapturePointID = cCapturePoint.EntityID;
|
||||
e.TeamNumberThatCapturedCapturePoint = currentTeam;
|
||||
m_EventBroker->Publish(e);
|
||||
//NextPossibleCapturePoint will be calculated in the next update...
|
||||
|
||||
@@ -45,10 +45,16 @@ void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& comp
|
||||
}
|
||||
}
|
||||
|
||||
bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e)
|
||||
bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e)
|
||||
{
|
||||
//save the changed HP to a vector. it will be taken care of in UpdateComponent
|
||||
//m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerDamagedID, -e.DamageAmount));
|
||||
ComponentWrapper cHealth = e.Player["Health"];
|
||||
double& health = cHealth["Health"];
|
||||
health -= e.Damage;
|
||||
|
||||
if (health <= 0.0) {
|
||||
m_World->DeleteEntity(e.Player.ID);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "Systems/LifetimeSystem.h"
|
||||
|
||||
void LifetimeSystem::Update(double dt)
|
||||
{
|
||||
for (auto& e : m_Deletions) {
|
||||
m_World->DeleteEntity(e.ID);
|
||||
}
|
||||
m_Deletions.clear();
|
||||
}
|
||||
|
||||
void LifetimeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cLifetime, double dt)
|
||||
{
|
||||
if (dt == 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!entity.Valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
double& lifetime = cLifetime["Lifetime"];
|
||||
lifetime -= dt;
|
||||
|
||||
if (lifetime <= 0.0) {
|
||||
m_Deletions.push_back(entity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "Game/Systems/PlayerHUD.h"
|
||||
|
||||
PlayerHUD::PlayerHUD(World* world, EventBroker* eventBrokerer)
|
||||
:System(world, eventBrokerer)
|
||||
, m_World(world)
|
||||
, m_EventBroker(eventBrokerer)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
PlayerHUD::~PlayerHUD()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PlayerHUD::Update(double dt)
|
||||
{
|
||||
auto healthHUDs = m_World->GetComponents("HealthHUD");
|
||||
if (healthHUDs == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& healthHUDComponent : *healthHUDs) {
|
||||
EntityWrapper entity = EntityWrapper(m_World, healthHUDComponent.EntityID);
|
||||
|
||||
EntityWrapper entityIDParent = entity;
|
||||
while (entityIDParent.Parent().Valid()) {
|
||||
entityIDParent = entityIDParent.Parent();
|
||||
|
||||
if (entityIDParent.HasComponent("Health")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (entityIDParent.HasComponent("Health")) {
|
||||
|
||||
if (entity.HasComponent("Text")) {
|
||||
std::string s = "";
|
||||
s = s + std::to_string((int)(double)entityIDParent["Health"]["Health"]);
|
||||
s = s + "/";
|
||||
s = s + std::to_string((int)(double)entityIDParent["Health"]["MaxHealth"]);
|
||||
float healthPercentage = (double)entityIDParent["Health"]["Health"]/(double)entityIDParent["Health"]["MaxHealth"];
|
||||
(glm::vec4&)entity["Text"]["Color"] = glm::vec4(1.0 - healthPercentage, 0.f, healthPercentage, 1.f);
|
||||
entity["Text"]["Content"] = s;
|
||||
}
|
||||
|
||||
if(entity.HasComponent("Fill")) {
|
||||
float healthPercentage = (double)entityIDParent["Health"]["Health"]/(double)entityIDParent["Health"]["MaxHealth"];
|
||||
(glm::vec4&)entity["Fill"]["Color"] = glm::vec4(1.0 - healthPercentage, 0.f, healthPercentage, 0.f);
|
||||
(double&)entity["Fill"]["Percentage"] = healthPercentage;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,15 +36,18 @@ void PlayerMovementSystem::Update(double dt)
|
||||
glm::vec3& ori = cTransform["Orientation"];
|
||||
ori.y += controller->Rotation().y;
|
||||
|
||||
float playerMovementSpeed = player["Player"]["MovementSpeed"];
|
||||
float playerCrouchSpeed = player["Player"]["CrouchSpeed"];
|
||||
|
||||
if (player.HasComponent("Physics")) {
|
||||
ComponentWrapper cPhysics = player["Physics"];
|
||||
|
||||
glm::vec3 wishDirection = controller->Movement() * glm::inverse(glm::quat(ori));
|
||||
float wishSpeed;
|
||||
if (controller->Crouching()) {
|
||||
wishSpeed = player["Player"]["CrouchSpeed"];
|
||||
wishSpeed = playerCrouchSpeed;
|
||||
} else {
|
||||
wishSpeed = player["Player"]["MovementSpeed"];
|
||||
wishSpeed = playerMovementSpeed;
|
||||
}
|
||||
glm::vec3& velocity = cPhysics["Velocity"];
|
||||
ImGui::Text("velocity: (%f, %f, %f)", velocity.x, velocity.y, velocity.z);
|
||||
@@ -73,20 +76,51 @@ void PlayerMovementSystem::Update(double dt)
|
||||
ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity));
|
||||
}
|
||||
|
||||
if (controller->Jumping() && !controller->Crouching() && velocity.y == 0.f) {
|
||||
if (controller->Jumping() && !controller->Crouching() && (velocity.y == 0.f || !controller->DoubleJumping())) {
|
||||
if (velocity.y == 0.f) {
|
||||
controller->SetDoubleJumping(false);
|
||||
}
|
||||
else {
|
||||
controller->SetDoubleJumping(true);
|
||||
}
|
||||
velocity.y += 4.f;
|
||||
}
|
||||
|
||||
//if (player.HasComponent("AABB")) {
|
||||
// glm::vec3& size = player["AABB"]["Size"];
|
||||
// if (controller->Crouching()) {
|
||||
// size = glm::vec3(1.f, 1.f, 1.f);
|
||||
// } else {
|
||||
// size = glm::vec3(1.f, 1.6f, 1.f);
|
||||
// }
|
||||
//}
|
||||
if (player.HasComponent("AABB")) {
|
||||
glm::vec3& size = player["AABB"]["Size"];
|
||||
if (controller->Crouching()) {
|
||||
size = glm::vec3(1.f, 1.f, 1.f);
|
||||
} else {
|
||||
size = glm::vec3(1.f, 1.6f, 1.f);
|
||||
}
|
||||
}
|
||||
|
||||
// Animations
|
||||
EntityWrapper playerModel = player.FirstChildByName("PlayerModel");
|
||||
if (playerModel.Valid()) {
|
||||
ComponentWrapper cAnimation = playerModel["Animation"];
|
||||
|
||||
float movementLength = glm::length(groundVelocity);
|
||||
if (glm::length(controller->Movement()) > 0.f) {
|
||||
if (controller->Crouching()) {
|
||||
cAnimation["Name"] = "Crouch Walk";
|
||||
(double&)cAnimation["Speed"] = 1.f * -glm::sign(controller->Movement().z);
|
||||
} else {
|
||||
cAnimation["Name"] = "Run";
|
||||
(double&)cAnimation["Speed"] = 2.f * -glm::sign(controller->Movement().z);
|
||||
}
|
||||
} else {
|
||||
if (controller->Crouching()) {
|
||||
cAnimation["Name"] = "Crouch";
|
||||
(double&)cAnimation["Speed"] = 1.f;
|
||||
} else {
|
||||
cAnimation["Name"] = "Hold Pos";
|
||||
(double&)cAnimation["Speed"] = 1.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
controller->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,10 +102,10 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||
}
|
||||
|
||||
// TODO: Set the player name to whatever
|
||||
//EntityWrapper playerName = e.Player.FirstChildByName("PlayerName");
|
||||
//if (playerName.Valid()) {
|
||||
// playerName["Text"]["Content"] = ???;
|
||||
//}
|
||||
EntityWrapper playerName = e.Player.FirstChildByName("PlayerName");
|
||||
if (playerName.Valid()) {
|
||||
playerName["Text"]["Content"] = e.PlayerName;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -30,7 +30,7 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent /
|
||||
if (spawnPoints.size() > 1) {
|
||||
static std::random_device randomDevice;
|
||||
static std::mt19937 randomGenerator(randomDevice());
|
||||
std::uniform_int_distribution<> distribution(0, std::distance(spawnPoints.begin(), spawnPoints.end()) - 1);
|
||||
std::uniform_int_distribution<> distribution(0, static_cast<int>(std::distance(spawnPoints.begin(), spawnPoints.end())) - 1);
|
||||
auto randomSpawnPointIt = spawnPoints.begin();
|
||||
std::advance(randomSpawnPointIt, distribution(randomGenerator));
|
||||
spawnPoint = *randomSpawnPointIt;
|
||||
@@ -50,7 +50,8 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent /
|
||||
|
||||
// Set its position and orientation to that of the SpawnPoint
|
||||
spawnedEntity["Transform"]["Position"] = Transform::AbsolutePosition(spawnPoint.World, spawnPoint.ID);
|
||||
spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint.World, spawnPoint.ID));
|
||||
// TODO: Quaternions, bitch
|
||||
//spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint.World, spawnPoint.ID));
|
||||
|
||||
return spawnedEntity;
|
||||
}
|
||||
|
||||
@@ -37,17 +37,74 @@ bool WeaponSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
|
||||
if (e.Command == "PrimaryFire" && e.Value > 0) {
|
||||
Events::Shoot eShoot;
|
||||
eShoot.Player = m_LocalPlayer;
|
||||
if (e.PlayerID == -1) {
|
||||
eShoot.Player = m_LocalPlayer;
|
||||
} else {
|
||||
eShoot.Player = e.Player;
|
||||
}
|
||||
m_EventBroker->Publish(eShoot);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WeaponSystem::OnShoot(const Events::Shoot& eShoot) {
|
||||
bool WeaponSystem::OnShoot(Events::Shoot& eShoot)
|
||||
{
|
||||
if (!eShoot.Player.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Weapon firing effects here
|
||||
|
||||
auto rayRed = ResourceManager::Load<EntityFile>("Schema/Entities/RayRed.xml");
|
||||
auto rayBlue = ResourceManager::Load<EntityFile>("Schema/Entities/RayBlue.xml");
|
||||
|
||||
EntityWrapper weapon = eShoot.Player.FirstChildByName("WeaponMuzzle");
|
||||
if (weapon.Valid()) {
|
||||
EntityWrapper ray;
|
||||
if ((ComponentInfo::EnumType)eShoot.Player["Team"]["Team"] == eShoot.Player["Team"]["Team"].Enum("Red")) {
|
||||
EntityFileParser parser(rayRed);
|
||||
EntityID rayID = parser.MergeEntities(m_World);
|
||||
ray = EntityWrapper(m_World, rayID);
|
||||
} else {
|
||||
EntityFileParser parser(rayBlue);
|
||||
EntityID rayID = parser.MergeEntities(m_World);
|
||||
ray = EntityWrapper(m_World, rayID);
|
||||
}
|
||||
|
||||
glm::mat4 transformation = Transform::AbsoluteTransformation(weapon);
|
||||
glm::vec3 scale;
|
||||
glm::vec3 translation;
|
||||
glm::quat orientation;
|
||||
glm::vec3 skew;
|
||||
glm::vec4 perspective;
|
||||
glm::decompose(transformation, scale, orientation, translation, skew, perspective);
|
||||
|
||||
// Matrix to euler angles
|
||||
glm::vec3 euler;
|
||||
euler.y = glm::asin(-transformation[0][2]);
|
||||
if (cos(euler.y) != 0) {
|
||||
euler.x = atan2(transformation[1][2], transformation[2][2]);
|
||||
euler.z = atan2(transformation[0][1], transformation[0][0]);
|
||||
} else {
|
||||
euler.x = atan2(-transformation[2][0], transformation[1][1]);
|
||||
euler.z = 0;
|
||||
}
|
||||
|
||||
//LOG_DEBUG("rotation: %f %f %f", euler.x, euler.y, euler.z);
|
||||
(glm::vec3&)ray["Transform"]["Position"] = translation;
|
||||
(glm::vec3&)ray["Transform"]["Orientation"] = euler;
|
||||
//(glm::vec3&)ray["Transform"]["Orientation"] = Transform::AbsoluteOrientationEuler(weapon);
|
||||
}
|
||||
|
||||
// Only run further picking code client-side!
|
||||
if (eShoot.Player != m_LocalPlayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Screen center, based on current resolution!
|
||||
//TODO: check if player has enough ammo and if weapon has a cooldown or not
|
||||
Rectangle screenResolution = m_Renderer->Resolution();
|
||||
// TODO: check if player has enough ammo and if weapon has a cooldown or not
|
||||
Rectangle screenResolution = m_Renderer->GetViewportSize();
|
||||
glm::vec2 centerScreen = glm::vec2(screenResolution.Width / 2, screenResolution.Height / 2);
|
||||
|
||||
// TODO: check if player has enough ammo and if weapon has a cooldown or not
|
||||
|
||||
Reference in New Issue
Block a user