summaryrefslogtreecommitdiff
path: root/engine-ocean/Game/Systems/CollisionSystems/UniformGrid/uniformgrid.cpp
diff options
context:
space:
mode:
authorjjesswan <jessica_wan@brown.edu>2024-04-22 21:56:26 -0400
committerjjesswan <jessica_wan@brown.edu>2024-04-22 21:56:26 -0400
commita556b45abf18f1bd509daaf63b66b7d55e9fd291 (patch)
treebc9b8a2d184c12aee236e7f9f276a34b84ca552d /engine-ocean/Game/Systems/CollisionSystems/UniformGrid/uniformgrid.cpp
parentcd7c76017a12bb548036571c1ff13e551369d06d (diff)
add engine version
Diffstat (limited to 'engine-ocean/Game/Systems/CollisionSystems/UniformGrid/uniformgrid.cpp')
-rw-r--r--engine-ocean/Game/Systems/CollisionSystems/UniformGrid/uniformgrid.cpp127
1 files changed, 127 insertions, 0 deletions
diff --git a/engine-ocean/Game/Systems/CollisionSystems/UniformGrid/uniformgrid.cpp b/engine-ocean/Game/Systems/CollisionSystems/UniformGrid/uniformgrid.cpp
new file mode 100644
index 0000000..822129b
--- /dev/null
+++ b/engine-ocean/Game/Systems/CollisionSystems/UniformGrid/uniformgrid.cpp
@@ -0,0 +1,127 @@
+#include "uniformgrid.h"
+#include "Game/Components/CollisionComponents/BoundingDynamicMesh.h"
+#include "Game/Components/CollisionComponents/BoundingTriangle.h"
+#include "Game/Components/CollisionComponents/CollisionComponent.h"
+#include "Game/Components/CollisionComponents/CylinderCollider.h"
+#include <algorithm>
+
+UniformGrid::UniformGrid(std::map<std::string, std::shared_ptr<GameObject>>& dynamic_gameobjects):
+ m_dynamic_gameobjects(dynamic_gameobjects)
+{
+ initializeGrid();
+}
+
+void UniformGrid::initializeGrid(){
+ // grid square: size it based on the largest entity
+
+ // set default square size to be same dimensions as player
+ m_square_dimensions = ceil(m_dynamic_gameobjects.at("player")->getComponent<CollisionComponent>()->getCollisionShape<BoundingDynamicMesh>()->getCylinder().aabbDimensions);
+
+
+ // find largest shape dimension in order to set grid square dimensions
+ for (const auto &go : m_dynamic_gameobjects){
+ if (go.second->hasComponent<CollisionComponent>()){
+ glm::vec3 shape_dimensions = go.second->getComponent<CollisionComponent>()->getCollisionShape<BoundingDynamicMesh>()->getCylinder().aabbDimensions;
+ // find the largest Bounds3f for a shape
+ if (glm::all(glm::greaterThan(shape_dimensions, m_square_dimensions))){
+ m_square_dimensions = ceil(shape_dimensions);
+ }
+ }
+ }
+
+ // initialize grid based on where entities are initially placed
+ for (const auto &go : m_dynamic_gameobjects){
+ updateUniformGrid(go);
+ }
+}
+
+std::string UniformGrid::vecToString(glm::vec3 v){
+ std::string square_bound = std::to_string(v.x) + std::to_string(v.y) + std::to_string(v.z);
+ return square_bound;
+}
+
+
+void UniformGrid::populateContainingCell(glm::vec3 bound_corner, std::string entity_id){
+ glm::vec3 factor = floor(bound_corner/m_square_dimensions);
+ glm::vec3 container_min = factor*m_square_dimensions;
+
+ for (auto &square : m_grid_map){
+ //if the containing square is already in map, then append entity id to its associate list
+ if (square.first == vecToString(container_min)){
+ m_grid_map.at(square.first).insert(entity_id);
+ return;
+ }
+ }
+ // if not yet in map, add to map
+ std::set<std::string> ids;
+ ids.insert(entity_id);
+ m_grid_map.insert(std::pair(vecToString(container_min), ids));
+}
+
+void UniformGrid::updateUniformGrid(const std::pair<std::string, std::shared_ptr<GameObject>> &go){
+ if (go.second->hasComponent<CollisionComponent>()){
+ Bounds3f shapeBounds = go.second->getComponent<CollisionComponent>()->getCollisionShape<BoundingDynamicMesh>()->getCylinder().bounds;
+ // if bounds min is within an interval of square dimensions, then occupy map with that entity
+ glm::vec3 shape_dimensions = go.second->getComponent<CollisionComponent>()->getCollisionShape<BoundingDynamicMesh>()->getCylinder().aabbDimensions;
+
+
+ // check all 6 aabb corners
+ float x_val = shapeBounds.min.x;
+ for (int x=0; x<2; x++){
+ float y_val = shapeBounds.min.y;
+ for (int y=0; y<2; y++){
+ float z_val = shapeBounds.min.z;
+ for (int z=0; z<2; z++){
+ glm::vec3 corner = glm::vec3(x_val,y_val,z_val);
+ populateContainingCell(corner, go.first);
+ z_val += shape_dimensions.z;
+ }
+ y_val += shape_dimensions.y;
+ }
+ x_val += shape_dimensions.x;
+ }
+ }
+}
+
+// only for entities that moved:
+void UniformGrid::moveEntityGridPosition(const std::pair<std::string, std::shared_ptr<GameObject>> &go){
+ // remove previous cells that entity occupied
+ for (auto &cell : m_grid_map){
+ cell.second.erase(go.first);
+ }
+
+ // if there are no more ids associated with that cell, remove it from map
+ for (auto cell = m_grid_map.cbegin(), next_i = cell; cell != m_grid_map.cend(); cell = next_i){
+ ++next_i;
+ if (cell->second.empty()){
+ m_grid_map.erase(cell);
+ }
+ }
+
+ // then update based on new pos
+ updateUniformGrid(go);
+}
+
+void UniformGrid::updateAllGrid(){
+ // initialize grid based on where entities are initially placed
+ for (const auto &go : m_dynamic_gameobjects){
+ moveEntityGridPosition(go);
+ }
+
+ //std::cout << "new ugrid size: " << m_grid_map.size() << std::endl;
+}
+
+std::set<std::set<std::string>> UniformGrid::detectPossibleCollisions(){
+ // store list of names of objects that are near e/o
+ // uses set there are no duplicate inner sets of the same objects
+ std::set<std::set<std::string>> candidate_collision_sets;
+
+ for (const auto &cell : m_grid_map){
+ if (cell.second.size() > 1){
+ candidate_collision_sets.insert(cell.second);
+ }
+ }
+
+ // then for each inner set, detect collisions between the contained objects
+ return candidate_collision_sets;
+}