Made TriggerSystem make use of Octree

This commit is contained in:
2016-01-27 13:35:16 +01:00
parent 8bed5194d8
commit 5fcd26cd3e
20 changed files with 145 additions and 130 deletions
@@ -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);
}
+6 -2
View File
@@ -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;
}
}
+3 -3
View File
@@ -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;
+44 -51
View File
@@ -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;
-4
View File
@@ -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));
-5
View File
@@ -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)) {
+1 -1
View File
@@ -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"]));