1 /* 2 Bullet Continuous Collision Detection and Physics Library 3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ 4 5 This software is provided 'as-is', without any express or implied warranty. 6 In no event will the authors be held liable for any damages arising from the use of this software. 7 Permission is granted to anyone to use this software for any purpose, 8 including commercial applications, and to alter it and redistribute it freely, 9 subject to the following restrictions: 10 11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 3. This notice may not be removed or altered from any source distribution. 14 */ 15 16 17 18 #include "btHashedSimplePairCache.h" 19 20 21 #include <stdio.h> 22 23 int gOverlappingSimplePairs = 0; 24 int gRemoveSimplePairs =0; 25 int gAddedSimplePairs =0; 26 int gFindSimplePairs =0; 27 28 29 30 31 btHashedSimplePairCache::btHashedSimplePairCache(): 32 m_blockedForChanges(false) 33 { 34 int initialAllocatedSize= 2; 35 m_overlappingPairArray.reserve(initialAllocatedSize); 36 growTables(); 37 } 38 39 40 41 42 btHashedSimplePairCache::~btHashedSimplePairCache() 43 { 44 } 45 46 47 48 49 50 51 void btHashedSimplePairCache::removeAllPairs() 52 { 53 m_overlappingPairArray.clear(); 54 m_hashTable.clear(); 55 m_next.clear(); 56 57 int initialAllocatedSize= 2; 58 m_overlappingPairArray.reserve(initialAllocatedSize); 59 growTables(); 60 } 61 62 63 64 btSimplePair* btHashedSimplePairCache::findPair(int indexA, int indexB) 65 { 66 gFindSimplePairs++; 67 68 69 /*if (indexA > indexB) 70 btSwap(indexA, indexB);*/ 71 72 int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); 73 74 if (hash >= m_hashTable.size()) 75 { 76 return NULL; 77 } 78 79 int index = m_hashTable[hash]; 80 while (index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], indexA, indexB) == false) 81 { 82 index = m_next[index]; 83 } 84 85 if (index == BT_SIMPLE_NULL_PAIR) 86 { 87 return NULL; 88 } 89 90 btAssert(index < m_overlappingPairArray.size()); 91 92 return &m_overlappingPairArray[index]; 93 } 94 95 //#include <stdio.h> 96 97 void btHashedSimplePairCache::growTables() 98 { 99 100 int newCapacity = m_overlappingPairArray.capacity(); 101 102 if (m_hashTable.size() < newCapacity) 103 { 104 //grow hashtable and next table 105 int curHashtableSize = m_hashTable.size(); 106 107 m_hashTable.resize(newCapacity); 108 m_next.resize(newCapacity); 109 110 111 int i; 112 113 for (i= 0; i < newCapacity; ++i) 114 { 115 m_hashTable[i] = BT_SIMPLE_NULL_PAIR; 116 } 117 for (i = 0; i < newCapacity; ++i) 118 { 119 m_next[i] = BT_SIMPLE_NULL_PAIR; 120 } 121 122 for(i=0;i<curHashtableSize;i++) 123 { 124 125 const btSimplePair& pair = m_overlappingPairArray[i]; 126 int indexA = pair.m_indexA; 127 int indexB = pair.m_indexB; 128 129 int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask 130 m_next[i] = m_hashTable[hashValue]; 131 m_hashTable[hashValue] = i; 132 } 133 134 135 } 136 } 137 138 btSimplePair* btHashedSimplePairCache::internalAddPair(int indexA, int indexB) 139 { 140 141 int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask 142 143 144 btSimplePair* pair = internalFindPair(indexA, indexB, hash); 145 if (pair != NULL) 146 { 147 return pair; 148 } 149 150 int count = m_overlappingPairArray.size(); 151 int oldCapacity = m_overlappingPairArray.capacity(); 152 void* mem = &m_overlappingPairArray.expandNonInitializing(); 153 154 int newCapacity = m_overlappingPairArray.capacity(); 155 156 if (oldCapacity < newCapacity) 157 { 158 growTables(); 159 //hash with new capacity 160 hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); 161 } 162 163 pair = new (mem) btSimplePair(indexA,indexB); 164 165 pair->m_userPointer = 0; 166 167 m_next[count] = m_hashTable[hash]; 168 m_hashTable[hash] = count; 169 170 return pair; 171 } 172 173 174 175 void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB) 176 { 177 gRemoveSimplePairs++; 178 179 180 /*if (indexA > indexB) 181 btSwap(indexA, indexB);*/ 182 183 int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); 184 185 btSimplePair* pair = internalFindPair(indexA, indexB, hash); 186 if (pair == NULL) 187 { 188 return 0; 189 } 190 191 192 void* userData = pair->m_userPointer; 193 194 195 int pairIndex = int(pair - &m_overlappingPairArray[0]); 196 btAssert(pairIndex < m_overlappingPairArray.size()); 197 198 // Remove the pair from the hash table. 199 int index = m_hashTable[hash]; 200 btAssert(index != BT_SIMPLE_NULL_PAIR); 201 202 int previous = BT_SIMPLE_NULL_PAIR; 203 while (index != pairIndex) 204 { 205 previous = index; 206 index = m_next[index]; 207 } 208 209 if (previous != BT_SIMPLE_NULL_PAIR) 210 { 211 btAssert(m_next[previous] == pairIndex); 212 m_next[previous] = m_next[pairIndex]; 213 } 214 else 215 { 216 m_hashTable[hash] = m_next[pairIndex]; 217 } 218 219 // We now move the last pair into spot of the 220 // pair being removed. We need to fix the hash 221 // table indices to support the move. 222 223 int lastPairIndex = m_overlappingPairArray.size() - 1; 224 225 // If the removed pair is the last pair, we are done. 226 if (lastPairIndex == pairIndex) 227 { 228 m_overlappingPairArray.pop_back(); 229 return userData; 230 } 231 232 // Remove the last pair from the hash table. 233 const btSimplePair* last = &m_overlappingPairArray[lastPairIndex]; 234 /* missing swap here too, Nat. */ 235 int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_indexA), static_cast<unsigned int>(last->m_indexB)) & (m_overlappingPairArray.capacity()-1)); 236 237 index = m_hashTable[lastHash]; 238 btAssert(index != BT_SIMPLE_NULL_PAIR); 239 240 previous = BT_SIMPLE_NULL_PAIR; 241 while (index != lastPairIndex) 242 { 243 previous = index; 244 index = m_next[index]; 245 } 246 247 if (previous != BT_SIMPLE_NULL_PAIR) 248 { 249 btAssert(m_next[previous] == lastPairIndex); 250 m_next[previous] = m_next[lastPairIndex]; 251 } 252 else 253 { 254 m_hashTable[lastHash] = m_next[lastPairIndex]; 255 } 256 257 // Copy the last pair into the remove pair's spot. 258 m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex]; 259 260 // Insert the last pair into the hash table 261 m_next[pairIndex] = m_hashTable[lastHash]; 262 m_hashTable[lastHash] = pairIndex; 263 264 m_overlappingPairArray.pop_back(); 265 266 return userData; 267 } 268 //#include <stdio.h> 269 270 271 272 273 274 275 276 277 278 279