2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
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:
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.
16 #ifndef B3_OBJECT_ARRAY__
17 #define B3_OBJECT_ARRAY__
19 #include "b3Scalar.h" // has definitions like B3_FORCE_INLINE
20 #include "b3AlignedAllocator.h"
22 ///If the platform doesn't support placement new, you can disable B3_USE_PLACEMENT_NEW
23 ///then the b3AlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors
24 ///You can enable B3_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator=
25 ///see discussion here: https://bulletphysics.orgphpBB2/viewtopic.php?t=1231 and
26 ///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240
28 #define B3_USE_PLACEMENT_NEW 1
29 //#define B3_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
30 #define B3_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
35 #endif //B3_USE_MEMCPY
37 #ifdef B3_USE_PLACEMENT_NEW
38 #include <new> //for placement new
39 #endif //B3_USE_PLACEMENT_NEW
41 ///The b3AlignedObjectArray template class uses a subset of the stl::vector interface for its methods
42 ///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
45 class b3AlignedObjectArray
47 b3AlignedAllocator<T, 16> m_allocator;
52 //PCK: added this line
55 #ifdef B3_ALLOW_ARRAY_COPY_OPERATOR
57 B3_FORCE_INLINE b3AlignedObjectArray<T>& operator=(const b3AlignedObjectArray<T>& other)
62 #else //B3_ALLOW_ARRAY_COPY_OPERATOR
64 B3_FORCE_INLINE b3AlignedObjectArray<T>& operator=(const b3AlignedObjectArray<T>& other);
65 #endif //B3_ALLOW_ARRAY_COPY_OPERATOR
68 B3_FORCE_INLINE int allocSize(int size)
70 return (size ? size * 2 : 1);
72 B3_FORCE_INLINE void copy(int start, int end, T* dest) const
75 for (i = start; i < end; ++i)
76 #ifdef B3_USE_PLACEMENT_NEW
77 new (&dest[i]) T(m_data[i]);
80 #endif //B3_USE_PLACEMENT_NEW
83 B3_FORCE_INLINE void init()
85 //PCK: added this line
91 B3_FORCE_INLINE void destroy(int first, int last)
94 for (i = first; i < last; i++)
100 B3_FORCE_INLINE void* allocate(int size)
103 return m_allocator.allocate(size);
107 B3_FORCE_INLINE void deallocate()
111 //PCK: enclosed the deallocation in this block
114 m_allocator.deallocate(m_data);
121 b3AlignedObjectArray()
126 ~b3AlignedObjectArray()
131 ///Generally it is best to avoid using the copy constructor of an b3AlignedObjectArray, and use a (const) reference to the array instead.
132 b3AlignedObjectArray(const b3AlignedObjectArray& otherArray)
136 int otherSize = otherArray.size();
138 //don't use otherArray.copy, it can leak memory
139 for (int i = 0; i < otherSize; i++)
141 m_data[i] = otherArray[i];
145 /// return the number of elements in the array
146 B3_FORCE_INLINE int size() const
151 B3_FORCE_INLINE const T& at(int n) const
154 b3Assert(n < size());
158 B3_FORCE_INLINE T& at(int n)
161 b3Assert(n < size());
165 B3_FORCE_INLINE const T& operator[](int n) const
168 b3Assert(n < size());
172 B3_FORCE_INLINE T& operator[](int n)
175 b3Assert(n < size());
179 ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
180 B3_FORCE_INLINE void clear()
189 B3_FORCE_INLINE void pop_back()
191 b3Assert(m_size > 0);
196 ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
197 ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
198 B3_FORCE_INLINE void resizeNoInitialize(int newsize)
200 int curSize = size();
202 if (newsize < curSize)
207 if (newsize > size())
211 //leave this uninitialized
216 B3_FORCE_INLINE void resize(int newsize, const T& fillData = T())
218 int curSize = size();
220 if (newsize < curSize)
222 for (int i = newsize; i < curSize; i++)
229 if (newsize > size())
233 #ifdef B3_USE_PLACEMENT_NEW
234 for (int i = curSize; i < newsize; i++)
236 new (&m_data[i]) T(fillData);
238 #endif //B3_USE_PLACEMENT_NEW
243 B3_FORCE_INLINE T& expandNonInitializing()
246 if (sz == capacity())
248 reserve(allocSize(size()));
255 B3_FORCE_INLINE T& expand(const T& fillValue = T())
258 if (sz == capacity())
260 reserve(allocSize(size()));
263 #ifdef B3_USE_PLACEMENT_NEW
264 new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
270 B3_FORCE_INLINE void push_back(const T& _Val)
273 if (sz == capacity())
275 reserve(allocSize(size()));
278 #ifdef B3_USE_PLACEMENT_NEW
279 new (&m_data[m_size]) T(_Val);
281 m_data[size()] = _Val;
282 #endif //B3_USE_PLACEMENT_NEW
287 /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
288 B3_FORCE_INLINE int capacity() const
293 B3_FORCE_INLINE void reserve(int _Count)
294 { // determine new minimum length of allocated storage
295 if (capacity() < _Count)
296 { // not enough room, reallocate
297 T* s = (T*)allocate(_Count);
301 b3Error("b3AlignedObjectArray reserve out-of-memory\n");
311 //PCK: added this line
323 bool operator()(const T& a, const T& b)
329 template <typename L>
330 void quickSortInternal(const L& CompareFunc, int lo, int hi)
332 // lo is the lower index, hi is the upper index
333 // of the region of array a that is to be sorted
335 T x = m_data[(lo + hi) / 2];
340 while (CompareFunc(m_data[i], x))
342 while (CompareFunc(x, m_data[j]))
354 quickSortInternal(CompareFunc, lo, j);
356 quickSortInternal(CompareFunc, i, hi);
359 template <typename L>
360 void quickSort(const L& CompareFunc)
362 //don't sort 0 or 1 elements
365 quickSortInternal(CompareFunc, 0, size() - 1);
369 ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
370 template <typename L>
371 void downHeap(T* pArr, int k, int n, const L& CompareFunc)
373 /* PRE: a[k+1..N] is a heap */
374 /* POST: a[k..N] is a heap */
376 T temp = pArr[k - 1];
382 if ((child < n) && CompareFunc(pArr[child - 1], pArr[child]))
386 /* pick larger child */
387 if (CompareFunc(temp, pArr[child - 1]))
390 pArr[k - 1] = pArr[child - 1];
401 void swap(int index0, int index1)
404 char temp[sizeof(T)];
405 memcpy(temp, &m_data[index0], sizeof(T));
406 memcpy(&m_data[index0], &m_data[index1], sizeof(T));
407 memcpy(&m_data[index1], temp, sizeof(T));
409 T temp = m_data[index0];
410 m_data[index0] = m_data[index1];
411 m_data[index1] = temp;
412 #endif //B3_USE_PLACEMENT_NEW
415 template <typename L>
416 void heapSort(const L& CompareFunc)
418 /* sort a[0..N-1], N.B. 0 to N-1 */
421 for (k = n / 2; k > 0; k--)
423 downHeap(m_data, k, n, CompareFunc);
426 /* a[1..N] is now a heap */
429 swap(0, n - 1); /* largest of a[0..n-1] */
432 /* restore a[1..i-1] heap */
433 downHeap(m_data, 1, n, CompareFunc);
437 ///non-recursive binary search, assumes sorted array
438 int findBinarySearch(const T& key) const
441 int last = size() - 1;
443 //assume sorted array
444 while (first <= last)
446 int mid = (first + last) / 2; // compute mid point.
447 if (key > m_data[mid])
448 first = mid + 1; // repeat search in top half.
449 else if (key < m_data[mid])
450 last = mid - 1; // repeat search in bottom half.
452 return mid; // found it. return position /////
454 return size(); // failed to find key
457 int findLinearSearch(const T& key) const
462 for (i = 0; i < size(); i++)
464 if (m_data[i] == key)
473 int findLinearSearch2(const T& key) const
478 for (i = 0; i < size(); i++)
480 if (m_data[i] == key)
489 void remove(const T& key)
491 int findIndex = findLinearSearch(key);
492 if (findIndex < size())
494 swap(findIndex, size() - 1);
499 //PCK: whole function
500 void initializeFromBuffer(void* buffer, int size, int capacity)
503 m_ownsMemory = false;
506 m_capacity = capacity;
509 void copyFromArray(const b3AlignedObjectArray& otherArray)
511 int otherSize = otherArray.size();
513 //don't use otherArray.copy, it can leak memory
514 for (int i = 0; i < otherSize; i++)
516 m_data[i] = otherArray[i];
520 void removeAtIndex(int index)
524 swap(index, size() - 1);
530 #endif //B3_OBJECT_ARRAY__