Made TriggerSystem make use of Octree
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);
|
||||
}
|
||||
|
||||
@@ -283,7 +283,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 +294,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,12 +9,12 @@ 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) {
|
||||
@@ -22,7 +22,7 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
|
||||
}
|
||||
|
||||
// Collide against octree
|
||||
std::vector<AABB> octreeResult;
|
||||
std::vector<EntityAABB> octreeResult;
|
||||
m_Octree->ObjectsInSameRegion(*boundingBox, octreeResult);
|
||||
for (auto& boxB : octreeResult) {
|
||||
glm::vec3 resolutionVector;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -97,11 +97,6 @@ EntityWrapper::operator EntityID() const
|
||||
return this->ID;
|
||||
}
|
||||
|
||||
EntityWrapper::operator bool()
|
||||
{
|
||||
return this->Valid();
|
||||
}
|
||||
|
||||
EntityWrapper EntityWrapper::firstChildByNameRecursive(const std::string& name, EntityID parent)
|
||||
{
|
||||
if (!this->World->ValidEntity(parent)) {
|
||||
|
||||
@@ -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"]));
|
||||
|
||||
Reference in New Issue
Block a user