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
OPC_BoxPruning.cpp
Go to the documentation of this file.
1 /*
3  * OPCODE - Optimized Collision Detection
4  * Copyright (C) 2001 Pierre Terdiman
5  * Homepage: http://www.codercorner.com/Opcode.htm
6  */
8 
10 
16 
18 /*
20  You could use a complex sweep-and-prune as implemented in I-Collide.
21  You could use a complex hashing scheme as implemented in V-Clip or recently in ODE it seems.
22  You could use a "Recursive Dimensional Clustering" algorithm as implemented in GPG2.
23 
24  Or you could use this.
25  Faster ? I don't know. Probably not. It would be a shame. But who knows ?
26  Easier ? Definitely. Enjoy the sheer simplicity.
28 */
29 
30 
32 // Precompiled Header
33 #include "Stdafx.h"
34 
35 
36 using namespace Opcode;
37 
38  inline_ void FindRunningIndex(udword& index, float* array, udword* sorted, int last, float max)
39  {
40  int First=index;
41  while(First<=last)
42  {
43  index = (First+last)>>1;
44 
45  if(max>array[sorted[index]]) First = index+1;
46  else last = index-1;
47  }
48  }
49 // ### could be log(n) !
50 // and maybe use cmp integers
51 
52 // InsertionSort has better coherence, RadixSort is better for one-shot queries.
53 #define PRUNING_SORTER RadixSort
54 //#define PRUNING_SORTER InsertionSort
55 
56 // Static for coherence
61 {
64 }
66 {
69 }
71 {
74 }
76 {
80 }
81 
82 
84 
94 bool Opcode::BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes)
96 {
97  // Checkings
98  if(!nb0 || !array0 || !nb1 || !array1) return false;
99 
100  // Catch axes
101  udword Axis0 = axes.mAxis0;
102  udword Axis1 = axes.mAxis1;
103  udword Axis2 = axes.mAxis2;
104 
105  // Allocate some temporary data
106  float* MinPosList0 = new float[nb0];
107  float* MinPosList1 = new float[nb1];
108 
109  udword i;
110  // 1) Build main lists using the primary axis
111  for(i=0;i<nb0;i++) MinPosList0[i] = array0[i]->GetMin(Axis0);
112  for(i=0;i<nb1;i++) MinPosList1[i] = array1[i]->GetMin(Axis0);
113 
114  // 2) Sort the lists
117  const udword* Sorted0 = RS0->Sort(MinPosList0, nb0).GetRanks();
118  const udword* Sorted1 = RS1->Sort(MinPosList1, nb1).GetRanks();
119 
120  // 3) Prune the lists
121  udword Index0, Index1;
122 
123  const udword* const LastSorted0 = &Sorted0[nb0];
124  const udword* const LastSorted1 = &Sorted1[nb1];
125  const udword* RunningAddress0 = Sorted0;
126  const udword* RunningAddress1 = Sorted1;
127 
128  while(RunningAddress1<LastSorted1 && Sorted0<LastSorted0)
129  {
130  Index0 = *Sorted0++;
131 
132  while(RunningAddress1<LastSorted1 && MinPosList1[*RunningAddress1]<MinPosList0[Index0]) RunningAddress1++;
133 
134  const udword* RunningAddress2_1 = RunningAddress1;
135 
136  while(RunningAddress2_1<LastSorted1 && MinPosList1[Index1 = *RunningAddress2_1++]<=array0[Index0]->GetMax(Axis0))
137  {
138  if(array0[Index0]->Intersect(*array1[Index1], Axis1))
139  {
140  if(array0[Index0]->Intersect(*array1[Index1], Axis2))
141  {
142  pairs.AddPair(Index0, Index1);
143  }
144  }
145  }
146  }
147 
149 
150  while(RunningAddress0<LastSorted0 && Sorted1<LastSorted1)
151  {
152  Index0 = *Sorted1++;
153 
154  while(RunningAddress0<LastSorted0 && MinPosList0[*RunningAddress0]<=MinPosList1[Index0]) RunningAddress0++;
155 
156  const udword* RunningAddress2_0 = RunningAddress0;
157 
158  while(RunningAddress2_0<LastSorted0 && MinPosList0[Index1 = *RunningAddress2_0++]<=array1[Index0]->GetMax(Axis0))
159  {
160  if(array0[Index1]->Intersect(*array1[Index0], Axis1))
161  {
162  if(array0[Index1]->Intersect(*array1[Index0], Axis2))
163  {
164  pairs.AddPair(Index1, Index0);
165  }
166  }
167 
168  }
169  }
170 
171  DELETEARRAY(MinPosList1);
172  DELETEARRAY(MinPosList0);
173 
174  return true;
175 }
176 
177 #define ORIGINAL_VERSION
178 //#define JOAKIM
179 
181 
189 bool Opcode::CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes)
191 {
192  // Checkings
193  if(!nb || !array) return false;
194 
195  // Catch axes
196  udword Axis0 = axes.mAxis0;
197  udword Axis1 = axes.mAxis1;
198  udword Axis2 = axes.mAxis2;
199 
200 #ifdef ORIGINAL_VERSION
201  // Allocate some temporary data
202 // float* PosList = new float[nb];
203  float* PosList = new float[nb+1];
204 
205  // 1) Build main list using the primary axis
206  for(udword i=0;i<nb;i++) PosList[i] = array[i]->GetMin(Axis0);
207 PosList[nb++] = MAX_FLOAT;
208 
209  // 2) Sort the list
211  const udword* Sorted = RS->Sort(PosList, nb).GetRanks();
212 
213  // 3) Prune the list
214  const udword* const LastSorted = &Sorted[nb];
215  const udword* RunningAddress = Sorted;
216  udword Index0, Index1;
217  while(RunningAddress<LastSorted && Sorted<LastSorted)
218  {
219  Index0 = *Sorted++;
220 
221 // while(RunningAddress<LastSorted && PosList[*RunningAddress++]<PosList[Index0]);
222  while(PosList[*RunningAddress++]<PosList[Index0]);
223 
224  if(RunningAddress<LastSorted)
225  {
226  const udword* RunningAddress2 = RunningAddress;
227 
228 // while(RunningAddress2<LastSorted && PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0))
229  while(PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0))
230  {
231 // if(Index0!=Index1)
232 // {
233  if(array[Index0]->Intersect(*array[Index1], Axis1))
234  {
235  if(array[Index0]->Intersect(*array[Index1], Axis2))
236  {
237  pairs.AddPair(Index0, Index1);
238  }
239  }
240 // }
241  }
242  }
243  }
244 
245  DELETEARRAY(PosList);
246 #endif
247 
248 #ifdef JOAKIM
249  // Allocate some temporary data
250 // float* PosList = new float[nb];
251  float* MinList = new float[nb+1];
252 
253  // 1) Build main list using the primary axis
254  for(udword i=0;i<nb;i++) MinList[i] = array[i]->GetMin(Axis0);
255  MinList[nb] = MAX_FLOAT;
256 
257  // 2) Sort the list
259  udword* Sorted = RS->Sort(MinList, nb+1).GetRanks();
260 
261  // 3) Prune the list
262 // const udword* const LastSorted = &Sorted[nb];
263 // const udword* const LastSorted = &Sorted[nb-1];
264  const udword* RunningAddress = Sorted;
265  udword Index0, Index1;
266 
267 // while(RunningAddress<LastSorted && Sorted<LastSorted)
268 // while(RunningAddress<LastSorted)
269  while(RunningAddress<&Sorted[nb])
270 // while(Sorted<LastSorted)
271  {
272 // Index0 = *Sorted++;
273  Index0 = *RunningAddress++;
274 
275 // while(RunningAddress<LastSorted && PosList[*RunningAddress++]<PosList[Index0]);
276 // while(PosList[*RunningAddress++]<PosList[Index0]);
277 //RunningAddress = Sorted;
278 // if(RunningAddress<LastSorted)
279  {
280  const udword* RunningAddress2 = RunningAddress;
281 
282 // while(RunningAddress2<LastSorted && PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0))
283 
284 // float CurrentMin = array[Index0]->GetMin(Axis0);
285  float CurrentMax = array[Index0]->GetMax(Axis0);
286 
287  while(MinList[Index1 = *RunningAddress2] <= CurrentMax)
288 // while(PosList[Index1 = *RunningAddress] <= CurrentMax)
289  {
290 // if(Index0!=Index1)
291 // {
292  if(array[Index0]->Intersect(*array[Index1], Axis1))
293  {
294  if(array[Index0]->Intersect(*array[Index1], Axis2))
295  {
296  pairs.AddPair(Index0, Index1);
297  }
298  }
299 // }
300 
301  RunningAddress2++;
302 // RunningAddress++;
303  }
304  }
305  }
306 
307  DELETEARRAY(MinList);
308 #endif
309 
310  return true;
311 }
312 
314 // Brute-force versions are kept:
315 // - to check the optimized versions return the correct list of intersections
316 // - to check the speed of the optimized code against the brute-force one
318 
320 
329 bool Opcode::BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs)
331 {
332  // Checkings
333  if(!nb0 || !array0 || !nb1 || !array1) return false;
334 
335  // Brute-force nb0*nb1 overlap tests
336  for(udword i=0;i<nb0;i++)
337  {
338  for(udword j=0;j<nb1;j++)
339  {
340  if(array0[i]->Intersect(*array1[j])) pairs.AddPair(i, j);
341  }
342  }
343  return true;
344 }
345 
347 
354 bool Opcode::BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs)
356 {
357  // Checkings
358  if(!nb || !array) return false;
359 
360  // Brute-force n(n-1)/2 overlap tests
361  for(udword i=0;i<nb;i++)
362  {
363  for(udword j=i+1;j<nb;j++)
364  {
365  if(array[i]->Intersect(*array[j])) pairs.AddPair(i, j);
366  }
367  }
368  return true;
369 }
370