Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/coll_rect/src/lib/collision_reaction/collision_handle.cc @ 9890

Last change on this file since 9890 was 9890, checked in by patrick, 18 years ago

intruducing new container collision_tube. which serves as a central collision registration tube.

File size: 10.1 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollersf
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Patrick Boenzli
13*/
14
15#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_COLLISION_REACTION
16
17#include "collision_handle.h"
18
19#include "world_entity.h"
20
21#include "collision.h"
22#include "collision_event.h"
23#include "collision_reaction.h"
24
25#include "cr_object_damage.h"
26#include "cr_physics_ground_walk.h"
27#include "cr_physics_full_walk.h"
28
29#include "debug.h"
30
31namespace CoRe
32{
33
34  ObjectListDefinition(CollisionHandle);
35
36  /**
37   * standard constructor
38   * @todo this constructor is not jet implemented - do it
39  */
40  CollisionHandle::CollisionHandle (WorldEntity* owner, CREngine::CRType type)
41  {
42    this->registerObject(this, CollisionHandle::_objectList);
43
44    this->owner = owner;
45    this->type = type;
46
47    this->bCollided = false;
48    this->bDispatched = true;
49
50    this->collisionReaction = NULL;
51    this->bContinuousPoll = false;
52    this->bStopOnFirstCollision = false;
53
54
55    switch( type)
56    {
57        case CREngine::CR_PHYSICS_FULL_WALK:
58        this->collisionReaction = new CRPhysicsFullWalk();
59        this->bContinuousPoll = true;
60        break;
61        case CREngine::CR_PHYSICS_GROUND_WALK:
62        this->collisionReaction = new CRPhysicsGroundWalk();
63        this->bContinuousPoll = true;
64        break;
65        case CREngine::CR_OBJECT_DAMAGE:
66        this->collisionReaction = new CRObjectDamage();
67        this->bStopOnFirstCollision = true;
68        break;
69        default:
70        break;
71    };
72  }
73
74
75  /**
76   * standard deconstructor
77  */
78  CollisionHandle::~CollisionHandle ()
79  {
80    // delete what has to be deleted here
81    if( this->collisionReaction != NULL)
82      delete this->collisionReaction;
83  }
84
85  /**
86   * restores the CollisionHandle to its initial state
87   */
88  void CollisionHandle::reset()
89  {
90    this->flushCollisions();
91  }
92
93
94  /**
95   * add more filter targets to this collision handle
96   *  @param classID the classid to look for
97   */
98  void CollisionHandle::addTarget(const ClassID& target)
99  {
100    // make sure there is no dublicate
101    std::vector<ClassID>::iterator it = this->targetList.begin();
102    for( ; it < this->targetList.end(); it++)
103      if( (*it) == target)
104        return;
105
106
107    // add element
108    this->targetList.push_back(target);
109    PRINTF(5)("addTarget: %i \n", target.id());
110  }
111
112
113  /**
114   * registers a new Collision Object
115   *  @param entityA WorldEntity A of the collision
116   *  @param entityB WorldEntity B of the collision
117   * if a there is already a collision object with the same stats
118   * registration will be skipped and the last collision object is returned
119   */
120  Collision* CollisionHandle::registerCollision(WorldEntity* entityA, WorldEntity* entityB)
121  {
122    //first get the collision object, multiple sources
123    Collision* c;
124    if( this->collisionList.empty() ||
125        ((this->collisionList.back())->getEntityA() != entityA && (this->collisionList.back())->getEntityB() != entityB ))
126    {
127      c = CREngine::getInstance()->popCollisionObject();
128      c->collide(entityA, entityB);
129      this->collisionList.push_back(c);
130
131      // now register it as a shared collision with the other collision entity
132      CollisionHandle* ch = entityB->getCollisionHandle(this->type);
133      if( ch != NULL)
134        ch->registerSharedCollision(c);
135    }
136    else
137      c = this->collisionList.back();
138
139    return c;
140  }
141
142
143  /**
144   * register a Collision to the Collision handle.
145   *  @param collision the collision object to register
146   *
147   * This is used for internal collision registration: sharing the collision objects between Collision Reactions
148   * Therefore dispatching it only once
149   */
150  void CollisionHandle::registerSharedCollision(Collision* collision)
151  {
152    // fist check if we are listening for this Collision
153    if( !this->filterCollision(collision))
154      return;
155
156    // set the state to not dispatched
157    this->bDispatched = false;
158    this->bCollided = true;
159    collision->setEntityBCollide(true);
160
161    this->collisionList.push_back(collision);
162  }
163
164
165  /**
166   * this is the function to be called on a collision event for this handle
167   *  @param collision the collision objects containing all collision informations
168   */
169  void CollisionHandle::registerCollisionEvent(CollisionEvent* collisionEvent)
170  {
171    if( !this->filterCollisionEvent(collisionEvent))
172      return;
173
174    // set the state to not dispatched
175    this->bDispatched = false;
176    this->bCollided = true;
177
178    // checks if these WorldEntities have already collided or if its a new collision -> create a new Collision object
179    Collision* c = this->registerCollision(collisionEvent->getEntityA(), collisionEvent->getEntityB());
180    c->setEntityACollide(true);
181
182    c->registerCollisionEvent(collisionEvent);
183    PRINTF(5)("Registering Collision Event: %s, %s\n", collisionEvent->getEntityA()->getClassCName(), collisionEvent->getEntityB()->getClassCName());
184  }
185
186
187  /**
188   * flushes the collision list
189   */
190  void CollisionHandle::flushCollisions()
191  {
192    this->collisionList.clear();
193  }
194
195
196  /**
197   * handles the collisions and react according to algorithm
198   */
199  void CollisionHandle::handleCollisions()
200  {
201    // if continuous poll the reaction
202    if( this->bContinuousPoll && !this->bCollided)
203    {
204      this->collisionReaction->update(this->owner);
205      return;
206    }
207
208    // collision reaction calculations (for every collision there will be a reaction)
209    std::vector<Collision*>::iterator it = this->collisionList.begin();
210    for(; it < this->collisionList.end(); it++)
211    {
212      if( !(*it)->isDispatched())
213      {
214        this->collisionReaction->reactToCollision(*it);
215        (*it)->flushCollisionEvents();
216      }
217    }
218
219    // now set state to dispatched
220    this->bDispatched = true;
221    this->bCollided = false;
222
223    this->flushCollisions();
224  }
225
226
227  /**
228   * filter out the CollisionEvents that are not wanted
229   *  @param collisionEvent the collision event to filter
230   */
231  bool CollisionHandle::filterCollisionEvent(CollisionEvent* collisionEvent)
232  {
233    std::vector<ClassID>::iterator it = this->targetList.begin();
234    for(; it < this->targetList.end(); it++)
235    {
236      //     if(collisionEvent->getEntityB()->isA(CL_AIMING_SYSTEM) || collisionEvent->getEntityA()->isA(CL_AIMING_SYSTEM))
237      //     {
238      //        PRINTF(0)("I am: %s colliding with: %s\n", owner->getClassCName(), collisionEvent->getEntityB()->getClassCName(), *it);
239      //        if( collisionEvent->getEntityA() == this->owner) {
240      //          PRINTF(0)("I am owner -> I am: %s colliding with: %s is a %i filter?\n", owner->getClassCName(),
241      //          collisionEvent->getEntityB()->getClassCName(), *it);
242      //          if( collisionEvent->getEntityB()->isA((ClassID)(*it))) {
243      //            PRINTF(0)("I am owner -> I am: %s colliding with: %s is a %i filter ok\n", owner->getClassCName(),
244      //            collisionEvent->getEntityB()->getClassCName(), *it);
245      //             }
246      //        }
247      //        else {
248      //          PRINTF(0)("I am not owner -> I am: %s colliding with: %s is a %i filter?\n", owner->getClassCName(),
249      //          collisionEvent->getEntityB()->getClassCName(), *it);
250      //          if( collisionEvent->getEntityA()->isA((ClassID)(*it))) {
251      //            PRINTF(0)("I'm not owner -> I am: %s colliding with: %s is a %i filter ok\n", owner->getClassCName(),
252      //            collisionEvent->getEntityA()->getClassCName(), *it);
253      //             }
254      //        }
255      //
256      //     }
257
258      if( collisionEvent->getEntityA() == this->owner)
259      {
260        if( collisionEvent->getEntityB()->isA((*it)))
261        {
262          PRINTF(5)("I am: %s colliding with: %s is a %i filter ok\n", owner->getClassCName(),
263                    collisionEvent->getEntityB()->getClassCName(), (*it).id());
264          return true;
265        }
266      }
267      else
268      {
269        if( collisionEvent->getEntityA()->isA((*it)))
270        {
271          PRINTF(5)("I am: %s colliding with: %s is a %i filter ok\n", owner->getClassCName(),
272                    collisionEvent->getEntityA()->getClassCName(), (*it).id());
273          return true;
274        }
275      }
276    }
277
278    return false;
279  }
280
281
282  /**
283   * filter Collisions that are not wanted to be reacted to
284   *  @param collision the collision object to filter
285   */
286  bool CollisionHandle::filterCollision(Collision* collision)
287  {
288    std::vector<ClassID>::iterator it = this->targetList.begin();
289    for(; it < this->targetList.end(); it++)
290    {
291
292      //     if(collision->getEntityB()->isA(CL_AIMING_SYSTEM) || collision->getEntityA()->isA(CL_AIMING_SYSTEM))
293      //     {
294      //       PRINTF(0)("Shared!!! I am: %s colliding with: %s\n", owner->getClassCName(), collision->getEntityB()->getClassCName(), *it);
295      //       if( collision->getEntityA() == this->owner) {
296      //         PRINTF(0)("I am owner -> I am: %s colliding with: %s is a %i filter?\n", owner->getClassCName(),
297      //         collision->getEntityB()->getClassCName(), *it);
298      //         if( collision->getEntityB()->isA((ClassID)(*it))) {
299      //           PRINTF(0)("I am owner -> I am: %s colliding with: %s is a %i filter ok\n", owner->getClassCName(),
300      //           collision->getEntityB()->getClassCName(), *it);
301      //         }
302      //       }
303      //       else {
304      //         PRINTF(0)("I'm not owner -> I am: %s colliding with: %s is a %i filter?\n", owner->getClassCName(),
305      //         collision->getEntityB()->getClassCName(), *it);
306      //         if( collision->getEntityA()->isA((ClassID)(*it))) {
307      //           PRINTF(0)("I'm not owner -> I am: %s colliding with: %s is a %i filter ok\n", owner->getClassCName(),
308      //           collision->getEntityA()->getClassCName(), *it);
309      //         }
310      //       }
311      //     }
312
313      if( collision->getEntityA() == this->owner)
314      {
315        if( collision->getEntityA()->isA(*it))
316          return true;
317      }
318      else
319      {
320        if( collision->getEntityB()->isA(*it))
321          return true;
322      }
323    }
324
325    return false;
326  }
327
328
329
330}
331
332
333
Note: See TracBrowser for help on using the repository browser.