Bubba-3D  0.9.0
Awesome game engine!
TwoPhaseCollider.cpp
1 /*
2  * This file is part of Bubba-3D.
3  *
4  * Bubba-3D is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Bubba-3D is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with Bubba-3D. If not, see http://www.gnu.org/licenses/.
16  */
17 //
18 // Created by johan on 2016-04-13.
19 //
20 
21 #include <cstddef>
22 #include <timer.h>
23 #include <sstream>
24 #include "GameObject.h"
25 #include "TwoPhaseCollider.h"
26 
27 TwoPhaseCollider::TwoPhaseCollider(BroadPhaseCollider *broadPhaseCollider, ExactPhaseCollider *exactPhaseCollider) {
28  this->broadPhaseCollider = broadPhaseCollider;
29  this->exactPhaseCollider = exactPhaseCollider;
30 }
31 
33  utils::Timer timer;
34  timer.start();
35  CollisionPairList possibleCollision = broadPhaseCollider->computeCollisionPairs(scene);
36  CollisionPairList exactCollisions = exactPhaseCollider->computeExactCollision(possibleCollision);
37 
38  triggerObjectEvents(exactCollisions);
39 
40  timer.stop();
41  std::stringstream timeMessage;
42  timeMessage << "Tested " << possibleCollision.size() <<" possible collision in : " << timer.getElapsedTime() << " ms";
43  Logger::logDebug(timeMessage.str());
44 }
45 
46 void TwoPhaseCollider::triggerObjectEvents(CollisionPairList exactCollisions) {
47  for(auto i = exactCollisions.begin(); i != exactCollisions.end(); i++ ) {
48  CollisionPair pair = *i;
49 
50  GameObject *object1 = pair.first;
51  GameObject *object2 = pair.second;
52 
53  if(wasCollidingPreviously(object1, object2)) {
54  triggerObjectEvent(object1, object2, EventType::DuringCollision);
55  } else {
56  triggerObjectEvent(object1, object2, EventType::BeforeCollision);
57  }
58  }
59 
60  callEventsForObjectsThatNoLongerCollides(exactCollisions);
61 }
62 
63 void TwoPhaseCollider::callEventsForObjectsThatNoLongerCollides(CollisionPairList exactCollisions) {
64  CollisionPairList newCollidingList;
65 
66  for(auto i = exactCollisions.begin(); i != exactCollisions.end(); i++ ) {
67  CollisionPair pair = *i;
68 
69  GameObject *object1 = pair.first;
70  GameObject *object2 = pair.second;
71 
72  GameObject* id1 = getMinId(object1,object2);
73  GameObject* id2 = getMaxId(object1,object2);
74 
75  CollisionPair sortedPair(id1, id2);
76  if(std::find(collidingList.begin(), collidingList.end(), sortedPair) != collidingList.end()) {
77  collidingList.erase(std::remove(collidingList.begin(), collidingList.end(), sortedPair));
78  }
79  newCollidingList.push_back(sortedPair);
80  }
81 
82 
83  for(auto i = collidingList.begin(); i != collidingList.end(); i++ ) {
84  CollisionPair pair = *i;
85 
86  GameObject *object1 = pair.first;
87  GameObject *object2 = pair.second;
88  triggerObjectEvent(object1, object2, EventType::AfterCollision);
89  }
90 
91  collidingList = newCollidingList;
92 }
93 
94 
95 void TwoPhaseCollider::triggerObjectEvent(GameObject* object1, GameObject* object2, EventType eventType) {
96  object1->callEvent(eventType, object2);
97  object2->callEvent(eventType, object1);
98 }
99 
100 void TwoPhaseCollider::rememberCollidingPair(GameObject* object1, GameObject* object2) {
101  GameObject* id1 = getMinId(object1,object2);
102  GameObject* id2 = getMaxId(object1,object2);
103 
104  collidingList.push_back(CollisionPair(id1, id2));
105 }
106 
107 void TwoPhaseCollider::forgetCollidingPair(GameObject* object1, GameObject* object2) {
108  GameObject* id1 = getMinId(object1,object2);
109  GameObject* id2 = getMaxId(object1,object2);
110 
111  collidingList.erase(std::remove(collidingList.begin(), collidingList.end(),
112  CollisionPair(id1, id2)));
113 }
114 
115 bool TwoPhaseCollider::wasCollidingPreviously(GameObject* object1, GameObject* object2) {
116  GameObject* id1 = getMinId(object1,object2);
117  GameObject* id2 = getMaxId(object1,object2);
118 
119  return std::find(collidingList.begin(), collidingList.end(), CollisionPair(id1, id2)) != collidingList.end();
120 }
121 
122 GameObject* TwoPhaseCollider::getMinId(GameObject* object1, GameObject* object2) {
123  return object1->getId() < object2->getId() ? object1 : object2;
124 }
125 
126 GameObject* TwoPhaseCollider::getMaxId(GameObject* object1, GameObject* object2) {
127  return object1->getId() > object2->getId() ? object1 : object2;
128 }
void updateCollision(Scene *scene) override
virtual CollisionPairList computeCollisionPairs(Scene *scene)=0
virtual CollisionPairList computeExactCollision(CollisionPairList possibleCollision)=0
A class for containing all information about a object in the game world.
Definition: GameObject.h:67
Definition: Scene.h:29
void callEvent(EventType type, GameObject *data)
Definition: GameObject.cpp:207