Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
collide_map.cpp
Go to the documentation of this file.
1 #include <algorithm>
2 #include <assert.h>
3 #include "collide_map.h"
4 #include "unit_generic.h"
5 #include "bolt.h"
6 
7 volatile bool apart_return = true;
9 {
10  count -= 1;
11  if ( target >= this->begin() && target < this->end() ) {
12  target->radius = 0;
13  target->ref.unit = NULL;
14  size_t diff = ( target-this->begin() );
15  if (this->unsorted.size() > diff) {
16  //for secondary collide arrays that have no unsorted array
17  iterator tmp = &*(this->unsorted.begin()+diff);
18  tmp->radius = 0;
19  tmp->ref.unit = NULL;
20  }
21  return;
22  } else if (target == NULL) {
23  return;
24  } else {
25  CollidableBackref *targ = static_cast< CollidableBackref* > (&*target);
26  std::list< CollidableBackref > *targlist = &toflattenhints[targ->toflattenhints_offset];
27  std::list< CollidableBackref >::iterator endlist = targlist->end();
28  for (std::list< CollidableBackref >::iterator i = targlist->begin(); i != endlist; ++i)
29  if (&*i == target) {
30  targlist->erase( i );
31  return;
32  }
33  }
34 }
36 {
37  if ( iter >= this->begin() && iter < this->end() ) {
38  ( *( unsorted.begin()+( iter-this->begin() ) ) ).ref = ref; //update both unsorted and sorted
39  (*iter).ref = ref;
40  } else if ( !is_null( iter ) ) {
41  (*iter).ref = ref;
42  }
43 }
45 {
46  if ( iter >= this->begin() && iter < this->end() ) {
47  iterator tmp = &*( this->unsorted.begin()+( iter-this->begin() ) );
48  *tmp = newKey;
49  } else {
50  *iter = newKey;
51  }
52  return iter;
53 }
56  const Collidable &newKey,
59 {
60  return this->changeKey( iter, newKey );
61 }
62 template < int direction, bool always_replace >
64 {
65  float last_radius;
66  double last_radius_key;
67 
68  float last_big_radius;
69  double last_big_radius_key;
70  CollideArray *cm;
71 public: RadiusUpdate( CollideArray *cm )
72  {
73  last_radius = 0;
74  last_big_radius = 0;
75  last_radius_key = 0;
76  last_big_radius_key = 0;
77  this->cm = cm;
78  }
79  void operator()( const Collidable &collidable, size_t index )
80  {
81  double key = collidable.getKey();
82  float rad = collidable.radius;
83  if (rad > 0) {
84  if (rad > last_big_radius) {
85  last_radius = last_big_radius = rad;
86  last_radius_key = last_big_radius_key = key;
87  } else if (rad > last_radius) {
88  last_radius = rad;
89  last_radius_key = key;
90  } else {last_radius_key = key; }}
91  if (last_big_radius && fabs( key-last_big_radius_key ) > 2*cm->max_bolt_radius*SIMULATION_ATOM) {
92  last_big_radius = last_radius;
93  last_big_radius_key = last_radius_key;
94  last_radius = 0;
95  last_radius_key = key;
96  }
97  if (always_replace || cm->max_radius[index] < last_big_radius)
98  cm->max_radius[index] = last_big_radius;
99  }
100 };
101 
102 template < int location_index >
104 {
105 public:
106  void updateBackpointer( Collidable &collidable )
107  {
109  assert( collidable.radius != 0.0f );
110  if (location_index != Unit::UNIT_ONLY && collidable.radius < 0)
111  Bolt::BoltFromIndex( ss, collidable.ref )->location = &collidable;
112  else
113  collidable.ref.unit->location[location_index] = &collidable;
114  }
115  void operator()( Collidable &collidable )
116  {
117  updateBackpointer( collidable );
118  }
119 };
120 
122 {
123  sorted.resize( count );
124  max_radius.resize( count );
125  size_t len = unsorted.size();
126  size_t index = count;
127  RadiusUpdate< -1, true >collideUpdate( this );
128  for (ptrdiff_t i = len; i >= 0; i--) {
129  Collidable *tmp;
130  if (i < static_cast<ptrdiff_t>(len) && (tmp = &unsorted[i])->radius != 0.0f) {
131  sorted[--index] = *tmp;
132  collideUpdate( *tmp, index );
133  }
134 
135  std::list< CollidableBackref >::iterator listend = toflattenhints[i].end();
136  for (std::list< CollidableBackref >::iterator j = toflattenhints[i].begin();
137  j != listend;
138  ++j)
139  if (j->radius != 0) {
140  sorted[--index] = *j;
141  collideUpdate( *j, index );
142  }
143  toflattenhints[i].resize( 0 );
144  }
145 
146  std::sort( sorted.begin(), sorted.end() );
147  unsorted = sorted;
148 
149  toflattenhints.resize( count+1 );
151  size_t i = 0;
152  size_t size = sorted.size();
153  ResizableArray::iterator iter = sorted.begin();
155  RadiusUpdate< 1, false > radUpdate( this );
156  for (i = 0; i != size; ++i, ++iter) {
157  update( *iter );
158  radUpdate( *iter, i );
159  }
160  } else if (location_index == Unit::UNIT_ONLY) {
162  } else {
163  assert( 0 && "Only Support arrays of units_only and mixed units bolts" ); //right now only support 2 array types;
164  }
165 }
166 class CopyExample : public UpdateBackpointers< Unit::UNIT_ONLY >
167 {
168 public:
169  CollideArray::ResizableArray::iterator examplebegin;
170  CollideArray::ResizableArray::iterator exampleend;
171 public: CopyExample( CollideArray::ResizableArray::iterator beg, CollideArray::ResizableArray::iterator end )
172  {
173  examplebegin = beg;
174  exampleend = end;
175  }
176  void operator()( Collidable &collidable )
177  {
178  assert( examplebegin != exampleend );
179  while ( !(examplebegin->radius > 0) ) {
180  ++examplebegin;
181  assert( examplebegin != exampleend );
182  }
183  collidable = *examplebegin++;
184  updateBackpointer( collidable );
185  }
186 };
187 
189 {
190 public:
191  template < class T >
192  void operator()( T &toclear )
193  {
194  toclear.resize( 0 );
195  }
196 };
198 {
200  sorted.resize( count );
201  for_each( toflattenhints.begin(), toflattenhints.end(), resizezero() );
202  toflattenhints.resize( count+1 );
203 
204  for_each( sorted.begin(), sorted.end(), CopyExample( hint.sorted.begin(), hint.sorted.end() ) );
205  } else {
206  printf( "Trying to use flatten hint on a array with both bolts and units\n" );
207  flatten();
208  }
209 }
210 
212 {
213  if (newKey.radius < -max_bolt_radius*SIMULATION_ATOM)
215  if ( this->begin() == this->end() ) {
216  count += 1;
217  this->unsorted.push_back( newKey );
218  this->toflattenhints.resize( 2 );
219  this->sorted.push_back( newKey );
220  return &sorted.back();
221  } else if ( hint >= this->begin() && hint <= this->end() ) {
222  count += 1;
223  size_t len = hint-this->begin();
224  std::list< CollidableBackref > *hintlist = &toflattenhints[len];
225  return &*hintlist->insert( hintlist->end(), CollidableBackref( newKey, len ) );
226  } else {
227  return this->insert( newKey ); //don't use hint;
228  }
229 }
230 
232 {
233  return ::std::lower_bound( this->begin(), this->end(), newKey );
234 }
235 
237 {
238  return this->insert( newKey, this->lower_bound( newKey ) );
239 }
241 {
242  if ( this->begin() != this->end() )
243  for (iterator newiter = this->begin(), iter = newiter++; newiter != this->end(); iter = newiter++)
244  assert( *iter < *newiter );
245 }
246 
248 {
249  radius = un->rSize();
250  if ( radius <= FLT_MIN || !FINITE( radius ) ) radius = 2*FLT_MIN;
251  assert( !un->isSubUnit() );
252  this->SetPosition( un->LocalPosition() );
253  ref.unit = un;
254 }
256 {
257  return a >= begin() && a < end();
258 }
259 template < class T >
261 {
262 public:
263  CollideMap::iterator operator()( T *input, unsigned int location_index )
264  {
265  return input->location[location_index];
266  }
267 };
268 template < >
270 {
271 public:
272  CollideMap::iterator operator()( Bolt *input, unsigned int location_index )
273  {
274  return input->location;
275  }
276 };
277 extern size_t nondecal_index( Collidable::CollideRef b );
278 template < class T, bool canbebolt >
280 {
281 public:
282  static void FixMinLookMaxLook( CollideMap *tmpcm, CollideMap::iterator tmptmore, double &minlook, double &maxlook )
283  {
284  double mid = (minlook+maxlook)*.5;
285  minlook = (minlook+mid)*.5-tmptmore->radius;
286  maxlook = (maxlook+mid)*.5+tmptmore->radius;
287  }
289  CollideMap::iterator cmend,
290  T *un,
291  const Collidable &collider,
292  unsigned int location_index,
293  CollideMap::iterator tless,
294  CollideMap::iterator tmore,
295  double minlook,
296  double maxlook )
297  {
298  CheckBackref< T >backref_obtain;
299  if (backref_obtain( un, location_index ) != cmbegin) {
300  //if will happen in case of !Iterable
301  while ( (*tless)->getKey() >= minlook ) {
302  float rad = (*tless)->radius;
303  bool boltSpecimen = canbebolt && (rad < 0);
304 
305  Collidable::CollideRef ref = (*tless)->ref;
306  if (tless == cmbegin) {
307  if (canbebolt && boltSpecimen) {
308  if ( CheckCollision( un, collider, ref, **tless ) ) {
309  if ( endAfterCollide( un, location_index ) )
310  return true;
311  else break;
312  } else {break; }} else if (rad != 0) {
313  if ( canbebolt == true && BoltType( un ) ) {
314  CollideMap::iterator tmptmore = ref.unit->location[Unit::UNIT_ONLY];
315  CollideMap::iterator tmptless = tmptmore;
316  ++tmptmore;
319  un, collider, Unit::UNIT_ONLY,
320  tmptless, tmptmore,
321  minlook, maxlook );
322  }
323  if ( CheckCollision( un, collider, ref.unit, **tless ) ) {
324  if ( endAfterCollide( un, location_index ) )
325  return true;
326  else break;
327  } else {break; }} else {break; }} else {
328  if (canbebolt && boltSpecimen) {
329  if ( CheckCollision( un, collider, ref, **tless-- ) )
330  if ( endAfterCollide( un, location_index ) )
331  return true;
332  } else if (rad != 0) {
333  if ( canbebolt == true && BoltType( un ) ) {
334  CollideMap::iterator tmptmore = ref.unit->location[Unit::UNIT_ONLY];
335  CollideMap::iterator tmptless = tmptmore;
336  ++tmptmore;
339  un, collider, Unit::UNIT_ONLY,
340  tmptless, tmptmore,
341  minlook, maxlook );
342  }
343  if ( CheckCollision( un, collider, ref.unit, **tless-- ) )
344  if ( endAfterCollide( un, location_index ) )
345  return true;
346  } else {
347  --tless;
348  }
349  }
350  }
351  }
352  while (tmore != cmend && (*tmore)->getKey() <= maxlook) {
353  float rad = (*tmore)->radius;
354  bool boltSpecimen = canbebolt && (rad < 0);
355  Collidable::CollideRef ref = (*tmore)->ref;
356  if (canbebolt && boltSpecimen) {
357  if ( CheckCollision( un, collider, ref, **tmore++ ) )
358  if ( endAfterCollide( un, location_index ) )
359  return true;
360  } else if (rad != 0) {
361  //not null unit
362  if ( canbebolt == true && BoltType( un ) ) {
363  CollideMap::iterator tmptmore = ref.unit->location[Unit::UNIT_ONLY];
364  CollideMap::iterator tmptless = tmptmore;
365  ++tmptmore;
368  un, collider, Unit::UNIT_ONLY,
369  tmptless, tmptmore,
370  minlook, maxlook );
371  }
372  if ( CheckCollision( un, collider, ref.unit, **tmore++ ) )
373  if ( endAfterCollide( un, location_index ) )
374  return true;
375  } else {++tmore; }}
376  return false;
377  }
378  static bool ComputeMaxLookMinLook( Unit *un,
379  CollideMap *cm,
380  CollideMap::iterator collider,
381  CollideMap::iterator begin,
383  double sortedloc,
384  float radius,
385  double &minlook,
386  double &maxlook )
387  {
388  maxlook = sortedloc+2.0625*radius;
389  minlook = sortedloc-2.0625*radius;
390  return false;
391  }
392  static bool ComputeMaxLookMinLook( Bolt *un,
393  CollideMap *cm,
394  CollideMap::iterator collider,
395  CollideMap::iterator cmbegin,
396  CollideMap::iterator cmend,
397  double sortedloc,
398  float rad,
399  double &minlook,
400  double &maxlook )
401  {
402  float dboltdist = -2.0625*rad;
403  float boltdist = -1.0625*rad;
404  if (collider >= cmbegin && collider < cmend) {
405  float maxrad = cm->max_radius[collider-cmbegin];
406  if (maxrad == 0)
407  return true;
408  boltdist += maxrad;
409  if (dboltdist < boltdist)
410  boltdist = dboltdist;
411  } else {boltdist += fabs( rad ); } maxlook = sortedloc+boltdist;
412  minlook = sortedloc-boltdist;
413  return false;
414  }
415  static bool CheckCollisions( CollideMap *cm, T *un, const Collidable &collider, unsigned int location_index )
416  {
417  CollideMap::iterator tless, tmore;
418  double sortedloc = collider.getKey();
419  float rad = collider.radius;
420  CollideMap::iterator cmbegin = cm->begin();
421  CollideMap::iterator cmend = cm->end();
422  if (cmbegin == cmend) return false;
423  double minlook, maxlook;
424  CollideMap::iterator startIter = CheckBackref< T > () ( un, location_index );
425  if ( ComputeMaxLookMinLook( un, cm, startIter, cmbegin, cmend, sortedloc, rad, minlook, maxlook ) ) return false; //no units in area
426  if ( !cm->Iterable( startIter ) ) {
427  CollideArray::CollidableBackref *br = static_cast< CollideArray::CollidableBackref* > (startIter);
428  CollideMap::iterator tmploc = cmbegin+br->toflattenhints_offset;
429  if (tmploc == cmend)
430  tmploc--;
431  tless = tmore = tmploc; //don't decrease tless
432  } else {
433  tless = tmore = startIter;
434  if (tless != cmbegin)
435  --tless;
436  }
437  ++tmore;
438  return CheckCollisionsInner( cmbegin, cmend,
439  un, collider, location_index,
440  tless, tmore,
441  minlook, maxlook );
442  }
443  static bool doUpdateKey( Bolt *b )
444  {
445  return true;
446  }
447  static bool doUpdateKey( Unit *un )
448  {
449  return false;
450  }
451  static bool endAfterCollide( Bolt *b, unsigned int location_index /*meaningless, just for templtae goodness*/ )
452  {
453  return true;
454  }
455  static bool endAfterCollide( Unit *un, unsigned int location_index )
456  {
457  return is_null( un->location[location_index] );
458  }
459  static bool ApartPositive( const Collidable &a, const Collidable &b )
460  {
461  float aradius = a.radius;
462  float bradius = b.radius;
463  return ( a.GetPosition()-b.GetPosition() ).MagnitudeSquared() > aradius*aradius+aradius*bradius*2+bradius*bradius;
464  }
465  static bool ApartNeg( const Collidable &a, const Collidable &b )
466  {
467  //return apart_return;
468  double tempy = a.position.j-b.position.j;
469  double tempz = a.position.k-b.position.k;
470  float radiussum = b.radius-a.radius; //a is negative
471  if (fabs( tempy ) > radiussum || fabs( tempz ) > radiussum)
472  return true;
473  double tempx = (a.position.i-b.position.i);
474  tempx *= tempx;
475  tempy *= tempy;
476  tempz *= tempz;
477  return (tempx+tempy+tempz) > radiussum*radiussum;
478  }
479  static bool CheckCollision( Unit *a, const Collidable &aiter, Unit *b, const Collidable &biter )
480  {
481  if ( !ApartPositive( aiter, biter ) )
482  return a->Collide( b );
483  return false;
484  }
485  static bool CheckCollision( Bolt *a, const Collidable &aiter, Unit *b, const Collidable &biter )
486  {
487  if ( !ApartNeg( aiter, biter ) ) {
488  if ( a->Collide( b ) ) {
489  a->Destroy( nondecal_index( aiter.ref ) );
490  return true;
491  }
492  }
493  return false;
494  }
495  static bool BoltType( Bolt *a )
496  {
497  return true;
498  }
499  static bool BoltType( Unit *a )
500  {
501  return false;
502  }
503 
504  static bool CheckCollision( Bolt *a, const Collidable &aiter, Collidable::CollideRef b, const Collidable &biter )
505  {
506  return false;
507  }
508  static bool CheckCollision( Unit *un, const Collidable &aiter, Collidable::CollideRef b, const Collidable &biter )
509  {
510  if ( !ApartNeg( biter, aiter ) )
511  return Bolt::CollideAnon( b, un );
512  return false;
513  }
514 };
515 
516 bool CollideMap::CheckCollisions( Bolt *bol, const Collidable &updated )
517 {
519 }
520 
521 bool CollideMap::CheckUnitCollisions( Bolt *bol, const Collidable &updated )
522 {
524 }
525 bool CollideMap::CheckCollisions( Unit *un, const Collidable &updated )
526 {
527  //need to check beams
528  if (un->activeStarSystem == NULL)
530  else
531  assert( un->activeStarSystem == _Universe->activeStarSystem() );
533 }
534 
536 {
537  //need to check beams
538  if (un->activeStarSystem == NULL)
540  else
541  assert( un->activeStarSystem == _Universe->activeStarSystem() );
543 }
544