OPC_BoxPruning.cpp
Go to the documentation of this file.
00001 
00002 /*
00003  *      OPCODE - Optimized Collision Detection
00004  *      Copyright (C) 2001 Pierre Terdiman
00005  *      Homepage: http://www.codercorner.com/Opcode.htm
00006  */
00008 
00010 
00016 
00017 
00018 /*
00020         You could use a complex sweep-and-prune as implemented in I-Collide.
00021         You could use a complex hashing scheme as implemented in V-Clip or recently in ODE it seems.
00022         You could use a "Recursive Dimensional Clustering" algorithm as implemented in GPG2.
00023 
00024         Or you could use this.
00025         Faster ? I don't know. Probably not. It would be a shame. But who knows ?
00026         Easier ? Definitely. Enjoy the sheer simplicity.
00028 */
00029 
00030 
00032 // Precompiled Header
00033 #include "Stdafx.h"
00034 
00035 using namespace Opcode;
00036 
00037         inline_ void FindRunningIndex(udword& index, float* array, udword* sorted, int last, float max)
00038         {
00039                 int First=index;
00040                 while(First<=last)
00041                 {
00042                         index = (First+last)>>1;
00043 
00044                         if(max>array[sorted[index]])    First   = index+1;
00045                         else                                                    last    = index-1;
00046                 }
00047         }
00048 // ### could be log(n) !
00049 // and maybe use cmp integers
00050 
00051 // InsertionSort has better coherence, RadixSort is better for one-shot queries.
00052 #define PRUNING_SORTER  RadixSort
00053 //#define PRUNING_SORTER        InsertionSort
00054 
00055 // Static for coherence
00056 static PRUNING_SORTER* gCompletePruningSorter = null;
00057 static PRUNING_SORTER* gBipartitePruningSorter0 = null;
00058 static PRUNING_SORTER* gBipartitePruningSorter1 = null;
00059 inline_ PRUNING_SORTER* GetCompletePruningSorter()
00060 {
00061         if(!gCompletePruningSorter)     gCompletePruningSorter = new PRUNING_SORTER;
00062         return gCompletePruningSorter;
00063 }
00064 inline_ PRUNING_SORTER* GetBipartitePruningSorter0()
00065 {
00066         if(!gBipartitePruningSorter0)   gBipartitePruningSorter0 = new PRUNING_SORTER;
00067         return gBipartitePruningSorter0;
00068 }
00069 inline_ PRUNING_SORTER* GetBipartitePruningSorter1()
00070 {
00071         if(!gBipartitePruningSorter1)   gBipartitePruningSorter1 = new PRUNING_SORTER;
00072         return gBipartitePruningSorter1;
00073 }
00074 void ReleasePruningSorters()
00075 {
00076         DELETESINGLE(gBipartitePruningSorter1);
00077         DELETESINGLE(gBipartitePruningSorter0);
00078         DELETESINGLE(gCompletePruningSorter);
00079 }
00080 
00081 
00083 
00093 
00094 bool Opcode::BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes)
00095 {
00096         // Checkings
00097         if(!nb0 || !array0 || !nb1 || !array1)  return false;
00098 
00099         // Catch axes
00100         udword Axis0 = axes.mAxis0;
00101         udword Axis1 = axes.mAxis1;
00102         udword Axis2 = axes.mAxis2;
00103 
00104         // Allocate some temporary data
00105         float* MinPosList0 = new float[nb0];
00106         float* MinPosList1 = new float[nb1];
00107 
00108         // 1) Build main lists using the primary axis
00109         for(udword i=0;i<nb0;i++)       MinPosList0[i] = array0[i]->GetMin(Axis0);
00110         for(udword i=0;i<nb1;i++)       MinPosList1[i] = array1[i]->GetMin(Axis0);
00111 
00112         // 2) Sort the lists
00113         PRUNING_SORTER* RS0 = GetBipartitePruningSorter0();
00114         PRUNING_SORTER* RS1 = GetBipartitePruningSorter1();
00115         const udword* Sorted0 = RS0->Sort(MinPosList0, nb0).GetRanks();
00116         const udword* Sorted1 = RS1->Sort(MinPosList1, nb1).GetRanks();
00117 
00118         // 3) Prune the lists
00119         udword Index0, Index1;
00120 
00121         const udword* const LastSorted0 = &Sorted0[nb0];
00122         const udword* const LastSorted1 = &Sorted1[nb1];
00123         const udword* RunningAddress0 = Sorted0;
00124         const udword* RunningAddress1 = Sorted1;
00125 
00126         while(RunningAddress1<LastSorted1 && Sorted0<LastSorted0)
00127         {
00128                 Index0 = *Sorted0++;
00129 
00130                 while(RunningAddress1<LastSorted1 && MinPosList1[*RunningAddress1]<MinPosList0[Index0]) RunningAddress1++;
00131 
00132                 const udword* RunningAddress2_1 = RunningAddress1;
00133 
00134                 while(RunningAddress2_1<LastSorted1 && MinPosList1[Index1 = *RunningAddress2_1++]<=array0[Index0]->GetMax(Axis0))
00135                 {
00136                         if(array0[Index0]->Intersect(*array1[Index1], Axis1))
00137                         {
00138                                 if(array0[Index0]->Intersect(*array1[Index1], Axis2))
00139                                 {
00140                                         pairs.AddPair(Index0, Index1);
00141                                 }
00142                         }
00143                 }
00144         }
00145 
00147 
00148         while(RunningAddress0<LastSorted0 && Sorted1<LastSorted1)
00149         {
00150                 Index0 = *Sorted1++;
00151 
00152                 while(RunningAddress0<LastSorted0 && MinPosList0[*RunningAddress0]<=MinPosList1[Index0])        RunningAddress0++;
00153 
00154                 const udword* RunningAddress2_0 = RunningAddress0;
00155 
00156                 while(RunningAddress2_0<LastSorted0 && MinPosList0[Index1 = *RunningAddress2_0++]<=array1[Index0]->GetMax(Axis0))
00157                 {
00158                         if(array0[Index1]->Intersect(*array1[Index0], Axis1))
00159                         {
00160                                 if(array0[Index1]->Intersect(*array1[Index0], Axis2))
00161                                 {
00162                                         pairs.AddPair(Index1, Index0);
00163                                 }
00164                         }
00165 
00166                 }
00167         }
00168 
00169         DELETEARRAY(MinPosList1);
00170         DELETEARRAY(MinPosList0);
00171 
00172         return true;
00173 }
00174 
00175 #define ORIGINAL_VERSION
00176 //#define JOAKIM
00177 
00179 
00187 
00188 bool Opcode::CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes)
00189 {
00190         // Checkings
00191         if(!nb || !array)       return false;
00192 
00193         // Catch axes
00194         udword Axis0 = axes.mAxis0;
00195         udword Axis1 = axes.mAxis1;
00196         udword Axis2 = axes.mAxis2;
00197 
00198 #ifdef ORIGINAL_VERSION
00199         // Allocate some temporary data
00200 //      float* PosList = new float[nb];
00201         float* PosList = new float[nb+1];
00202 
00203         // 1) Build main list using the primary axis
00204         for(udword i=0;i<nb;i++)        PosList[i] = array[i]->GetMin(Axis0);
00205 PosList[nb++] = MAX_FLOAT;
00206 
00207         // 2) Sort the list
00208         PRUNING_SORTER* RS = GetCompletePruningSorter();
00209         const udword* Sorted = RS->Sort(PosList, nb).GetRanks();
00210 
00211         // 3) Prune the list
00212         const udword* const LastSorted = &Sorted[nb];
00213         const udword* RunningAddress = Sorted;
00214         udword Index0, Index1;
00215         while(RunningAddress<LastSorted && Sorted<LastSorted)
00216         {
00217                 Index0 = *Sorted++;
00218 
00219 //              while(RunningAddress<LastSorted && PosList[*RunningAddress++]<PosList[Index0]);
00220                 while(PosList[*RunningAddress++]<PosList[Index0]);
00221 
00222                 if(RunningAddress<LastSorted)
00223                 {
00224                         const udword* RunningAddress2 = RunningAddress;
00225 
00226 //                      while(RunningAddress2<LastSorted && PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0))
00227                         while(PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0))
00228                         {
00229 //                              if(Index0!=Index1)
00230 //                              {
00231                                         if(array[Index0]->Intersect(*array[Index1], Axis1))
00232                                         {
00233                                                 if(array[Index0]->Intersect(*array[Index1], Axis2))
00234                                                 {
00235                                                         pairs.AddPair(Index0, Index1);
00236                                                 }
00237                                         }
00238 //                              }
00239                         }
00240                 }
00241         }
00242 
00243         DELETEARRAY(PosList);
00244 #endif
00245 
00246 #ifdef JOAKIM
00247         // Allocate some temporary data
00248 //      float* PosList = new float[nb];
00249         float* MinList = new float[nb+1];
00250 
00251         // 1) Build main list using the primary axis
00252         for(udword i=0;i<nb;i++)        MinList[i] = array[i]->GetMin(Axis0);
00253         MinList[nb] = MAX_FLOAT;
00254 
00255         // 2) Sort the list
00256         PRUNING_SORTER* RS = GetCompletePruningSorter();
00257         udword* Sorted = RS->Sort(MinList, nb+1).GetRanks();
00258 
00259         // 3) Prune the list
00260 //      const udword* const LastSorted = &Sorted[nb];
00261 //      const udword* const LastSorted = &Sorted[nb-1];
00262         const udword* RunningAddress = Sorted;
00263         udword Index0, Index1;
00264 
00265 //      while(RunningAddress<LastSorted && Sorted<LastSorted)
00266 //      while(RunningAddress<LastSorted)
00267         while(RunningAddress<&Sorted[nb])
00268 //      while(Sorted<LastSorted)
00269         {
00270 //              Index0 = *Sorted++;
00271                 Index0 = *RunningAddress++;
00272 
00273 //              while(RunningAddress<LastSorted && PosList[*RunningAddress++]<PosList[Index0]);
00274 //              while(PosList[*RunningAddress++]<PosList[Index0]);
00275 //RunningAddress = Sorted;
00276 //              if(RunningAddress<LastSorted)
00277                 {
00278                         const udword* RunningAddress2 = RunningAddress;
00279 
00280 //                      while(RunningAddress2<LastSorted && PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0))
00281 
00282 //                      float CurrentMin = array[Index0]->GetMin(Axis0);
00283                         float CurrentMax = array[Index0]->GetMax(Axis0);
00284 
00285                         while(MinList[Index1 = *RunningAddress2] <= CurrentMax)
00286 //                      while(PosList[Index1 = *RunningAddress] <= CurrentMax)
00287                         {
00288 //                              if(Index0!=Index1)
00289 //                              {
00290                                         if(array[Index0]->Intersect(*array[Index1], Axis1))
00291                                         {
00292                                                 if(array[Index0]->Intersect(*array[Index1], Axis2))
00293                                                 {
00294                                                         pairs.AddPair(Index0, Index1);
00295                                                 }
00296                                         }
00297 //                              }
00298 
00299                                 RunningAddress2++;
00300 //                              RunningAddress++;
00301                         }
00302                 }
00303         }
00304 
00305         DELETEARRAY(MinList);
00306 #endif
00307 
00308         return true;
00309 }
00310 
00312 // Brute-force versions are kept:
00313 // - to check the optimized versions return the correct list of intersections
00314 // - to check the speed of the optimized code against the brute-force one
00316 
00318 
00327 
00328 bool Opcode::BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs)
00329 {
00330         // Checkings
00331         if(!nb0 || !array0 || !nb1 || !array1)  return false;
00332 
00333         // Brute-force nb0*nb1 overlap tests
00334         for(udword i=0;i<nb0;i++)
00335         {
00336                 for(udword j=0;j<nb1;j++)
00337                 {
00338                         if(array0[i]->Intersect(*array1[j]))    pairs.AddPair(i, j);
00339                 }
00340         }
00341         return true;
00342 }
00343 
00345 
00352 
00353 bool Opcode::BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs)
00354 {
00355         // Checkings
00356         if(!nb || !array)       return false;
00357 
00358         // Brute-force n(n-1)/2 overlap tests
00359         for(udword i=0;i<nb;i++)
00360         {
00361                 for(udword j=i+1;j<nb;j++)
00362                 {
00363                         if(array[i]->Intersect(*array[j]))      pairs.AddPair(i, j);
00364                 }
00365         }
00366         return true;
00367 }


openhrp3
Author(s): AIST, General Robotix Inc., Nakamura Lab of Dept. of Mechano Informatics at University of Tokyo
autogenerated on Sun Apr 2 2017 03:43:55