Code-style consistency improvement:

Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files.
make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type.
This commit contains no other changes aside from adding and applying clang-format-all.sh
This commit is contained in:
erwincoumans
2018-09-23 14:17:31 -07:00
parent b73b05e9fb
commit ab8f16961e
1773 changed files with 1081087 additions and 474249 deletions

View File

@@ -25,10 +25,10 @@ subject to the following restrictions:
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
#define btAlignedAlloc(a, b) \
btAlignedAllocInternal(a, b, __LINE__, __FILE__)
btAlignedAllocInternal(a, b, __LINE__, __FILE__)
#define btAlignedFree(ptr) \
btAlignedFreeInternal(ptr, __LINE__, __FILE__)
btAlignedFreeInternal(ptr, __LINE__, __FILE__)
void* btAlignedAllocInternal(size_t size, int alignment, int line, char* filename);
@@ -57,48 +57,54 @@ void btAlignedAllocSetCustomAligned(btAlignedAllocFunc* allocFunc, btAlignedFree
///The btAlignedAllocator is a portable class for aligned memory allocations.
///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned.
template <typename T, unsigned Alignment>
class btAlignedAllocator {
typedef btAlignedAllocator<T, Alignment> self_type;
class btAlignedAllocator
{
typedef btAlignedAllocator<T, Alignment> self_type;
public:
//just going down a list:
btAlignedAllocator() {}
/*
//just going down a list:
btAlignedAllocator() {}
/*
btAlignedAllocator( const self_type & ) {}
*/
template <typename Other>
btAlignedAllocator(const btAlignedAllocator<Other, Alignment>&) {}
template <typename Other>
btAlignedAllocator(const btAlignedAllocator<Other, Alignment>&)
{
}
typedef const T* const_pointer;
typedef const T& const_reference;
typedef T* pointer;
typedef T& reference;
typedef T value_type;
typedef const T* const_pointer;
typedef const T& const_reference;
typedef T* pointer;
typedef T& reference;
typedef T value_type;
pointer address(reference ref) const { return &ref; }
const_pointer address(const_reference ref) const { return &ref; }
pointer allocate(size_type n, const_pointer* hint = 0)
{
(void)hint;
return reinterpret_cast<pointer>(btAlignedAlloc(sizeof(value_type) * n, Alignment));
}
void construct(pointer ptr, const value_type& value) { new (ptr) value_type(value); }
void deallocate(pointer ptr)
{
btAlignedFree(reinterpret_cast<void*>(ptr));
}
void destroy(pointer ptr) { ptr->~value_type(); }
pointer address(reference ref) const { return &ref; }
const_pointer address(const_reference ref) const { return &ref; }
pointer allocate(size_type n, const_pointer* hint = 0)
{
(void)hint;
return reinterpret_cast<pointer>(btAlignedAlloc(sizeof(value_type) * n, Alignment));
}
void construct(pointer ptr, const value_type& value) { new (ptr) value_type(value); }
void deallocate(pointer ptr)
{
btAlignedFree(reinterpret_cast<void*>(ptr));
}
void destroy(pointer ptr) { ptr->~value_type(); }
template <typename O>
struct rebind {
typedef btAlignedAllocator<O, Alignment> other;
};
template <typename O>
self_type& operator=(const btAlignedAllocator<O, Alignment>&) { return *this; }
template <typename O>
struct rebind
{
typedef btAlignedAllocator<O, Alignment> other;
};
template <typename O>
self_type& operator=(const btAlignedAllocator<O, Alignment>&)
{
return *this;
}
friend bool operator==(const self_type&, const self_type&) { return true; }
friend bool operator==(const self_type&, const self_type&) { return true; }
};
#endif //BT_ALIGNED_ALLOCATOR
#endif //BT_ALIGNED_ALLOCATOR

View File

@@ -17,7 +17,7 @@ subject to the following restrictions:
#define BT_OBJECT_ARRAY__
#include "btAlignedAllocator.h"
#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW
///then the btAlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors
@@ -27,422 +27,448 @@ subject to the following restrictions:
#define BT_USE_PLACEMENT_NEW 1
//#define BT_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...
#define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
#define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
#ifdef BT_USE_MEMCPY
#include <memory.h>
#include <string.h>
#endif //BT_USE_MEMCPY
#endif //BT_USE_MEMCPY
#ifdef BT_USE_PLACEMENT_NEW
#include <new> //for placement new
#endif //BT_USE_PLACEMENT_NEW
#include <new> //for placement new
#endif //BT_USE_PLACEMENT_NEW
///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods
///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
template <typename T>
//template <class T>
class btAlignedObjectArray {
btAlignedAllocator<T, 16> m_allocator;
class btAlignedObjectArray
{
btAlignedAllocator<T, 16> m_allocator;
int m_size;
int m_capacity;
T* m_data;
//PCK: added this line
bool m_ownsMemory;
int m_size;
int m_capacity;
T* m_data;
//PCK: added this line
bool m_ownsMemory;
#ifdef BT_ALLOW_ARRAY_COPY_OPERATOR
public:
SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other)
{
copyFromArray(other);
return *this;
}
#else //BT_ALLOW_ARRAY_COPY_OPERATOR
SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other)
{
copyFromArray(other);
return *this;
}
#else //BT_ALLOW_ARRAY_COPY_OPERATOR
private:
SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other);
#endif //BT_ALLOW_ARRAY_COPY_OPERATOR
SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other);
#endif //BT_ALLOW_ARRAY_COPY_OPERATOR
protected:
SIMD_FORCE_INLINE int allocSize(int size)
{
return (size ? size * 2 : 1);
}
SIMD_FORCE_INLINE void copy(int start, int end, T* dest) const
{
int i;
for (i = start; i < end; ++i)
SIMD_FORCE_INLINE int allocSize(int size)
{
return (size ? size * 2 : 1);
}
SIMD_FORCE_INLINE void copy(int start, int end, T* dest) const
{
int i;
for (i = start; i < end; ++i)
#ifdef BT_USE_PLACEMENT_NEW
new (&dest[i]) T(m_data[i]);
new (&dest[i]) T(m_data[i]);
#else
dest[i] = m_data[i];
#endif //BT_USE_PLACEMENT_NEW
}
dest[i] = m_data[i];
#endif //BT_USE_PLACEMENT_NEW
}
SIMD_FORCE_INLINE void init()
{
//PCK: added this line
m_ownsMemory = true;
m_data = 0;
m_size = 0;
m_capacity = 0;
}
SIMD_FORCE_INLINE void destroy(int first, int last)
{
int i;
for (i = first; i < last; i++) {
m_data[i].~T();
}
}
SIMD_FORCE_INLINE void init()
{
//PCK: added this line
m_ownsMemory = true;
m_data = 0;
m_size = 0;
m_capacity = 0;
}
SIMD_FORCE_INLINE void destroy(int first, int last)
{
int i;
for (i = first; i < last; i++)
{
m_data[i].~T();
}
}
SIMD_FORCE_INLINE void* allocate(int size)
{
if (size)
return m_allocator.allocate(size);
return 0;
}
SIMD_FORCE_INLINE void* allocate(int size)
{
if (size)
return m_allocator.allocate(size);
return 0;
}
SIMD_FORCE_INLINE void deallocate()
{
if (m_data) {
//PCK: enclosed the deallocation in this block
if (m_ownsMemory) {
m_allocator.deallocate(m_data);
}
m_data = 0;
}
}
SIMD_FORCE_INLINE void deallocate()
{
if (m_data)
{
//PCK: enclosed the deallocation in this block
if (m_ownsMemory)
{
m_allocator.deallocate(m_data);
}
m_data = 0;
}
}
public:
btAlignedObjectArray()
{
init();
}
btAlignedObjectArray()
{
init();
}
~btAlignedObjectArray()
{
clear();
}
~btAlignedObjectArray()
{
clear();
}
///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
btAlignedObjectArray(const btAlignedObjectArray& otherArray)
{
init();
///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
btAlignedObjectArray(const btAlignedObjectArray& otherArray)
{
init();
int otherSize = otherArray.size();
resize(otherSize);
otherArray.copy(0, otherSize, m_data);
}
int otherSize = otherArray.size();
resize(otherSize);
otherArray.copy(0, otherSize, m_data);
}
/// return the number of elements in the array
SIMD_FORCE_INLINE int size() const
{
return m_size;
}
/// return the number of elements in the array
SIMD_FORCE_INLINE int size() const
{
return m_size;
}
SIMD_FORCE_INLINE const T& at(int n) const
{
btAssert(n >= 0);
btAssert(n < size());
return m_data[n];
}
SIMD_FORCE_INLINE const T& at(int n) const
{
btAssert(n >= 0);
btAssert(n < size());
return m_data[n];
}
SIMD_FORCE_INLINE T& at(int n)
{
btAssert(n >= 0);
btAssert(n < size());
return m_data[n];
}
SIMD_FORCE_INLINE T& at(int n)
{
btAssert(n >= 0);
btAssert(n < size());
return m_data[n];
}
SIMD_FORCE_INLINE const T& operator[](int n) const
{
btAssert(n >= 0);
btAssert(n < size());
return m_data[n];
}
SIMD_FORCE_INLINE const T& operator[](int n) const
{
btAssert(n >= 0);
btAssert(n < size());
return m_data[n];
}
SIMD_FORCE_INLINE T& operator[](int n)
{
btAssert(n >= 0);
btAssert(n < size());
return m_data[n];
}
SIMD_FORCE_INLINE T& operator[](int n)
{
btAssert(n >= 0);
btAssert(n < size());
return m_data[n];
}
///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
SIMD_FORCE_INLINE void clear()
{
destroy(0, size());
///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
SIMD_FORCE_INLINE void clear()
{
destroy(0, size());
deallocate();
deallocate();
init();
}
init();
}
SIMD_FORCE_INLINE void pop_back()
{
btAssert(m_size > 0);
m_size--;
m_data[m_size].~T();
}
SIMD_FORCE_INLINE void pop_back()
{
btAssert(m_size > 0);
m_size--;
m_data[m_size].~T();
}
///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.
///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.
SIMD_FORCE_INLINE void resize(int newsize, const T& fillData = T())
{
int curSize = size();
///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.
///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.
SIMD_FORCE_INLINE void resize(int newsize, const T& fillData = T())
{
int curSize = size();
if (newsize < curSize) {
for (int i = newsize; i < curSize; i++) {
m_data[i].~T();
}
}
else {
if (newsize > size()) {
reserve(newsize);
}
if (newsize < curSize)
{
for (int i = newsize; i < curSize; i++)
{
m_data[i].~T();
}
}
else
{
if (newsize > size())
{
reserve(newsize);
}
#ifdef BT_USE_PLACEMENT_NEW
for (int i = curSize; i < newsize; i++) {
new (&m_data[i]) T(fillData);
}
#endif //BT_USE_PLACEMENT_NEW
}
for (int i = curSize; i < newsize; i++)
{
new (&m_data[i]) T(fillData);
}
#endif //BT_USE_PLACEMENT_NEW
}
m_size = newsize;
}
m_size = newsize;
}
SIMD_FORCE_INLINE T& expandNonInitializing()
{
int sz = size();
if (sz == capacity()) {
reserve(allocSize(size()));
}
m_size++;
SIMD_FORCE_INLINE T& expandNonInitializing()
{
int sz = size();
if (sz == capacity())
{
reserve(allocSize(size()));
}
m_size++;
return m_data[sz];
}
return m_data[sz];
}
SIMD_FORCE_INLINE T& expand(const T& fillValue = T())
{
int sz = size();
if (sz == capacity()) {
reserve(allocSize(size()));
}
m_size++;
SIMD_FORCE_INLINE T& expand(const T& fillValue = T())
{
int sz = size();
if (sz == capacity())
{
reserve(allocSize(size()));
}
m_size++;
#ifdef BT_USE_PLACEMENT_NEW
new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
#endif
return m_data[sz];
}
return m_data[sz];
}
SIMD_FORCE_INLINE void push_back(const T& _Val)
{
int sz = size();
if (sz == capacity()) {
reserve(allocSize(size()));
}
SIMD_FORCE_INLINE void push_back(const T& _Val)
{
int sz = size();
if (sz == capacity())
{
reserve(allocSize(size()));
}
#ifdef BT_USE_PLACEMENT_NEW
new (&m_data[m_size]) T(_Val);
new (&m_data[m_size]) T(_Val);
#else
m_data[size()] = _Val;
#endif //BT_USE_PLACEMENT_NEW
m_data[size()] = _Val;
#endif //BT_USE_PLACEMENT_NEW
m_size++;
}
m_size++;
}
/// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
SIMD_FORCE_INLINE int capacity() const
{
return m_capacity;
}
/// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
SIMD_FORCE_INLINE int capacity() const
{
return m_capacity;
}
SIMD_FORCE_INLINE void reserve(int _Count)
{ // determine new minimum length of allocated storage
if (capacity() < _Count) { // not enough room, reallocate
T* s = (T*)allocate(_Count);
SIMD_FORCE_INLINE void reserve(int _Count)
{ // determine new minimum length of allocated storage
if (capacity() < _Count)
{ // not enough room, reallocate
T* s = (T*)allocate(_Count);
copy(0, size(), s);
copy(0, size(), s);
destroy(0, size());
destroy(0, size());
deallocate();
deallocate();
//PCK: added this line
m_ownsMemory = true;
//PCK: added this line
m_ownsMemory = true;
m_data = s;
m_data = s;
m_capacity = _Count;
}
}
m_capacity = _Count;
}
}
class less {
public:
bool operator()(const T& a, const T& b)
{
return (a < b);
}
};
class less
{
public:
bool operator()(const T& a, const T& b)
{
return (a < b);
}
};
template <typename L>
void quickSortInternal(const L& CompareFunc, int lo, int hi)
{
// lo is the lower index, hi is the upper index
// of the region of array a that is to be sorted
int i = lo, j = hi;
T x = m_data[(lo + hi) / 2];
template <typename L>
void quickSortInternal(const L& CompareFunc, int lo, int hi)
{
// lo is the lower index, hi is the upper index
// of the region of array a that is to be sorted
int i = lo, j = hi;
T x = m_data[(lo + hi) / 2];
// partition
do {
while (CompareFunc(m_data[i], x))
i++;
while (CompareFunc(x, m_data[j]))
j--;
if (i <= j) {
swap(i, j);
i++;
j--;
}
} while (i <= j);
// partition
do
{
while (CompareFunc(m_data[i], x))
i++;
while (CompareFunc(x, m_data[j]))
j--;
if (i <= j)
{
swap(i, j);
i++;
j--;
}
} while (i <= j);
// recursion
if (lo < j)
quickSortInternal(CompareFunc, lo, j);
if (i < hi)
quickSortInternal(CompareFunc, i, hi);
}
// recursion
if (lo < j)
quickSortInternal(CompareFunc, lo, j);
if (i < hi)
quickSortInternal(CompareFunc, i, hi);
}
template <typename L>
void quickSort(const L& CompareFunc)
{
//don't sort 0 or 1 elements
if (size() > 1) {
quickSortInternal(CompareFunc, 0, size() - 1);
}
}
template <typename L>
void quickSort(const L& CompareFunc)
{
//don't sort 0 or 1 elements
if (size() > 1)
{
quickSortInternal(CompareFunc, 0, size() - 1);
}
}
///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
template <typename L>
void downHeap(T* pArr, int k, int n, const L& CompareFunc)
{
/* PRE: a[k+1..N] is a heap */
/* POST: a[k..N] is a heap */
///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
template <typename L>
void downHeap(T* pArr, int k, int n, const L& CompareFunc)
{
/* PRE: a[k+1..N] is a heap */
/* POST: a[k..N] is a heap */
T temp = pArr[k - 1];
/* k has child(s) */
while (k <= n / 2) {
int child = 2 * k;
T temp = pArr[k - 1];
/* k has child(s) */
while (k <= n / 2)
{
int child = 2 * k;
if ((child < n) && CompareFunc(pArr[child - 1], pArr[child])) {
child++;
}
/* pick larger child */
if (CompareFunc(temp, pArr[child - 1])) {
/* move child up */
pArr[k - 1] = pArr[child - 1];
k = child;
}
else {
break;
}
}
pArr[k - 1] = temp;
} /*downHeap*/
if ((child < n) && CompareFunc(pArr[child - 1], pArr[child]))
{
child++;
}
/* pick larger child */
if (CompareFunc(temp, pArr[child - 1]))
{
/* move child up */
pArr[k - 1] = pArr[child - 1];
k = child;
}
else
{
break;
}
}
pArr[k - 1] = temp;
} /*downHeap*/
void swap(int index0, int index1)
{
void swap(int index0, int index1)
{
#ifdef BT_USE_MEMCPY
char temp[sizeof(T)];
memcpy(temp, &m_data[index0], sizeof(T));
memcpy(&m_data[index0], &m_data[index1], sizeof(T));
memcpy(&m_data[index1], temp, sizeof(T));
char temp[sizeof(T)];
memcpy(temp, &m_data[index0], sizeof(T));
memcpy(&m_data[index0], &m_data[index1], sizeof(T));
memcpy(&m_data[index1], temp, sizeof(T));
#else
T temp = m_data[index0];
m_data[index0] = m_data[index1];
m_data[index1] = temp;
#endif //BT_USE_PLACEMENT_NEW
}
T temp = m_data[index0];
m_data[index0] = m_data[index1];
m_data[index1] = temp;
#endif //BT_USE_PLACEMENT_NEW
}
template <typename L>
void heapSort(const L& CompareFunc)
{
/* sort a[0..N-1], N.B. 0 to N-1 */
int k;
int n = m_size;
for (k = n / 2; k > 0; k--) {
downHeap(m_data, k, n, CompareFunc);
}
template <typename L>
void heapSort(const L& CompareFunc)
{
/* sort a[0..N-1], N.B. 0 to N-1 */
int k;
int n = m_size;
for (k = n / 2; k > 0; k--)
{
downHeap(m_data, k, n, CompareFunc);
}
/* a[1..N] is now a heap */
while (n >= 1) {
swap(0, n - 1); /* largest of a[0..n-1] */
/* a[1..N] is now a heap */
while (n >= 1)
{
swap(0, n - 1); /* largest of a[0..n-1] */
n = n - 1;
/* restore a[1..i-1] heap */
downHeap(m_data, 1, n, CompareFunc);
}
}
n = n - 1;
/* restore a[1..i-1] heap */
downHeap(m_data, 1, n, CompareFunc);
}
}
///non-recursive binary search, assumes sorted array
int findBinarySearch(const T& key) const
{
int first = 0;
int last = size() - 1;
///non-recursive binary search, assumes sorted array
int findBinarySearch(const T& key) const
{
int first = 0;
int last = size() - 1;
//assume sorted array
while (first <= last) {
int mid = (first + last) / 2; // compute mid point.
if (key > m_data[mid])
first = mid + 1; // repeat search in top half.
else if (key < m_data[mid])
last = mid - 1; // repeat search in bottom half.
else
return mid; // found it. return position /////
}
return size(); // failed to find key
}
//assume sorted array
while (first <= last)
{
int mid = (first + last) / 2; // compute mid point.
if (key > m_data[mid])
first = mid + 1; // repeat search in top half.
else if (key < m_data[mid])
last = mid - 1; // repeat search in bottom half.
else
return mid; // found it. return position /////
}
return size(); // failed to find key
}
int findLinearSearch(const T& key) const
{
int index = size();
int i;
int findLinearSearch(const T& key) const
{
int index = size();
int i;
for (i = 0; i < size(); i++) {
if (m_data[i] == key) {
index = i;
break;
}
}
return index;
}
for (i = 0; i < size(); i++)
{
if (m_data[i] == key)
{
index = i;
break;
}
}
return index;
}
void remove(const T& key)
{
void remove(const T& key)
{
int findIndex = findLinearSearch(key);
if (findIndex < size())
{
swap(findIndex, size() - 1);
pop_back();
}
}
int findIndex = findLinearSearch(key);
if (findIndex < size()) {
swap(findIndex, size() - 1);
pop_back();
}
}
//PCK: whole function
void initializeFromBuffer(void* buffer, int size, int capacity)
{
clear();
m_ownsMemory = false;
m_data = (T*)buffer;
m_size = size;
m_capacity = capacity;
}
//PCK: whole function
void initializeFromBuffer(void* buffer, int size, int capacity)
{
clear();
m_ownsMemory = false;
m_data = (T*)buffer;
m_size = size;
m_capacity = capacity;
}
void copyFromArray(const btAlignedObjectArray& otherArray)
{
int otherSize = otherArray.size();
resize(otherSize);
otherArray.copy(0, otherSize, m_data);
}
void copyFromArray(const btAlignedObjectArray& otherArray)
{
int otherSize = otherArray.size();
resize(otherSize);
otherArray.copy(0, otherSize, m_data);
}
};
#endif //BT_OBJECT_ARRAY__
#endif //BT_OBJECT_ARRAY__

View File

@@ -21,56 +21,58 @@ subject to the following restrictions:
/// Convex hull implementation based on Preparata and Hong
/// See http://code.google.com/p/bullet/issues/detail?id=275
/// Ole Kniemeyer, MAXON Computer GmbH
class btConvexHullComputer {
class btConvexHullComputer
{
private:
btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp);
btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp);
public:
class Edge {
private:
int next;
int reverse;
int targetVertex;
class Edge
{
private:
int next;
int reverse;
int targetVertex;
friend class btConvexHullComputer;
friend class btConvexHullComputer;
public:
int getSourceVertex() const
{
return (this + reverse)->targetVertex;
}
public:
int getSourceVertex() const
{
return (this + reverse)->targetVertex;
}
int getTargetVertex() const
{
return targetVertex;
}
int getTargetVertex() const
{
return targetVertex;
}
const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
{
return this + next;
}
const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
{
return this + next;
}
const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
{
return (this + reverse)->getNextEdgeOfVertex();
}
const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
{
return (this + reverse)->getNextEdgeOfVertex();
}
const Edge* getReverseEdge() const
{
return this + reverse;
}
};
const Edge* getReverseEdge() const
{
return this + reverse;
}
};
// Vertices of the output hull
btAlignedObjectArray<btVector3> vertices;
// Vertices of the output hull
btAlignedObjectArray<btVector3> vertices;
// Edges of the output hull
btAlignedObjectArray<Edge> edges;
// Edges of the output hull
btAlignedObjectArray<Edge> edges;
// Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
btAlignedObjectArray<int> faces;
// Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
btAlignedObjectArray<int> faces;
/*
/*
Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes
between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken
by that amount (each face is moved by "shrink" length units towards the center along its normal).
@@ -82,16 +84,16 @@ public:
The output convex hull can be found in the member variables "vertices", "edges", "faces".
*/
btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
{
return compute(coords, false, stride, count, shrink, shrinkClamp);
}
btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
{
return compute(coords, false, stride, count, shrink, shrinkClamp);
}
// same as above, but double precision
btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
{
return compute(coords, true, stride, count, shrink, shrinkClamp);
}
// same as above, but double precision
btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
{
return compute(coords, true, stride, count, shrink, shrinkClamp);
}
};
#endif //BT_CONVEX_HULL_COMPUTER_H
#endif //BT_CONVEX_HULL_COMPUTER_H

View File

@@ -20,46 +20,50 @@ subject to the following restrictions:
template <class T>
SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b)
{
return a < b ? a : b;
return a < b ? a : b;
}
template <class T>
SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b)
{
return a > b ? a : b;
return a > b ? a : b;
}
template <class T>
SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub)
{
return a < lb ? lb : (ub < a ? ub : a);
return a < lb ? lb : (ub < a ? ub : a);
}
template <class T>
SIMD_FORCE_INLINE void btSetMin(T& a, const T& b)
{
if (b < a) {
a = b;
}
if (b < a)
{
a = b;
}
}
template <class T>
SIMD_FORCE_INLINE void btSetMax(T& a, const T& b)
{
if (a < b) {
a = b;
}
if (a < b)
{
a = b;
}
}
template <class T>
SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub)
{
if (a < lb) {
a = lb;
}
else if (ub < a) {
a = ub;
}
if (a < lb)
{
a = lb;
}
else if (ub < a)
{
a = ub;
}
}
#endif //BT_GEN_MINMAX_H
#endif //BT_GEN_MINMAX_H

View File

@@ -22,14 +22,14 @@ subject to the following restrictions:
#include <float.h>
#include <math.h>
#include <stdlib.h> //size_t for MSVC 6.0
#include <stdlib.h> //size_t for MSVC 6.0
/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
#define BT_BULLET_VERSION 279
inline int btGetVersion()
{
return BT_BULLET_VERSION;
return BT_BULLET_VERSION;
}
#if defined(DEBUG) || defined(_DEBUG)
@@ -46,7 +46,7 @@ inline int btGetVersion()
#define ATTRIBUTE_ALIGNED128(a) a
#else
//#define BT_HAS_ALIGNED_ALLOCATOR
#pragma warning(disable : 4324) // disable padding warning
#pragma warning(disable : 4324) // disable padding warning
// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
// #pragma warning(disable:4996) //Turn off warnings about deprecated C routines
// #pragma warning(disable:4786) // Disable the "debug name too long" warning
@@ -68,9 +68,9 @@ inline int btGetVersion()
#include <emmintrin.h>
#endif
#endif //_XBOX
#endif //_XBOX
#endif //__MINGW32__
#endif //__MINGW32__
#include <assert.h>
#ifdef BT_DEBUG
@@ -99,12 +99,13 @@ inline int btGetVersion()
#include <spu_printf.h>
#define printf spu_printf
#define btAssert(x) \
{ \
if (!(x)) { \
printf("Assert " __FILE__ ":%u (" #x ")\n", __LINE__); \
spu_hcmpeq(0, 0); \
} \
}
{ \
if (!(x)) \
{ \
printf("Assert " __FILE__ ":%u (" #x ")\n", __LINE__); \
spu_hcmpeq(0, 0); \
} \
}
#else
#define btAssert assert
#endif
@@ -191,11 +192,11 @@ inline int btGetVersion()
#define btFullAssert(x)
#define btLikely(_c) _c
#define btUnlikely(_c) _c
#endif //__APPLE__
#endif //__APPLE__
#endif // LIBSPE2
#endif // LIBSPE2
#endif //__CELLOS_LV2__
#endif //__CELLOS_LV2__
#endif
///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
@@ -210,20 +211,20 @@ typedef float btScalar;
#endif
#define BT_DECLARE_ALIGNED_ALLOCATOR() \
SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \
SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \
SIMD_FORCE_INLINE void operator delete(void*, void*) {} \
SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \
SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \
SIMD_FORCE_INLINE void operator delete[](void*, void*) {}
SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \
SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \
SIMD_FORCE_INLINE void operator delete(void*, void*) {} \
SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \
SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \
SIMD_FORCE_INLINE void operator delete[](void*, void*) {}
#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS)
SIMD_FORCE_INLINE btScalar btSqrt(btScalar x)
{
return sqrt(x);
return sqrt(x);
}
SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); }
SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); }
@@ -231,19 +232,19 @@ SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); }
SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); }
SIMD_FORCE_INLINE btScalar btAcos(btScalar x)
{
if (x < btScalar(-1))
x = btScalar(-1);
if (x > btScalar(1))
x = btScalar(1);
return acos(x);
if (x < btScalar(-1))
x = btScalar(-1);
if (x > btScalar(1))
x = btScalar(1);
return acos(x);
}
SIMD_FORCE_INLINE btScalar btAsin(btScalar x)
{
if (x < btScalar(-1))
x = btScalar(-1);
if (x > btScalar(1))
x = btScalar(1);
return asin(x);
if (x < btScalar(-1))
x = btScalar(-1);
if (x > btScalar(1))
x = btScalar(1);
return asin(x);
}
SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); }
SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); }
@@ -257,21 +258,21 @@ SIMD_FORCE_INLINE btScalar btFmod(btScalar x, btScalar y) { return fmod(x, y); }
SIMD_FORCE_INLINE btScalar btSqrt(btScalar y)
{
#ifdef USE_APPROXIMATION
double x, z, tempf;
unsigned long* tfptr = ((unsigned long*)&tempf) + 1;
double x, z, tempf;
unsigned long* tfptr = ((unsigned long*)&tempf) + 1;
tempf = y;
*tfptr = (0xbfcdd90a - *tfptr) >> 1; /* estimate of 1/sqrt(y) */
x = tempf;
z = y * btScalar(0.5);
x = (btScalar(1.5) * x) - (x * x) * (x * z); /* iteration formula */
x = (btScalar(1.5) * x) - (x * x) * (x * z);
x = (btScalar(1.5) * x) - (x * x) * (x * z);
x = (btScalar(1.5) * x) - (x * x) * (x * z);
x = (btScalar(1.5) * x) - (x * x) * (x * z);
return x * y;
tempf = y;
*tfptr = (0xbfcdd90a - *tfptr) >> 1; /* estimate of 1/sqrt(y) */
x = tempf;
z = y * btScalar(0.5);
x = (btScalar(1.5) * x) - (x * x) * (x * z); /* iteration formula */
x = (btScalar(1.5) * x) - (x * x) * (x * z);
x = (btScalar(1.5) * x) - (x * x) * (x * z);
x = (btScalar(1.5) * x) - (x * x) * (x * z);
x = (btScalar(1.5) * x) - (x * x) * (x * z);
return x * y;
#else
return sqrtf(y);
return sqrtf(y);
#endif
}
SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); }
@@ -280,19 +281,19 @@ SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); }
SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); }
SIMD_FORCE_INLINE btScalar btAcos(btScalar x)
{
if (x < btScalar(-1))
x = btScalar(-1);
if (x > btScalar(1))
x = btScalar(1);
return acosf(x);
if (x < btScalar(-1))
x = btScalar(-1);
if (x > btScalar(1))
x = btScalar(1);
return acosf(x);
}
SIMD_FORCE_INLINE btScalar btAsin(btScalar x)
{
if (x < btScalar(-1))
x = btScalar(-1);
if (x > btScalar(1))
x = btScalar(1);
return asinf(x);
if (x < btScalar(-1))
x = btScalar(-1);
if (x > btScalar(1))
x = btScalar(1);
return asinf(x);
}
SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); }
SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); }
@@ -322,117 +323,120 @@ SIMD_FORCE_INLINE btScalar btFmod(btScalar x, btScalar y) { return fmodf(x, y);
SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x)
{
btScalar coeff_1 = SIMD_PI / 4.0f;
btScalar coeff_2 = 3.0f * coeff_1;
btScalar abs_y = btFabs(y);
btScalar angle;
if (x >= 0.0f) {
btScalar r = (x - abs_y) / (x + abs_y);
angle = coeff_1 - coeff_1 * r;
}
else {
btScalar r = (x + abs_y) / (abs_y - x);
angle = coeff_2 - coeff_1 * r;
}
return (y < 0.0f) ? -angle : angle;
btScalar coeff_1 = SIMD_PI / 4.0f;
btScalar coeff_2 = 3.0f * coeff_1;
btScalar abs_y = btFabs(y);
btScalar angle;
if (x >= 0.0f)
{
btScalar r = (x - abs_y) / (x + abs_y);
angle = coeff_1 - coeff_1 * r;
}
else
{
btScalar r = (x + abs_y) / (abs_y - x);
angle = coeff_2 - coeff_1 * r;
}
return (y < 0.0f) ? -angle : angle;
}
SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; }
SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps)
{
return (((a) <= eps) && !((a) < -eps));
return (((a) <= eps) && !((a) < -eps));
}
SIMD_FORCE_INLINE bool btGreaterEqual(btScalar a, btScalar eps)
{
return (!((a) <= eps));
return (!((a) <= eps));
}
SIMD_FORCE_INLINE int btIsNegative(btScalar x)
{
return x < btScalar(0.0) ? 1 : 0;
return x < btScalar(0.0) ? 1 : 0;
}
SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; }
SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; }
#define BT_DECLARE_HANDLE(name) \
typedef struct name##__ { \
int unused; \
} * name
typedef struct name##__ \
{ \
int unused; \
} * name
#ifndef btFsel
SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c)
{
return a >= 0 ? b : c;
return a >= 0 ? b : c;
}
#endif
#define btFsels(a, b, c) (btScalar) btFsel(a, b, c)
SIMD_FORCE_INLINE bool btMachineIsLittleEndian()
{
long int i = 1;
const char* p = (const char*)&i;
if (p[0] == 1) // Lowest address contains the least significant byte
return true;
else
return false;
long int i = 1;
const char* p = (const char*)&i;
if (p[0] == 1) // Lowest address contains the least significant byte
return true;
else
return false;
}
///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360
///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html
SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero)
{
// Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
// Rely on positive value or'ed with its negative having sign bit on
// and zero value or'ed with its negative (which is still zero) having sign bit off
// Use arithmetic shift right, shifting the sign bit through all 32 bits
unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
unsigned testEqz = ~testNz;
return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
// Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
// Rely on positive value or'ed with its negative having sign bit on
// and zero value or'ed with its negative (which is still zero) having sign bit off
// Use arithmetic shift right, shifting the sign bit through all 32 bits
unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
unsigned testEqz = ~testNz;
return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
}
SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero)
{
unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
unsigned testEqz = ~testNz;
return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
unsigned testEqz = ~testNz;
return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
}
SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
{
#ifdef BT_HAVE_NATIVE_FSEL
return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
#else
return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero;
return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero;
#endif
}
template <typename T>
SIMD_FORCE_INLINE void btSwap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
T tmp = a;
a = b;
b = tmp;
}
//PCK: endian swapping functions
SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val)
{
return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
}
SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val)
{
return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
}
SIMD_FORCE_INLINE unsigned btSwapEndian(int val)
{
return btSwapEndian((unsigned)val);
return btSwapEndian((unsigned)val);
}
SIMD_FORCE_INLINE unsigned short btSwapEndian(short val)
{
return btSwapEndian((unsigned short)val);
return btSwapEndian((unsigned short)val);
}
///btSwapFloat uses using char pointers to swap the endianness
@@ -443,90 +447,94 @@ SIMD_FORCE_INLINE unsigned short btSwapEndian(short val)
///so instead of returning a float/double, we return integer/long long integer
SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d)
{
unsigned int a = 0;
unsigned char* dst = (unsigned char*)&a;
unsigned char* src = (unsigned char*)&d;
unsigned int a = 0;
unsigned char* dst = (unsigned char*)&a;
unsigned char* src = (unsigned char*)&d;
dst[0] = src[3];
dst[1] = src[2];
dst[2] = src[1];
dst[3] = src[0];
return a;
dst[0] = src[3];
dst[1] = src[2];
dst[2] = src[1];
dst[3] = src[0];
return a;
}
// unswap using char pointers
SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a)
{
float d = 0.0f;
unsigned char* src = (unsigned char*)&a;
unsigned char* dst = (unsigned char*)&d;
float d = 0.0f;
unsigned char* src = (unsigned char*)&a;
unsigned char* dst = (unsigned char*)&d;
dst[0] = src[3];
dst[1] = src[2];
dst[2] = src[1];
dst[3] = src[0];
dst[0] = src[3];
dst[1] = src[2];
dst[2] = src[1];
dst[3] = src[0];
return d;
return d;
}
// swap using char pointers
SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst)
{
unsigned char* src = (unsigned char*)&d;
unsigned char* src = (unsigned char*)&d;
dst[0] = src[7];
dst[1] = src[6];
dst[2] = src[5];
dst[3] = src[4];
dst[4] = src[3];
dst[5] = src[2];
dst[6] = src[1];
dst[7] = src[0];
dst[0] = src[7];
dst[1] = src[6];
dst[2] = src[5];
dst[3] = src[4];
dst[4] = src[3];
dst[5] = src[2];
dst[6] = src[1];
dst[7] = src[0];
}
// unswap using char pointers
SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char* src)
{
double d = 0.0;
unsigned char* dst = (unsigned char*)&d;
double d = 0.0;
unsigned char* dst = (unsigned char*)&d;
dst[0] = src[7];
dst[1] = src[6];
dst[2] = src[5];
dst[3] = src[4];
dst[4] = src[3];
dst[5] = src[2];
dst[6] = src[1];
dst[7] = src[0];
dst[0] = src[7];
dst[1] = src[6];
dst[2] = src[5];
dst[3] = src[4];
dst[4] = src[3];
dst[5] = src[2];
dst[6] = src[1];
dst[7] = src[0];
return d;
return d;
}
// returns normalized value in range [-SIMD_PI, SIMD_PI]
SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians)
{
angleInRadians = btFmod(angleInRadians, SIMD_2_PI);
if (angleInRadians < -SIMD_PI) {
return angleInRadians + SIMD_2_PI;
}
else if (angleInRadians > SIMD_PI) {
return angleInRadians - SIMD_2_PI;
}
else {
return angleInRadians;
}
angleInRadians = btFmod(angleInRadians, SIMD_2_PI);
if (angleInRadians < -SIMD_PI)
{
return angleInRadians + SIMD_2_PI;
}
else if (angleInRadians > SIMD_PI)
{
return angleInRadians - SIMD_2_PI;
}
else
{
return angleInRadians;
}
}
///rudimentary class to provide type info
struct btTypedObject {
btTypedObject(int objectType)
: m_objectType(objectType)
{
}
int m_objectType;
inline int getObjectType() const
{
return m_objectType;
}
struct btTypedObject
{
btTypedObject(int objectType)
: m_objectType(objectType)
{
}
int m_objectType;
inline int getObjectType() const
{
return m_objectType;
}
};
#endif //BT_SCALAR_H
#endif //BT_SCALAR_H

File diff suppressed because it is too large Load Diff

View File

@@ -16,64 +16,69 @@
#ifndef VHACD_CIRCULAR_LIST_H
#define VHACD_CIRCULAR_LIST_H
#include <stdlib.h>
namespace VHACD {
namespace VHACD
{
//! CircularListElement class.
template <typename T>
class CircularListElement {
class CircularListElement
{
public:
T& GetData() { return m_data; }
const T& GetData() const { return m_data; }
CircularListElement<T>*& GetNext() { return m_next; }
CircularListElement<T>*& GetPrev() { return m_prev; }
const CircularListElement<T>*& GetNext() const { return m_next; }
const CircularListElement<T>*& GetPrev() const { return m_prev; }
//! Constructor
CircularListElement(const T& data) { m_data = data; }
CircularListElement(void) {}
//! Destructor
~CircularListElement(void) {}
private:
T m_data;
CircularListElement<T>* m_next;
CircularListElement<T>* m_prev;
T& GetData() { return m_data; }
const T& GetData() const { return m_data; }
CircularListElement<T>*& GetNext() { return m_next; }
CircularListElement<T>*& GetPrev() { return m_prev; }
const CircularListElement<T>*& GetNext() const { return m_next; }
const CircularListElement<T>*& GetPrev() const { return m_prev; }
//! Constructor
CircularListElement(const T& data) { m_data = data; }
CircularListElement(void) {}
//! Destructor
~CircularListElement(void) {}
CircularListElement(const CircularListElement& rhs);
private:
T m_data;
CircularListElement<T>* m_next;
CircularListElement<T>* m_prev;
CircularListElement(const CircularListElement& rhs);
};
//! CircularList class.
template <typename T>
class CircularList {
class CircularList
{
public:
CircularListElement<T>*& GetHead() { return m_head; }
const CircularListElement<T>* GetHead() const { return m_head; }
bool IsEmpty() const { return (m_size == 0); }
size_t GetSize() const { return m_size; }
const T& GetData() const { return m_head->GetData(); }
T& GetData() { return m_head->GetData(); }
bool Delete();
bool Delete(CircularListElement<T>* element);
CircularListElement<T>* Add(const T* data = 0);
CircularListElement<T>* Add(const T& data);
bool Next();
bool Prev();
void Clear()
{
while (Delete())
;
};
const CircularList& operator=(const CircularList& rhs);
//! Constructor
CircularList()
{
m_head = 0;
m_size = 0;
}
CircularList(const CircularList& rhs);
//! Destructor
~CircularList(void) { Clear(); };
CircularListElement<T>*& GetHead() { return m_head; }
const CircularListElement<T>* GetHead() const { return m_head; }
bool IsEmpty() const { return (m_size == 0); }
size_t GetSize() const { return m_size; }
const T& GetData() const { return m_head->GetData(); }
T& GetData() { return m_head->GetData(); }
bool Delete();
bool Delete(CircularListElement<T>* element);
CircularListElement<T>* Add(const T* data = 0);
CircularListElement<T>* Add(const T& data);
bool Next();
bool Prev();
void Clear()
{
while (Delete())
;
};
const CircularList& operator=(const CircularList& rhs);
//! Constructor
CircularList()
{
m_head = 0;
m_size = 0;
}
CircularList(const CircularList& rhs);
//! Destructor
~CircularList(void) { Clear(); };
private:
CircularListElement<T>* m_head; //!< a pointer to the head of the circular list
size_t m_size; //!< number of element in the circular list
CircularListElement<T>* m_head; //!< a pointer to the head of the circular list
size_t m_size; //!< number of element in the circular list
};
}
} // namespace VHACD
#include "vhacdCircularList.inl"
#endif // VHACD_CIRCULAR_LIST_H
#endif // VHACD_CIRCULAR_LIST_H

View File

@@ -18,81 +18,84 @@
#include "vhacdManifoldMesh.h"
#include "vhacdVector.h"
namespace VHACD {
namespace VHACD
{
//! Incremental Convex Hull algorithm (cf. http://cs.smith.edu/~orourke/books/ftp.html ).
enum ICHullError {
ICHullErrorOK = 0,
ICHullErrorCoplanarPoints,
ICHullErrorNoVolume,
ICHullErrorInconsistent,
ICHullErrorNotEnoughPoints
enum ICHullError
{
ICHullErrorOK = 0,
ICHullErrorCoplanarPoints,
ICHullErrorNoVolume,
ICHullErrorInconsistent,
ICHullErrorNotEnoughPoints
};
class ICHull {
class ICHull
{
public:
static const double sc_eps;
//!
bool IsFlat() { return m_isFlat; }
//! Returns the computed mesh
TMMesh& GetMesh() { return m_mesh; }
//! Add one point to the convex-hull
bool AddPoint(const Vec3<double>& point) { return AddPoints(&point, 1); }
//! Add one point to the convex-hull
bool AddPoint(const Vec3<double>& point, int id);
//! Add points to the convex-hull
bool AddPoints(const Vec3<double>* points, size_t nPoints);
//!
ICHullError Process();
//!
ICHullError Process(const unsigned int nPointsCH, const double minVolume = 0.0);
//!
bool IsInside(const Vec3<double>& pt0, const double eps = 0.0);
//!
const ICHull& operator=(ICHull& rhs);
static const double sc_eps;
//!
bool IsFlat() { return m_isFlat; }
//! Returns the computed mesh
TMMesh& GetMesh() { return m_mesh; }
//! Add one point to the convex-hull
bool AddPoint(const Vec3<double>& point) { return AddPoints(&point, 1); }
//! Add one point to the convex-hull
bool AddPoint(const Vec3<double>& point, int id);
//! Add points to the convex-hull
bool AddPoints(const Vec3<double>* points, size_t nPoints);
//!
ICHullError Process();
//!
ICHullError Process(const unsigned int nPointsCH, const double minVolume = 0.0);
//!
bool IsInside(const Vec3<double>& pt0, const double eps = 0.0);
//!
const ICHull& operator=(ICHull& rhs);
//! Constructor
ICHull();
//! Destructor
~ICHull(void){};
//! Constructor
ICHull();
//! Destructor
~ICHull(void){};
private:
//! DoubleTriangle builds the initial double triangle. It first finds 3 noncollinear points and makes two faces out of them, in opposite order. It then finds a fourth point that is not coplanar with that face. The vertices are stored in the face structure in counterclockwise order so that the volume between the face and the point is negative. Lastly, the 3 newfaces to the fourth point are constructed and the data structures are cleaned up.
ICHullError DoubleTriangle();
//! MakeFace creates a new face structure from three vertices (in ccw order). It returns a pointer to the face.
CircularListElement<TMMTriangle>* MakeFace(CircularListElement<TMMVertex>* v0,
CircularListElement<TMMVertex>* v1,
CircularListElement<TMMVertex>* v2,
CircularListElement<TMMTriangle>* fold);
//!
CircularListElement<TMMTriangle>* MakeConeFace(CircularListElement<TMMEdge>* e, CircularListElement<TMMVertex>* v);
//!
bool ProcessPoint();
//!
bool ComputePointVolume(double& totalVolume, bool markVisibleFaces);
//!
bool FindMaxVolumePoint(const double minVolume = 0.0);
//!
bool CleanEdges();
//!
bool CleanVertices(unsigned int& addedPoints);
//!
bool CleanTriangles();
//!
bool CleanUp(unsigned int& addedPoints);
//!
bool MakeCCW(CircularListElement<TMMTriangle>* f,
CircularListElement<TMMEdge>* e,
CircularListElement<TMMVertex>* v);
void Clear();
//! DoubleTriangle builds the initial double triangle. It first finds 3 noncollinear points and makes two faces out of them, in opposite order. It then finds a fourth point that is not coplanar with that face. The vertices are stored in the face structure in counterclockwise order so that the volume between the face and the point is negative. Lastly, the 3 newfaces to the fourth point are constructed and the data structures are cleaned up.
ICHullError DoubleTriangle();
//! MakeFace creates a new face structure from three vertices (in ccw order). It returns a pointer to the face.
CircularListElement<TMMTriangle>* MakeFace(CircularListElement<TMMVertex>* v0,
CircularListElement<TMMVertex>* v1,
CircularListElement<TMMVertex>* v2,
CircularListElement<TMMTriangle>* fold);
//!
CircularListElement<TMMTriangle>* MakeConeFace(CircularListElement<TMMEdge>* e, CircularListElement<TMMVertex>* v);
//!
bool ProcessPoint();
//!
bool ComputePointVolume(double& totalVolume, bool markVisibleFaces);
//!
bool FindMaxVolumePoint(const double minVolume = 0.0);
//!
bool CleanEdges();
//!
bool CleanVertices(unsigned int& addedPoints);
//!
bool CleanTriangles();
//!
bool CleanUp(unsigned int& addedPoints);
//!
bool MakeCCW(CircularListElement<TMMTriangle>* f,
CircularListElement<TMMEdge>* e,
CircularListElement<TMMVertex>* v);
void Clear();
private:
static const int sc_dummyIndex;
TMMesh m_mesh;
SArray<CircularListElement<TMMEdge>*> m_edgesToDelete;
SArray<CircularListElement<TMMEdge>*> m_edgesToUpdate;
SArray<CircularListElement<TMMTriangle>*> m_trianglesToDelete;
Vec3<double> m_normal;
bool m_isFlat;
ICHull(const ICHull& rhs);
static const int sc_dummyIndex;
TMMesh m_mesh;
SArray<CircularListElement<TMMEdge>*> m_edgesToDelete;
SArray<CircularListElement<TMMEdge>*> m_edgesToUpdate;
SArray<CircularListElement<TMMTriangle>*> m_trianglesToDelete;
Vec3<double> m_normal;
bool m_isFlat;
ICHull(const ICHull& rhs);
};
}
#endif // VHACD_ICHULL_H
} // namespace VHACD
#endif // VHACD_ICHULL_H

View File

@@ -18,125 +18,130 @@ All rights reserved.
#include "vhacdCircularList.h"
#include "vhacdSArray.h"
#include "vhacdVector.h"
namespace VHACD {
namespace VHACD
{
class TMMTriangle;
class TMMEdge;
class TMMesh;
class ICHull;
//! Vertex data structure used in a triangular manifold mesh (TMM).
class TMMVertex {
class TMMVertex
{
public:
void Initialize();
TMMVertex(void);
~TMMVertex(void);
void Initialize();
TMMVertex(void);
~TMMVertex(void);
private:
Vec3<double> m_pos;
int m_name;
size_t m_id;
CircularListElement<TMMEdge>* m_duplicate; // pointer to incident cone edge (or NULL)
bool m_onHull;
bool m_tag;
TMMVertex(const TMMVertex& rhs);
friend class ICHull;
friend class TMMesh;
friend class TMMTriangle;
friend class TMMEdge;
Vec3<double> m_pos;
int m_name;
size_t m_id;
CircularListElement<TMMEdge>* m_duplicate; // pointer to incident cone edge (or NULL)
bool m_onHull;
bool m_tag;
TMMVertex(const TMMVertex& rhs);
friend class ICHull;
friend class TMMesh;
friend class TMMTriangle;
friend class TMMEdge;
};
//! Edge data structure used in a triangular manifold mesh (TMM).
class TMMEdge {
class TMMEdge
{
public:
void Initialize();
TMMEdge(void);
~TMMEdge(void);
void Initialize();
TMMEdge(void);
~TMMEdge(void);
private:
size_t m_id;
CircularListElement<TMMTriangle>* m_triangles[2];
CircularListElement<TMMVertex>* m_vertices[2];
CircularListElement<TMMTriangle>* m_newFace;
TMMEdge(const TMMEdge& rhs);
friend class ICHull;
friend class TMMTriangle;
friend class TMMVertex;
friend class TMMesh;
size_t m_id;
CircularListElement<TMMTriangle>* m_triangles[2];
CircularListElement<TMMVertex>* m_vertices[2];
CircularListElement<TMMTriangle>* m_newFace;
TMMEdge(const TMMEdge& rhs);
friend class ICHull;
friend class TMMTriangle;
friend class TMMVertex;
friend class TMMesh;
};
//! Triangle data structure used in a triangular manifold mesh (TMM).
class TMMTriangle {
class TMMTriangle
{
public:
void Initialize();
TMMTriangle(void);
~TMMTriangle(void);
void Initialize();
TMMTriangle(void);
~TMMTriangle(void);
private:
size_t m_id;
CircularListElement<TMMEdge>* m_edges[3];
CircularListElement<TMMVertex>* m_vertices[3];
bool m_visible;
size_t m_id;
CircularListElement<TMMEdge>* m_edges[3];
CircularListElement<TMMVertex>* m_vertices[3];
bool m_visible;
TMMTriangle(const TMMTriangle& rhs);
friend class ICHull;
friend class TMMesh;
friend class TMMVertex;
friend class TMMEdge;
TMMTriangle(const TMMTriangle& rhs);
friend class ICHull;
friend class TMMesh;
friend class TMMVertex;
friend class TMMEdge;
};
//! triangular manifold mesh data structure.
class TMMesh {
class TMMesh
{
public:
//! Returns the number of vertices>
inline size_t GetNVertices() const { return m_vertices.GetSize(); }
//! Returns the number of edges
inline size_t GetNEdges() const { return m_edges.GetSize(); }
//! Returns the number of triangles
inline size_t GetNTriangles() const { return m_triangles.GetSize(); }
//! Returns the vertices circular list
inline const CircularList<TMMVertex>& GetVertices() const { return m_vertices; }
//! Returns the edges circular list
inline const CircularList<TMMEdge>& GetEdges() const { return m_edges; }
//! Returns the triangles circular list
inline const CircularList<TMMTriangle>& GetTriangles() const { return m_triangles; }
//! Returns the vertices circular list
inline CircularList<TMMVertex>& GetVertices() { return m_vertices; }
//! Returns the edges circular list
inline CircularList<TMMEdge>& GetEdges() { return m_edges; }
//! Returns the triangles circular list
inline CircularList<TMMTriangle>& GetTriangles() { return m_triangles; }
//! Add vertex to the mesh
CircularListElement<TMMVertex>* AddVertex() { return m_vertices.Add(); }
//! Add vertex to the mesh
CircularListElement<TMMEdge>* AddEdge() { return m_edges.Add(); }
//! Add vertex to the mesh
CircularListElement<TMMTriangle>* AddTriangle() { return m_triangles.Add(); }
//! Print mesh information
void Print();
//!
void GetIFS(Vec3<double>* const points, Vec3<int>* const triangles);
//!
void Clear();
//!
void Copy(TMMesh& mesh);
//!
bool CheckConsistancy();
//!
bool Normalize();
//!
bool Denormalize();
//! Constructor
TMMesh();
//! Destructor
virtual ~TMMesh(void);
//! Returns the number of vertices>
inline size_t GetNVertices() const { return m_vertices.GetSize(); }
//! Returns the number of edges
inline size_t GetNEdges() const { return m_edges.GetSize(); }
//! Returns the number of triangles
inline size_t GetNTriangles() const { return m_triangles.GetSize(); }
//! Returns the vertices circular list
inline const CircularList<TMMVertex>& GetVertices() const { return m_vertices; }
//! Returns the edges circular list
inline const CircularList<TMMEdge>& GetEdges() const { return m_edges; }
//! Returns the triangles circular list
inline const CircularList<TMMTriangle>& GetTriangles() const { return m_triangles; }
//! Returns the vertices circular list
inline CircularList<TMMVertex>& GetVertices() { return m_vertices; }
//! Returns the edges circular list
inline CircularList<TMMEdge>& GetEdges() { return m_edges; }
//! Returns the triangles circular list
inline CircularList<TMMTriangle>& GetTriangles() { return m_triangles; }
//! Add vertex to the mesh
CircularListElement<TMMVertex>* AddVertex() { return m_vertices.Add(); }
//! Add vertex to the mesh
CircularListElement<TMMEdge>* AddEdge() { return m_edges.Add(); }
//! Add vertex to the mesh
CircularListElement<TMMTriangle>* AddTriangle() { return m_triangles.Add(); }
//! Print mesh information
void Print();
//!
void GetIFS(Vec3<double>* const points, Vec3<int>* const triangles);
//!
void Clear();
//!
void Copy(TMMesh& mesh);
//!
bool CheckConsistancy();
//!
bool Normalize();
//!
bool Denormalize();
//! Constructor
TMMesh();
//! Destructor
virtual ~TMMesh(void);
private:
CircularList<TMMVertex> m_vertices;
CircularList<TMMEdge> m_edges;
CircularList<TMMTriangle> m_triangles;
CircularList<TMMVertex> m_vertices;
CircularList<TMMEdge> m_edges;
CircularList<TMMTriangle> m_triangles;
// not defined
TMMesh(const TMMesh& rhs);
friend class ICHull;
// not defined
TMMesh(const TMMesh& rhs);
friend class ICHull;
};
}
#endif // VHACD_MANIFOLD_MESH_H
} // namespace VHACD
#endif // VHACD_MANIFOLD_MESH_H

View File

@@ -20,110 +20,114 @@
#define VHACD_DEBUG_MESH
namespace VHACD {
enum AXIS {
AXIS_X = 0,
AXIS_Y = 1,
AXIS_Z = 2
namespace VHACD
{
enum AXIS
{
AXIS_X = 0,
AXIS_Y = 1,
AXIS_Z = 2
};
struct Plane {
double m_a;
double m_b;
double m_c;
double m_d;
AXIS m_axis;
short m_index;
struct Plane
{
double m_a;
double m_b;
double m_c;
double m_d;
AXIS m_axis;
short m_index;
};
#ifdef VHACD_DEBUG_MESH
struct Material {
Vec3<double> m_diffuseColor;
double m_ambientIntensity;
Vec3<double> m_specularColor;
Vec3<double> m_emissiveColor;
double m_shininess;
double m_transparency;
Material(void)
{
m_diffuseColor.X() = 0.5;
m_diffuseColor.Y() = 0.5;
m_diffuseColor.Z() = 0.5;
m_specularColor.X() = 0.5;
m_specularColor.Y() = 0.5;
m_specularColor.Z() = 0.5;
m_ambientIntensity = 0.4;
m_emissiveColor.X() = 0.0;
m_emissiveColor.Y() = 0.0;
m_emissiveColor.Z() = 0.0;
m_shininess = 0.4;
m_transparency = 0.0;
};
struct Material
{
Vec3<double> m_diffuseColor;
double m_ambientIntensity;
Vec3<double> m_specularColor;
Vec3<double> m_emissiveColor;
double m_shininess;
double m_transparency;
Material(void)
{
m_diffuseColor.X() = 0.5;
m_diffuseColor.Y() = 0.5;
m_diffuseColor.Z() = 0.5;
m_specularColor.X() = 0.5;
m_specularColor.Y() = 0.5;
m_specularColor.Z() = 0.5;
m_ambientIntensity = 0.4;
m_emissiveColor.X() = 0.0;
m_emissiveColor.Y() = 0.0;
m_emissiveColor.Z() = 0.0;
m_shininess = 0.4;
m_transparency = 0.0;
};
};
#endif // VHACD_DEBUG_MESH
#endif // VHACD_DEBUG_MESH
//! Triangular mesh data structure
class Mesh {
class Mesh
{
public:
void AddPoint(const Vec3<double>& pt) { m_points.PushBack(pt); };
void SetPoint(size_t index, const Vec3<double>& pt) { m_points[index] = pt; };
const Vec3<double>& GetPoint(size_t index) const { return m_points[index]; };
Vec3<double>& GetPoint(size_t index) { return m_points[index]; };
size_t GetNPoints() const { return m_points.Size(); };
double* GetPoints() { return (double*)m_points.Data(); } // ugly
const double* const GetPoints() const { return (double*)m_points.Data(); } // ugly
const Vec3<double>* const GetPointsBuffer() const { return m_points.Data(); } //
Vec3<double>* const GetPointsBuffer() { return m_points.Data(); } //
void AddTriangle(const Vec3<int>& tri) { m_triangles.PushBack(tri); };
void SetTriangle(size_t index, const Vec3<int>& tri) { m_triangles[index] = tri; };
const Vec3<int>& GetTriangle(size_t index) const { return m_triangles[index]; };
Vec3<int>& GetTriangle(size_t index) { return m_triangles[index]; };
size_t GetNTriangles() const { return m_triangles.Size(); };
int* GetTriangles() { return (int*)m_triangles.Data(); } // ugly
const int* const GetTriangles() const { return (int*)m_triangles.Data(); } // ugly
const Vec3<int>* const GetTrianglesBuffer() const { return m_triangles.Data(); }
Vec3<int>* const GetTrianglesBuffer() { return m_triangles.Data(); }
const Vec3<double>& GetCenter() const { return m_center; }
const Vec3<double>& GetMinBB() const { return m_minBB; }
const Vec3<double>& GetMaxBB() const { return m_maxBB; }
void ClearPoints() { m_points.Clear(); }
void ClearTriangles() { m_triangles.Clear(); }
void Clear()
{
ClearPoints();
ClearTriangles();
}
void ResizePoints(size_t nPts) { m_points.Resize(nPts); }
void ResizeTriangles(size_t nTri) { m_triangles.Resize(nTri); }
void CopyPoints(SArray<Vec3<double> >& points) const { points = m_points; }
double GetDiagBB() const { return m_diag; }
double ComputeVolume() const;
void ComputeConvexHull(const double* const pts,
const size_t nPts);
void Clip(const Plane& plane,
SArray<Vec3<double> >& positivePart,
SArray<Vec3<double> >& negativePart) const;
bool IsInside(const Vec3<double>& pt) const;
double ComputeDiagBB();
void AddPoint(const Vec3<double>& pt) { m_points.PushBack(pt); };
void SetPoint(size_t index, const Vec3<double>& pt) { m_points[index] = pt; };
const Vec3<double>& GetPoint(size_t index) const { return m_points[index]; };
Vec3<double>& GetPoint(size_t index) { return m_points[index]; };
size_t GetNPoints() const { return m_points.Size(); };
double* GetPoints() { return (double*)m_points.Data(); } // ugly
const double* const GetPoints() const { return (double*)m_points.Data(); } // ugly
const Vec3<double>* const GetPointsBuffer() const { return m_points.Data(); } //
Vec3<double>* const GetPointsBuffer() { return m_points.Data(); } //
void AddTriangle(const Vec3<int>& tri) { m_triangles.PushBack(tri); };
void SetTriangle(size_t index, const Vec3<int>& tri) { m_triangles[index] = tri; };
const Vec3<int>& GetTriangle(size_t index) const { return m_triangles[index]; };
Vec3<int>& GetTriangle(size_t index) { return m_triangles[index]; };
size_t GetNTriangles() const { return m_triangles.Size(); };
int* GetTriangles() { return (int*)m_triangles.Data(); } // ugly
const int* const GetTriangles() const { return (int*)m_triangles.Data(); } // ugly
const Vec3<int>* const GetTrianglesBuffer() const { return m_triangles.Data(); }
Vec3<int>* const GetTrianglesBuffer() { return m_triangles.Data(); }
const Vec3<double>& GetCenter() const { return m_center; }
const Vec3<double>& GetMinBB() const { return m_minBB; }
const Vec3<double>& GetMaxBB() const { return m_maxBB; }
void ClearPoints() { m_points.Clear(); }
void ClearTriangles() { m_triangles.Clear(); }
void Clear()
{
ClearPoints();
ClearTriangles();
}
void ResizePoints(size_t nPts) { m_points.Resize(nPts); }
void ResizeTriangles(size_t nTri) { m_triangles.Resize(nTri); }
void CopyPoints(SArray<Vec3<double> >& points) const { points = m_points; }
double GetDiagBB() const { return m_diag; }
double ComputeVolume() const;
void ComputeConvexHull(const double* const pts,
const size_t nPts);
void Clip(const Plane& plane,
SArray<Vec3<double> >& positivePart,
SArray<Vec3<double> >& negativePart) const;
bool IsInside(const Vec3<double>& pt) const;
double ComputeDiagBB();
#ifdef VHACD_DEBUG_MESH
bool LoadOFF(const std::string& fileName, bool invert);
bool SaveVRML2(const std::string& fileName) const;
bool SaveVRML2(std::ofstream& fout, const Material& material) const;
bool SaveOFF(const std::string& fileName) const;
#endif // VHACD_DEBUG_MESH
bool LoadOFF(const std::string& fileName, bool invert);
bool SaveVRML2(const std::string& fileName) const;
bool SaveVRML2(std::ofstream& fout, const Material& material) const;
bool SaveOFF(const std::string& fileName) const;
#endif // VHACD_DEBUG_MESH
//! Constructor.
Mesh();
//! Destructor.
~Mesh(void);
//! Constructor.
Mesh();
//! Destructor.
~Mesh(void);
private:
SArray<Vec3<double> > m_points;
SArray<Vec3<int> > m_triangles;
Vec3<double> m_minBB;
Vec3<double> m_maxBB;
Vec3<double> m_center;
double m_diag;
SArray<Vec3<double> > m_points;
SArray<Vec3<int> > m_triangles;
Vec3<double> m_minBB;
Vec3<double> m_maxBB;
Vec3<double> m_center;
double m_diag;
};
}
} // namespace VHACD
#endif

View File

@@ -82,65 +82,67 @@
#define VHACD_VERIFY(x) assert((x))
#endif
namespace VHACD {
class Mutex {
namespace VHACD
{
class Mutex
{
public:
Mutex(void)
{
Mutex(void)
{
#if defined(WIN32) || defined(_XBOX)
InitializeCriticalSection(&m_mutex);
InitializeCriticalSection(&m_mutex);
#elif defined(__APPLE__) || defined(__linux__)
pthread_mutexattr_t mutexAttr; // Mutex Attribute
VHACD_VERIFY(pthread_mutexattr_init(&mutexAttr) == 0);
VHACD_VERIFY(pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_RECURSIVE_NP) == 0);
VHACD_VERIFY(pthread_mutex_init(&m_mutex, &mutexAttr) == 0);
VHACD_VERIFY(pthread_mutexattr_destroy(&mutexAttr) == 0);
pthread_mutexattr_t mutexAttr; // Mutex Attribute
VHACD_VERIFY(pthread_mutexattr_init(&mutexAttr) == 0);
VHACD_VERIFY(pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_RECURSIVE_NP) == 0);
VHACD_VERIFY(pthread_mutex_init(&m_mutex, &mutexAttr) == 0);
VHACD_VERIFY(pthread_mutexattr_destroy(&mutexAttr) == 0);
#endif
}
~Mutex(void)
{
}
~Mutex(void)
{
#if defined(WIN32) || defined(_XBOX)
DeleteCriticalSection(&m_mutex);
DeleteCriticalSection(&m_mutex);
#elif defined(__APPLE__) || defined(__linux__)
VHACD_VERIFY(pthread_mutex_destroy(&m_mutex) == 0);
VHACD_VERIFY(pthread_mutex_destroy(&m_mutex) == 0);
#endif
}
void Lock(void)
{
}
void Lock(void)
{
#if defined(WIN32) || defined(_XBOX)
EnterCriticalSection(&m_mutex);
EnterCriticalSection(&m_mutex);
#elif defined(__APPLE__) || defined(__linux__)
VHACD_VERIFY(pthread_mutex_lock(&m_mutex) == 0);
VHACD_VERIFY(pthread_mutex_lock(&m_mutex) == 0);
#endif
}
bool TryLock(void)
{
}
bool TryLock(void)
{
#if defined(WIN32) || defined(_XBOX)
bool bRet = false;
//assert(("TryEnterCriticalSection seems to not work on XP???", 0));
bRet = TryEnterCriticalSection(&m_mutex) ? true : false;
return bRet;
bool bRet = false;
//assert(("TryEnterCriticalSection seems to not work on XP???", 0));
bRet = TryEnterCriticalSection(&m_mutex) ? true : false;
return bRet;
#elif defined(__APPLE__) || defined(__linux__)
int result = pthread_mutex_trylock(&m_mutex);
return (result == 0);
int result = pthread_mutex_trylock(&m_mutex);
return (result == 0);
#endif
}
}
void Unlock(void)
{
void Unlock(void)
{
#if defined(WIN32) || defined(_XBOX)
LeaveCriticalSection(&m_mutex);
LeaveCriticalSection(&m_mutex);
#elif defined(__APPLE__) || defined(__linux__)
VHACD_VERIFY(pthread_mutex_unlock(&m_mutex) == 0);
VHACD_VERIFY(pthread_mutex_unlock(&m_mutex) == 0);
#endif
}
}
private:
#if defined(WIN32) || defined(_XBOX)
CRITICAL_SECTION m_mutex;
CRITICAL_SECTION m_mutex;
#elif defined(__APPLE__) || defined(__linux__)
pthread_mutex_t m_mutex;
pthread_mutex_t m_mutex;
#endif
};
}
#endif // VHACD_MUTEX_H
} // namespace VHACD
#endif // VHACD_MUTEX_H

View File

@@ -21,138 +21,144 @@
#define SARRAY_DEFAULT_MIN_SIZE 16
namespace VHACD {
namespace VHACD
{
//! SArray.
template <typename T, size_t N = 64>
class SArray {
class SArray
{
public:
T& operator[](size_t i)
{
T* const data = Data();
return data[i];
}
const T& operator[](size_t i) const
{
const T* const data = Data();
return data[i];
}
size_t Size() const
{
return m_size;
}
T* const Data()
{
return (m_maxSize == N) ? m_data0 : m_data;
}
const T* const Data() const
{
return (m_maxSize == N) ? m_data0 : m_data;
}
void Clear()
{
m_size = 0;
delete[] m_data;
m_data = 0;
m_maxSize = N;
}
void PopBack()
{
--m_size;
}
void Allocate(size_t size)
{
if (size > m_maxSize) {
T* temp = new T[size];
memcpy(temp, Data(), m_size * sizeof(T));
delete[] m_data;
m_data = temp;
m_maxSize = size;
}
}
void Resize(size_t size)
{
Allocate(size);
m_size = size;
}
T& operator[](size_t i)
{
T* const data = Data();
return data[i];
}
const T& operator[](size_t i) const
{
const T* const data = Data();
return data[i];
}
size_t Size() const
{
return m_size;
}
T* const Data()
{
return (m_maxSize == N) ? m_data0 : m_data;
}
const T* const Data() const
{
return (m_maxSize == N) ? m_data0 : m_data;
}
void Clear()
{
m_size = 0;
delete[] m_data;
m_data = 0;
m_maxSize = N;
}
void PopBack()
{
--m_size;
}
void Allocate(size_t size)
{
if (size > m_maxSize)
{
T* temp = new T[size];
memcpy(temp, Data(), m_size * sizeof(T));
delete[] m_data;
m_data = temp;
m_maxSize = size;
}
}
void Resize(size_t size)
{
Allocate(size);
m_size = size;
}
void PushBack(const T& value)
{
if (m_size == m_maxSize) {
size_t maxSize = (m_maxSize << 1);
T* temp = new T[maxSize];
memcpy(temp, Data(), m_maxSize * sizeof(T));
delete[] m_data;
m_data = temp;
m_maxSize = maxSize;
}
T* const data = Data();
data[m_size++] = value;
}
bool Find(const T& value, size_t& pos)
{
T* const data = Data();
for (pos = 0; pos < m_size; ++pos)
if (value == data[pos])
return true;
return false;
}
bool Insert(const T& value)
{
size_t pos;
if (Find(value, pos))
return false;
PushBack(value);
return true;
}
bool Erase(const T& value)
{
size_t pos;
T* const data = Data();
if (Find(value, pos)) {
for (size_t j = pos + 1; j < m_size; ++j)
data[j - 1] = data[j];
--m_size;
return true;
}
return false;
}
void operator=(const SArray& rhs)
{
if (m_maxSize < rhs.m_size) {
delete[] m_data;
m_maxSize = rhs.m_maxSize;
m_data = new T[m_maxSize];
}
m_size = rhs.m_size;
memcpy(Data(), rhs.Data(), m_size * sizeof(T));
}
void Initialize()
{
m_data = 0;
m_size = 0;
m_maxSize = N;
}
SArray(const SArray& rhs)
{
m_data = 0;
m_size = 0;
m_maxSize = N;
*this = rhs;
}
SArray()
{
Initialize();
}
~SArray()
{
delete[] m_data;
}
void PushBack(const T& value)
{
if (m_size == m_maxSize)
{
size_t maxSize = (m_maxSize << 1);
T* temp = new T[maxSize];
memcpy(temp, Data(), m_maxSize * sizeof(T));
delete[] m_data;
m_data = temp;
m_maxSize = maxSize;
}
T* const data = Data();
data[m_size++] = value;
}
bool Find(const T& value, size_t& pos)
{
T* const data = Data();
for (pos = 0; pos < m_size; ++pos)
if (value == data[pos])
return true;
return false;
}
bool Insert(const T& value)
{
size_t pos;
if (Find(value, pos))
return false;
PushBack(value);
return true;
}
bool Erase(const T& value)
{
size_t pos;
T* const data = Data();
if (Find(value, pos))
{
for (size_t j = pos + 1; j < m_size; ++j)
data[j - 1] = data[j];
--m_size;
return true;
}
return false;
}
void operator=(const SArray& rhs)
{
if (m_maxSize < rhs.m_size)
{
delete[] m_data;
m_maxSize = rhs.m_maxSize;
m_data = new T[m_maxSize];
}
m_size = rhs.m_size;
memcpy(Data(), rhs.Data(), m_size * sizeof(T));
}
void Initialize()
{
m_data = 0;
m_size = 0;
m_maxSize = N;
}
SArray(const SArray& rhs)
{
m_data = 0;
m_size = 0;
m_maxSize = N;
*this = rhs;
}
SArray()
{
Initialize();
}
~SArray()
{
delete[] m_data;
}
private:
T m_data0[N];
T* m_data;
size_t m_size;
size_t m_maxSize;
T m_data0[N];
T* m_data;
size_t m_size;
size_t m_maxSize;
};
}
} // namespace VHACD
#endif

View File

@@ -18,7 +18,7 @@
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#endif
#include <windows.h>
#elif __MACH__
@@ -29,93 +29,97 @@
#include <time.h>
#endif
namespace VHACD {
namespace VHACD
{
#ifdef _WIN32
class Timer {
class Timer
{
public:
Timer(void)
{
m_start.QuadPart = 0;
m_stop.QuadPart = 0;
QueryPerformanceFrequency(&m_freq);
};
~Timer(void){};
void Tic()
{
QueryPerformanceCounter(&m_start);
}
void Toc()
{
QueryPerformanceCounter(&m_stop);
}
double GetElapsedTime() // in ms
{
LARGE_INTEGER delta;
delta.QuadPart = m_stop.QuadPart - m_start.QuadPart;
return (1000.0 * delta.QuadPart) / (double)m_freq.QuadPart;
}
Timer(void)
{
m_start.QuadPart = 0;
m_stop.QuadPart = 0;
QueryPerformanceFrequency(&m_freq);
};
~Timer(void){};
void Tic()
{
QueryPerformanceCounter(&m_start);
}
void Toc()
{
QueryPerformanceCounter(&m_stop);
}
double GetElapsedTime() // in ms
{
LARGE_INTEGER delta;
delta.QuadPart = m_stop.QuadPart - m_start.QuadPart;
return (1000.0 * delta.QuadPart) / (double)m_freq.QuadPart;
}
private:
LARGE_INTEGER m_start;
LARGE_INTEGER m_stop;
LARGE_INTEGER m_freq;
LARGE_INTEGER m_start;
LARGE_INTEGER m_stop;
LARGE_INTEGER m_freq;
};
#elif __MACH__
class Timer {
class Timer
{
public:
Timer(void)
{
memset(this, 0, sizeof(Timer));
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &m_cclock);
};
~Timer(void)
{
mach_port_deallocate(mach_task_self(), m_cclock);
};
void Tic()
{
clock_get_time(m_cclock, &m_start);
}
void Toc()
{
clock_get_time(m_cclock, &m_stop);
}
double GetElapsedTime() // in ms
{
return 1000.0 * (m_stop.tv_sec - m_start.tv_sec + (1.0E-9) * (m_stop.tv_nsec - m_start.tv_nsec));
}
Timer(void)
{
memset(this, 0, sizeof(Timer));
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &m_cclock);
};
~Timer(void)
{
mach_port_deallocate(mach_task_self(), m_cclock);
};
void Tic()
{
clock_get_time(m_cclock, &m_start);
}
void Toc()
{
clock_get_time(m_cclock, &m_stop);
}
double GetElapsedTime() // in ms
{
return 1000.0 * (m_stop.tv_sec - m_start.tv_sec + (1.0E-9) * (m_stop.tv_nsec - m_start.tv_nsec));
}
private:
clock_serv_t m_cclock;
mach_timespec_t m_start;
mach_timespec_t m_stop;
clock_serv_t m_cclock;
mach_timespec_t m_start;
mach_timespec_t m_stop;
};
#else
class Timer {
class Timer
{
public:
Timer(void)
{
memset(this, 0, sizeof(Timer));
};
~Timer(void){};
void Tic()
{
clock_gettime(CLOCK_REALTIME, &m_start);
}
void Toc()
{
clock_gettime(CLOCK_REALTIME, &m_stop);
}
double GetElapsedTime() // in ms
{
return 1000.0 * (m_stop.tv_sec - m_start.tv_sec + (1.0E-9) * (m_stop.tv_nsec - m_start.tv_nsec));
}
Timer(void)
{
memset(this, 0, sizeof(Timer));
};
~Timer(void){};
void Tic()
{
clock_gettime(CLOCK_REALTIME, &m_start);
}
void Toc()
{
clock_gettime(CLOCK_REALTIME, &m_stop);
}
double GetElapsedTime() // in ms
{
return 1000.0 * (m_stop.tv_sec - m_start.tv_sec + (1.0E-9) * (m_stop.tv_nsec - m_start.tv_nsec));
}
private:
struct timespec m_start;
struct timespec m_stop;
struct timespec m_start;
struct timespec m_stop;
};
#endif
}
#endif // VHACD_TIMER_H
} // namespace VHACD
#endif // VHACD_TIMER_H

View File

@@ -22,7 +22,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#else
#include <CL/cl.h>
#endif
#endif //OPENCL_FOUND
#endif //OPENCL_FOUND
#include "vhacdMutex.h"
#include "vhacdVolume.h"
@@ -30,321 +30,340 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#define USE_THREAD 1
#define OCL_MIN_NUM_PRIMITIVES 4096
#define CH_APP_MIN_NUM_PRIMITIVES 64000
namespace VHACD {
class VHACD : public IVHACD {
namespace VHACD
{
class VHACD : public IVHACD
{
public:
//! Constructor.
VHACD()
{
//! Constructor.
VHACD()
{
#if USE_THREAD == 1 && _OPENMP
m_ompNumProcessors = 2 * omp_get_num_procs();
omp_set_num_threads(m_ompNumProcessors);
#else //USE_THREAD == 1 && _OPENMP
m_ompNumProcessors = 1;
#endif //USE_THREAD == 1 && _OPENMP
m_ompNumProcessors = 2 * omp_get_num_procs();
omp_set_num_threads(m_ompNumProcessors);
#else //USE_THREAD == 1 && _OPENMP
m_ompNumProcessors = 1;
#endif //USE_THREAD == 1 && _OPENMP
#ifdef CL_VERSION_1_1
m_oclWorkGroupSize = 0;
m_oclDevice = 0;
m_oclQueue = 0;
m_oclKernelComputePartialVolumes = 0;
m_oclKernelComputeSum = 0;
#endif //CL_VERSION_1_1
Init();
}
//! Destructor.
~VHACD(void) {}
unsigned int GetNConvexHulls() const
{
return (unsigned int)m_convexHulls.Size();
}
void Cancel()
{
SetCancel(true);
}
void GetConvexHull(const unsigned int index, ConvexHull& ch) const
{
Mesh* mesh = m_convexHulls[index];
ch.m_nPoints = (unsigned int)mesh->GetNPoints();
ch.m_nTriangles = (unsigned int)mesh->GetNTriangles();
ch.m_points = mesh->GetPoints();
ch.m_triangles = mesh->GetTriangles();
}
void Clean(void)
{
delete m_volume;
delete m_pset;
size_t nCH = m_convexHulls.Size();
for (size_t p = 0; p < nCH; ++p) {
delete m_convexHulls[p];
}
m_convexHulls.Clear();
Init();
}
void Release(void)
{
delete this;
}
bool Compute(const float* const points,
const unsigned int stridePoints,
const unsigned int nPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int nTriangles,
const Parameters& params);
bool Compute(const double* const points,
const unsigned int stridePoints,
const unsigned int nPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int nTriangles,
const Parameters& params);
bool OCLInit(void* const oclDevice,
IUserLogger* const logger = 0);
bool OCLRelease(IUserLogger* const logger = 0);
m_oclWorkGroupSize = 0;
m_oclDevice = 0;
m_oclQueue = 0;
m_oclKernelComputePartialVolumes = 0;
m_oclKernelComputeSum = 0;
#endif //CL_VERSION_1_1
Init();
}
//! Destructor.
~VHACD(void) {}
unsigned int GetNConvexHulls() const
{
return (unsigned int)m_convexHulls.Size();
}
void Cancel()
{
SetCancel(true);
}
void GetConvexHull(const unsigned int index, ConvexHull& ch) const
{
Mesh* mesh = m_convexHulls[index];
ch.m_nPoints = (unsigned int)mesh->GetNPoints();
ch.m_nTriangles = (unsigned int)mesh->GetNTriangles();
ch.m_points = mesh->GetPoints();
ch.m_triangles = mesh->GetTriangles();
}
void Clean(void)
{
delete m_volume;
delete m_pset;
size_t nCH = m_convexHulls.Size();
for (size_t p = 0; p < nCH; ++p)
{
delete m_convexHulls[p];
}
m_convexHulls.Clear();
Init();
}
void Release(void)
{
delete this;
}
bool Compute(const float* const points,
const unsigned int stridePoints,
const unsigned int nPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int nTriangles,
const Parameters& params);
bool Compute(const double* const points,
const unsigned int stridePoints,
const unsigned int nPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int nTriangles,
const Parameters& params);
bool OCLInit(void* const oclDevice,
IUserLogger* const logger = 0);
bool OCLRelease(IUserLogger* const logger = 0);
private:
void SetCancel(bool cancel)
{
m_cancelMutex.Lock();
m_cancel = cancel;
m_cancelMutex.Unlock();
}
bool GetCancel()
{
void SetCancel(bool cancel)
{
m_cancelMutex.Lock();
m_cancel = cancel;
m_cancelMutex.Unlock();
}
bool GetCancel()
{
m_cancelMutex.Lock();
bool cancel = m_cancel;
m_cancelMutex.Unlock();
return cancel;
}
void Update(const double stageProgress,
const double operationProgress,
const Parameters& params)
{
m_stageProgress = stageProgress;
m_operationProgress = operationProgress;
if (params.m_callback)
{
params.m_callback->Update(m_overallProgress,
m_stageProgress,
m_operationProgress,
m_stage.c_str(),
m_operation.c_str());
}
}
void Init()
{
memset(m_rot, 0, sizeof(double) * 9);
m_dim = 64;
m_volume = 0;
m_volumeCH0 = 0.0;
m_pset = 0;
m_overallProgress = 0.0;
m_stageProgress = 0.0;
m_operationProgress = 0.0;
m_stage = "";
m_operation = "";
m_barycenter[0] = m_barycenter[1] = m_barycenter[2] = 0.0;
m_rot[0][0] = m_rot[1][1] = m_rot[2][2] = 1.0;
SetCancel(false);
}
void ComputePrimitiveSet(const Parameters& params);
void ComputeACD(const Parameters& params);
void MergeConvexHulls(const Parameters& params);
void SimplifyConvexHulls(const Parameters& params);
void ComputeBestClippingPlane(const PrimitiveSet* inputPSet,
const double volume,
const SArray<Plane>& planes,
const Vec3<double>& preferredCuttingDirection,
const double w,
const double alpha,
const double beta,
const int convexhullDownsampling,
const double progress0,
const double progress1,
Plane& bestPlane,
double& minConcavity,
const Parameters& params);
template <class T>
void AlignMesh(const T* const points,
const unsigned int stridePoints,
const unsigned int nPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int nTriangles,
const Parameters& params)
{
if (GetCancel() || !params.m_pca)
{
return;
}
m_timer.Tic();
m_cancelMutex.Lock();
bool cancel = m_cancel;
m_cancelMutex.Unlock();
return cancel;
}
void Update(const double stageProgress,
const double operationProgress,
const Parameters& params)
{
m_stageProgress = stageProgress;
m_operationProgress = operationProgress;
if (params.m_callback) {
params.m_callback->Update(m_overallProgress,
m_stageProgress,
m_operationProgress,
m_stage.c_str(),
m_operation.c_str());
}
}
void Init()
{
memset(m_rot, 0, sizeof(double) * 9);
m_dim = 64;
m_volume = 0;
m_volumeCH0 = 0.0;
m_pset = 0;
m_overallProgress = 0.0;
m_stageProgress = 0.0;
m_operationProgress = 0.0;
m_stage = "";
m_operation = "";
m_barycenter[0] = m_barycenter[1] = m_barycenter[2] = 0.0;
m_rot[0][0] = m_rot[1][1] = m_rot[2][2] = 1.0;
SetCancel(false);
}
void ComputePrimitiveSet(const Parameters& params);
void ComputeACD(const Parameters& params);
void MergeConvexHulls(const Parameters& params);
void SimplifyConvexHulls(const Parameters& params);
void ComputeBestClippingPlane(const PrimitiveSet* inputPSet,
const double volume,
const SArray<Plane>& planes,
const Vec3<double>& preferredCuttingDirection,
const double w,
const double alpha,
const double beta,
const int convexhullDownsampling,
const double progress0,
const double progress1,
Plane& bestPlane,
double& minConcavity,
const Parameters& params);
template <class T>
void AlignMesh(const T* const points,
const unsigned int stridePoints,
const unsigned int nPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int nTriangles,
const Parameters& params)
{
if (GetCancel() || !params.m_pca) {
return;
}
m_timer.Tic();
m_stage = "Align mesh";
m_operation = "Voxelization";
m_stage = "Align mesh";
m_operation = "Voxelization";
std::ostringstream msg;
if (params.m_logger)
{
msg << "+ " << m_stage << std::endl;
params.m_logger->Log(msg.str().c_str());
}
std::ostringstream msg;
if (params.m_logger) {
msg << "+ " << m_stage << std::endl;
params.m_logger->Log(msg.str().c_str());
}
Update(0.0, 0.0, params);
if (GetCancel())
{
return;
}
m_dim = (size_t)(pow((double)params.m_resolution, 1.0 / 3.0) + 0.5);
Volume volume;
volume.Voxelize(points, stridePoints, nPoints,
triangles, strideTriangles, nTriangles,
m_dim, m_barycenter, m_rot);
size_t n = volume.GetNPrimitivesOnSurf() + volume.GetNPrimitivesInsideSurf();
Update(50.0, 100.0, params);
Update(0.0, 0.0, params);
if (GetCancel()) {
return;
}
m_dim = (size_t)(pow((double)params.m_resolution, 1.0 / 3.0) + 0.5);
Volume volume;
volume.Voxelize(points, stridePoints, nPoints,
triangles, strideTriangles, nTriangles,
m_dim, m_barycenter, m_rot);
size_t n = volume.GetNPrimitivesOnSurf() + volume.GetNPrimitivesInsideSurf();
Update(50.0, 100.0, params);
if (params.m_logger)
{
msg.str("");
msg << "\t dim = " << m_dim << "\t-> " << n << " voxels" << std::endl;
params.m_logger->Log(msg.str().c_str());
}
if (GetCancel())
{
return;
}
m_operation = "PCA";
Update(50.0, 0.0, params);
volume.AlignToPrincipalAxes(m_rot);
m_overallProgress = 1.0;
Update(100.0, 100.0, params);
if (params.m_logger) {
msg.str("");
msg << "\t dim = " << m_dim << "\t-> " << n << " voxels" << std::endl;
params.m_logger->Log(msg.str().c_str());
}
if (GetCancel()) {
return;
}
m_operation = "PCA";
Update(50.0, 0.0, params);
volume.AlignToPrincipalAxes(m_rot);
m_overallProgress = 1.0;
Update(100.0, 100.0, params);
m_timer.Toc();
if (params.m_logger)
{
msg.str("");
msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
params.m_logger->Log(msg.str().c_str());
}
}
template <class T>
void VoxelizeMesh(const T* const points,
const unsigned int stridePoints,
const unsigned int nPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int nTriangles,
const Parameters& params)
{
if (GetCancel())
{
return;
}
m_timer.Toc();
if (params.m_logger) {
msg.str("");
msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
params.m_logger->Log(msg.str().c_str());
}
}
template <class T>
void VoxelizeMesh(const T* const points,
const unsigned int stridePoints,
const unsigned int nPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int nTriangles,
const Parameters& params)
{
if (GetCancel()) {
return;
}
m_timer.Tic();
m_stage = "Voxelization";
m_timer.Tic();
m_stage = "Voxelization";
std::ostringstream msg;
if (params.m_logger)
{
msg << "+ " << m_stage << std::endl;
params.m_logger->Log(msg.str().c_str());
}
std::ostringstream msg;
if (params.m_logger) {
msg << "+ " << m_stage << std::endl;
params.m_logger->Log(msg.str().c_str());
}
delete m_volume;
m_volume = 0;
int iteration = 0;
const int maxIteration = 5;
double progress = 0.0;
while (iteration++ < maxIteration && !m_cancel)
{
msg.str("");
msg << "Iteration " << iteration;
m_operation = msg.str();
delete m_volume;
m_volume = 0;
int iteration = 0;
const int maxIteration = 5;
double progress = 0.0;
while (iteration++ < maxIteration && !m_cancel) {
msg.str("");
msg << "Iteration " << iteration;
m_operation = msg.str();
progress = iteration * 100.0 / maxIteration;
Update(progress, 0.0, params);
progress = iteration * 100.0 / maxIteration;
Update(progress, 0.0, params);
m_volume = new Volume;
m_volume->Voxelize(points, stridePoints, nPoints,
triangles, strideTriangles, nTriangles,
m_dim, m_barycenter, m_rot);
m_volume = new Volume;
m_volume->Voxelize(points, stridePoints, nPoints,
triangles, strideTriangles, nTriangles,
m_dim, m_barycenter, m_rot);
Update(progress, 100.0, params);
Update(progress, 100.0, params);
size_t n = m_volume->GetNPrimitivesOnSurf() + m_volume->GetNPrimitivesInsideSurf();
if (params.m_logger)
{
msg.str("");
msg << "\t dim = " << m_dim << "\t-> " << n << " voxels" << std::endl;
params.m_logger->Log(msg.str().c_str());
}
size_t n = m_volume->GetNPrimitivesOnSurf() + m_volume->GetNPrimitivesInsideSurf();
if (params.m_logger) {
msg.str("");
msg << "\t dim = " << m_dim << "\t-> " << n << " voxels" << std::endl;
params.m_logger->Log(msg.str().c_str());
}
double a = pow((double)(params.m_resolution) / n, 0.33);
size_t dim_next = (size_t)(m_dim * a + 0.5);
if (n < params.m_resolution && iteration < maxIteration && m_volume->GetNPrimitivesOnSurf() < params.m_resolution / 8 && m_dim != dim_next)
{
delete m_volume;
m_volume = 0;
m_dim = dim_next;
}
else
{
break;
}
}
m_overallProgress = 10.0;
Update(100.0, 100.0, params);
double a = pow((double)(params.m_resolution) / n, 0.33);
size_t dim_next = (size_t)(m_dim * a + 0.5);
if (n < params.m_resolution && iteration < maxIteration && m_volume->GetNPrimitivesOnSurf() < params.m_resolution / 8 && m_dim != dim_next) {
delete m_volume;
m_volume = 0;
m_dim = dim_next;
}
else {
break;
}
}
m_overallProgress = 10.0;
Update(100.0, 100.0, params);
m_timer.Toc();
if (params.m_logger) {
msg.str("");
msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
params.m_logger->Log(msg.str().c_str());
}
}
template <class T>
bool ComputeACD(const T* const points,
const unsigned int stridePoints,
const unsigned int nPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int nTriangles,
const Parameters& params)
{
Init();
if (params.m_oclAcceleration) {
// build kernals
}
AlignMesh(points, stridePoints, nPoints, triangles, strideTriangles, nTriangles, params);
VoxelizeMesh(points, stridePoints, nPoints, triangles, strideTriangles, nTriangles, params);
ComputePrimitiveSet(params);
ComputeACD(params);
MergeConvexHulls(params);
SimplifyConvexHulls(params);
if (params.m_oclAcceleration) {
// Release kernals
}
if (GetCancel()) {
Clean();
return false;
}
return true;
}
m_timer.Toc();
if (params.m_logger)
{
msg.str("");
msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
params.m_logger->Log(msg.str().c_str());
}
}
template <class T>
bool ComputeACD(const T* const points,
const unsigned int stridePoints,
const unsigned int nPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int nTriangles,
const Parameters& params)
{
Init();
if (params.m_oclAcceleration)
{
// build kernals
}
AlignMesh(points, stridePoints, nPoints, triangles, strideTriangles, nTriangles, params);
VoxelizeMesh(points, stridePoints, nPoints, triangles, strideTriangles, nTriangles, params);
ComputePrimitiveSet(params);
ComputeACD(params);
MergeConvexHulls(params);
SimplifyConvexHulls(params);
if (params.m_oclAcceleration)
{
// Release kernals
}
if (GetCancel())
{
Clean();
return false;
}
return true;
}
private:
SArray<Mesh*> m_convexHulls;
std::string m_stage;
std::string m_operation;
double m_overallProgress;
double m_stageProgress;
double m_operationProgress;
double m_rot[3][3];
double m_volumeCH0;
Vec3<double> m_barycenter;
Timer m_timer;
size_t m_dim;
Volume* m_volume;
PrimitiveSet* m_pset;
Mutex m_cancelMutex;
bool m_cancel;
int m_ompNumProcessors;
SArray<Mesh*> m_convexHulls;
std::string m_stage;
std::string m_operation;
double m_overallProgress;
double m_stageProgress;
double m_operationProgress;
double m_rot[3][3];
double m_volumeCH0;
Vec3<double> m_barycenter;
Timer m_timer;
size_t m_dim;
Volume* m_volume;
PrimitiveSet* m_pset;
Mutex m_cancelMutex;
bool m_cancel;
int m_ompNumProcessors;
#ifdef CL_VERSION_1_1
cl_device_id* m_oclDevice;
cl_context m_oclContext;
cl_program m_oclProgram;
cl_command_queue* m_oclQueue;
cl_kernel* m_oclKernelComputePartialVolumes;
cl_kernel* m_oclKernelComputeSum;
size_t m_oclWorkGroupSize;
#endif //CL_VERSION_1_1
cl_device_id* m_oclDevice;
cl_context m_oclContext;
cl_program m_oclProgram;
cl_command_queue* m_oclQueue;
cl_kernel* m_oclKernelComputePartialVolumes;
cl_kernel* m_oclKernelComputeSum;
size_t m_oclWorkGroupSize;
#endif //CL_VERSION_1_1
};
}
#endif // VHACD_VHACD_H
} // namespace VHACD
#endif // VHACD_VHACD_H

View File

@@ -18,86 +18,89 @@
#include <iostream>
#include <math.h>
namespace VHACD {
namespace VHACD
{
//! Vector dim 3.
template <typename T>
class Vec3 {
class Vec3
{
public:
T& operator[](size_t i) { return m_data[i]; }
const T& operator[](size_t i) const { return m_data[i]; }
T& X();
T& Y();
T& Z();
const T& X() const;
const T& Y() const;
const T& Z() const;
void Normalize();
T GetNorm() const;
void operator=(const Vec3& rhs);
void operator+=(const Vec3& rhs);
void operator-=(const Vec3& rhs);
void operator-=(T a);
void operator+=(T a);
void operator/=(T a);
void operator*=(T a);
Vec3 operator^(const Vec3& rhs) const;
T operator*(const Vec3& rhs) const;
Vec3 operator+(const Vec3& rhs) const;
Vec3 operator-(const Vec3& rhs) const;
Vec3 operator-() const;
Vec3 operator*(T rhs) const;
Vec3 operator/(T rhs) const;
bool operator<(const Vec3& rhs) const;
bool operator>(const Vec3& rhs) const;
Vec3();
Vec3(T a);
Vec3(T x, T y, T z);
Vec3(const Vec3& rhs);
/*virtual*/ ~Vec3(void);
T& operator[](size_t i) { return m_data[i]; }
const T& operator[](size_t i) const { return m_data[i]; }
T& X();
T& Y();
T& Z();
const T& X() const;
const T& Y() const;
const T& Z() const;
void Normalize();
T GetNorm() const;
void operator=(const Vec3& rhs);
void operator+=(const Vec3& rhs);
void operator-=(const Vec3& rhs);
void operator-=(T a);
void operator+=(T a);
void operator/=(T a);
void operator*=(T a);
Vec3 operator^(const Vec3& rhs) const;
T operator*(const Vec3& rhs) const;
Vec3 operator+(const Vec3& rhs) const;
Vec3 operator-(const Vec3& rhs) const;
Vec3 operator-() const;
Vec3 operator*(T rhs) const;
Vec3 operator/(T rhs) const;
bool operator<(const Vec3& rhs) const;
bool operator>(const Vec3& rhs) const;
Vec3();
Vec3(T a);
Vec3(T x, T y, T z);
Vec3(const Vec3& rhs);
/*virtual*/ ~Vec3(void);
private:
T m_data[3];
T m_data[3];
};
//! Vector dim 2.
template <typename T>
class Vec2 {
class Vec2
{
public:
T& operator[](size_t i) { return m_data[i]; }
const T& operator[](size_t i) const { return m_data[i]; }
T& X();
T& Y();
const T& X() const;
const T& Y() const;
void Normalize();
T GetNorm() const;
void operator=(const Vec2& rhs);
void operator+=(const Vec2& rhs);
void operator-=(const Vec2& rhs);
void operator-=(T a);
void operator+=(T a);
void operator/=(T a);
void operator*=(T a);
T operator^(const Vec2& rhs) const;
T operator*(const Vec2& rhs) const;
Vec2 operator+(const Vec2& rhs) const;
Vec2 operator-(const Vec2& rhs) const;
Vec2 operator-() const;
Vec2 operator*(T rhs) const;
Vec2 operator/(T rhs) const;
Vec2();
Vec2(T a);
Vec2(T x, T y);
Vec2(const Vec2& rhs);
/*virtual*/ ~Vec2(void);
T& operator[](size_t i) { return m_data[i]; }
const T& operator[](size_t i) const { return m_data[i]; }
T& X();
T& Y();
const T& X() const;
const T& Y() const;
void Normalize();
T GetNorm() const;
void operator=(const Vec2& rhs);
void operator+=(const Vec2& rhs);
void operator-=(const Vec2& rhs);
void operator-=(T a);
void operator+=(T a);
void operator/=(T a);
void operator*=(T a);
T operator^(const Vec2& rhs) const;
T operator*(const Vec2& rhs) const;
Vec2 operator+(const Vec2& rhs) const;
Vec2 operator-(const Vec2& rhs) const;
Vec2 operator-() const;
Vec2 operator*(T rhs) const;
Vec2 operator/(T rhs) const;
Vec2();
Vec2(T a);
Vec2(T x, T y);
Vec2(const Vec2& rhs);
/*virtual*/ ~Vec2(void);
private:
T m_data[2];
T m_data[2];
};
template <typename T>
const bool Colinear(const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c);
template <typename T>
const T ComputeVolume4(const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c, const Vec3<T>& d);
}
#include "vhacdVector.inl" // template implementation
} // namespace VHACD
#include "vhacdVector.inl" // template implementation
#endif

View File

@@ -19,401 +19,423 @@
#include "vhacdVector.h"
#include <assert.h>
namespace VHACD {
enum VOXEL_VALUE {
PRIMITIVE_UNDEFINED = 0,
PRIMITIVE_OUTSIDE_SURFACE = 1,
PRIMITIVE_INSIDE_SURFACE = 2,
PRIMITIVE_ON_SURFACE = 3
namespace VHACD
{
enum VOXEL_VALUE
{
PRIMITIVE_UNDEFINED = 0,
PRIMITIVE_OUTSIDE_SURFACE = 1,
PRIMITIVE_INSIDE_SURFACE = 2,
PRIMITIVE_ON_SURFACE = 3
};
struct Voxel {
struct Voxel
{
public:
short m_coord[3];
short m_data;
short m_coord[3];
short m_data;
};
class PrimitiveSet {
class PrimitiveSet
{
public:
virtual ~PrimitiveSet(){};
virtual PrimitiveSet* Create() const = 0;
virtual const size_t GetNPrimitives() const = 0;
virtual const size_t GetNPrimitivesOnSurf() const = 0;
virtual const size_t GetNPrimitivesInsideSurf() const = 0;
virtual const double GetEigenValue(AXIS axis) const = 0;
virtual const double ComputeMaxVolumeError() const = 0;
virtual const double ComputeVolume() const = 0;
virtual void Clip(const Plane& plane, PrimitiveSet* const positivePart,
PrimitiveSet* const negativePart) const = 0;
virtual void Intersect(const Plane& plane, SArray<Vec3<double> >* const positivePts,
SArray<Vec3<double> >* const negativePts, const size_t sampling) const = 0;
virtual void ComputeExteriorPoints(const Plane& plane, const Mesh& mesh,
SArray<Vec3<double> >* const exteriorPts) const = 0;
virtual void ComputeClippedVolumes(const Plane& plane, double& positiveVolume,
double& negativeVolume) const = 0;
virtual void SelectOnSurface(PrimitiveSet* const onSurfP) const = 0;
virtual void ComputeConvexHull(Mesh& meshCH, const size_t sampling = 1) const = 0;
virtual void ComputeBB() = 0;
virtual void ComputePrincipalAxes() = 0;
virtual void AlignToPrincipalAxes() = 0;
virtual void RevertAlignToPrincipalAxes() = 0;
virtual void Convert(Mesh& mesh, const VOXEL_VALUE value) const = 0;
const Mesh& GetConvexHull() const { return m_convexHull; };
Mesh& GetConvexHull() { return m_convexHull; };
virtual ~PrimitiveSet(){};
virtual PrimitiveSet* Create() const = 0;
virtual const size_t GetNPrimitives() const = 0;
virtual const size_t GetNPrimitivesOnSurf() const = 0;
virtual const size_t GetNPrimitivesInsideSurf() const = 0;
virtual const double GetEigenValue(AXIS axis) const = 0;
virtual const double ComputeMaxVolumeError() const = 0;
virtual const double ComputeVolume() const = 0;
virtual void Clip(const Plane& plane, PrimitiveSet* const positivePart,
PrimitiveSet* const negativePart) const = 0;
virtual void Intersect(const Plane& plane, SArray<Vec3<double> >* const positivePts,
SArray<Vec3<double> >* const negativePts, const size_t sampling) const = 0;
virtual void ComputeExteriorPoints(const Plane& plane, const Mesh& mesh,
SArray<Vec3<double> >* const exteriorPts) const = 0;
virtual void ComputeClippedVolumes(const Plane& plane, double& positiveVolume,
double& negativeVolume) const = 0;
virtual void SelectOnSurface(PrimitiveSet* const onSurfP) const = 0;
virtual void ComputeConvexHull(Mesh& meshCH, const size_t sampling = 1) const = 0;
virtual void ComputeBB() = 0;
virtual void ComputePrincipalAxes() = 0;
virtual void AlignToPrincipalAxes() = 0;
virtual void RevertAlignToPrincipalAxes() = 0;
virtual void Convert(Mesh& mesh, const VOXEL_VALUE value) const = 0;
const Mesh& GetConvexHull() const { return m_convexHull; };
Mesh& GetConvexHull() { return m_convexHull; };
private:
Mesh m_convexHull;
Mesh m_convexHull;
};
//!
class VoxelSet : public PrimitiveSet {
friend class Volume;
class VoxelSet : public PrimitiveSet
{
friend class Volume;
public:
//! Destructor.
~VoxelSet(void);
//! Constructor.
VoxelSet();
//! Destructor.
~VoxelSet(void);
//! Constructor.
VoxelSet();
const size_t GetNPrimitives() const { return m_voxels.Size(); }
const size_t GetNPrimitivesOnSurf() const { return m_numVoxelsOnSurface; }
const size_t GetNPrimitivesInsideSurf() const { return m_numVoxelsInsideSurface; }
const double GetEigenValue(AXIS axis) const { return m_D[axis][axis]; }
const double ComputeVolume() const { return m_unitVolume * m_voxels.Size(); }
const double ComputeMaxVolumeError() const { return m_unitVolume * m_numVoxelsOnSurface; }
const Vec3<short>& GetMinBBVoxels() const { return m_minBBVoxels; }
const Vec3<short>& GetMaxBBVoxels() const { return m_maxBBVoxels; }
const Vec3<double>& GetMinBB() const { return m_minBB; }
const double& GetScale() const { return m_scale; }
const double& GetUnitVolume() const { return m_unitVolume; }
Vec3<double> GetPoint(Vec3<short> voxel) const
{
return Vec3<double>(voxel[0] * m_scale + m_minBB[0],
voxel[1] * m_scale + m_minBB[1],
voxel[2] * m_scale + m_minBB[2]);
}
Vec3<double> GetPoint(const Voxel& voxel) const
{
return Vec3<double>(voxel.m_coord[0] * m_scale + m_minBB[0],
voxel.m_coord[1] * m_scale + m_minBB[1],
voxel.m_coord[2] * m_scale + m_minBB[2]);
}
Vec3<double> GetPoint(Vec3<double> voxel) const
{
return Vec3<double>(voxel[0] * m_scale + m_minBB[0],
voxel[1] * m_scale + m_minBB[1],
voxel[2] * m_scale + m_minBB[2]);
}
void GetPoints(const Voxel& voxel, Vec3<double>* const pts) const;
void ComputeConvexHull(Mesh& meshCH, const size_t sampling = 1) const;
void Clip(const Plane& plane, PrimitiveSet* const positivePart, PrimitiveSet* const negativePart) const;
void Intersect(const Plane& plane, SArray<Vec3<double> >* const positivePts,
SArray<Vec3<double> >* const negativePts, const size_t sampling) const;
void ComputeExteriorPoints(const Plane& plane, const Mesh& mesh,
SArray<Vec3<double> >* const exteriorPts) const;
void ComputeClippedVolumes(const Plane& plane, double& positiveVolume, double& negativeVolume) const;
void SelectOnSurface(PrimitiveSet* const onSurfP) const;
void ComputeBB();
void Convert(Mesh& mesh, const VOXEL_VALUE value) const;
void ComputePrincipalAxes();
PrimitiveSet* Create() const
{
return new VoxelSet();
}
void AlignToPrincipalAxes(){};
void RevertAlignToPrincipalAxes(){};
Voxel* const GetVoxels() { return m_voxels.Data(); }
const Voxel* const GetVoxels() const { return m_voxels.Data(); }
const size_t GetNPrimitives() const { return m_voxels.Size(); }
const size_t GetNPrimitivesOnSurf() const { return m_numVoxelsOnSurface; }
const size_t GetNPrimitivesInsideSurf() const { return m_numVoxelsInsideSurface; }
const double GetEigenValue(AXIS axis) const { return m_D[axis][axis]; }
const double ComputeVolume() const { return m_unitVolume * m_voxels.Size(); }
const double ComputeMaxVolumeError() const { return m_unitVolume * m_numVoxelsOnSurface; }
const Vec3<short>& GetMinBBVoxels() const { return m_minBBVoxels; }
const Vec3<short>& GetMaxBBVoxels() const { return m_maxBBVoxels; }
const Vec3<double>& GetMinBB() const { return m_minBB; }
const double& GetScale() const { return m_scale; }
const double& GetUnitVolume() const { return m_unitVolume; }
Vec3<double> GetPoint(Vec3<short> voxel) const
{
return Vec3<double>(voxel[0] * m_scale + m_minBB[0],
voxel[1] * m_scale + m_minBB[1],
voxel[2] * m_scale + m_minBB[2]);
}
Vec3<double> GetPoint(const Voxel& voxel) const
{
return Vec3<double>(voxel.m_coord[0] * m_scale + m_minBB[0],
voxel.m_coord[1] * m_scale + m_minBB[1],
voxel.m_coord[2] * m_scale + m_minBB[2]);
}
Vec3<double> GetPoint(Vec3<double> voxel) const
{
return Vec3<double>(voxel[0] * m_scale + m_minBB[0],
voxel[1] * m_scale + m_minBB[1],
voxel[2] * m_scale + m_minBB[2]);
}
void GetPoints(const Voxel& voxel, Vec3<double>* const pts) const;
void ComputeConvexHull(Mesh& meshCH, const size_t sampling = 1) const;
void Clip(const Plane& plane, PrimitiveSet* const positivePart, PrimitiveSet* const negativePart) const;
void Intersect(const Plane& plane, SArray<Vec3<double> >* const positivePts,
SArray<Vec3<double> >* const negativePts, const size_t sampling) const;
void ComputeExteriorPoints(const Plane& plane, const Mesh& mesh,
SArray<Vec3<double> >* const exteriorPts) const;
void ComputeClippedVolumes(const Plane& plane, double& positiveVolume, double& negativeVolume) const;
void SelectOnSurface(PrimitiveSet* const onSurfP) const;
void ComputeBB();
void Convert(Mesh& mesh, const VOXEL_VALUE value) const;
void ComputePrincipalAxes();
PrimitiveSet* Create() const
{
return new VoxelSet();
}
void AlignToPrincipalAxes(){};
void RevertAlignToPrincipalAxes(){};
Voxel* const GetVoxels() { return m_voxels.Data(); }
const Voxel* const GetVoxels() const { return m_voxels.Data(); }
private:
size_t m_numVoxelsOnSurface;
size_t m_numVoxelsInsideSurface;
Vec3<double> m_minBB;
double m_scale;
SArray<Voxel, 8> m_voxels;
double m_unitVolume;
Vec3<double> m_minBBPts;
Vec3<double> m_maxBBPts;
Vec3<short> m_minBBVoxels;
Vec3<short> m_maxBBVoxels;
Vec3<short> m_barycenter;
double m_Q[3][3];
double m_D[3][3];
Vec3<double> m_barycenterPCA;
size_t m_numVoxelsOnSurface;
size_t m_numVoxelsInsideSurface;
Vec3<double> m_minBB;
double m_scale;
SArray<Voxel, 8> m_voxels;
double m_unitVolume;
Vec3<double> m_minBBPts;
Vec3<double> m_maxBBPts;
Vec3<short> m_minBBVoxels;
Vec3<short> m_maxBBVoxels;
Vec3<short> m_barycenter;
double m_Q[3][3];
double m_D[3][3];
Vec3<double> m_barycenterPCA;
};
struct Tetrahedron {
struct Tetrahedron
{
public:
Vec3<double> m_pts[4];
unsigned char m_data;
Vec3<double> m_pts[4];
unsigned char m_data;
};
//!
class TetrahedronSet : public PrimitiveSet {
friend class Volume;
class TetrahedronSet : public PrimitiveSet
{
friend class Volume;
public:
//! Destructor.
~TetrahedronSet(void);
//! Constructor.
TetrahedronSet();
//! Destructor.
~TetrahedronSet(void);
//! Constructor.
TetrahedronSet();
const size_t GetNPrimitives() const { return m_tetrahedra.Size(); }
const size_t GetNPrimitivesOnSurf() const { return m_numTetrahedraOnSurface; }
const size_t GetNPrimitivesInsideSurf() const { return m_numTetrahedraInsideSurface; }
const Vec3<double>& GetMinBB() const { return m_minBB; }
const Vec3<double>& GetMaxBB() const { return m_maxBB; }
const Vec3<double>& GetBarycenter() const { return m_barycenter; }
const double GetEigenValue(AXIS axis) const { return m_D[axis][axis]; }
const double GetSacle() const { return m_scale; }
const double ComputeVolume() const;
const double ComputeMaxVolumeError() const;
void ComputeConvexHull(Mesh& meshCH, const size_t sampling = 1) const;
void ComputePrincipalAxes();
void AlignToPrincipalAxes();
void RevertAlignToPrincipalAxes();
void Clip(const Plane& plane, PrimitiveSet* const positivePart, PrimitiveSet* const negativePart) const;
void Intersect(const Plane& plane, SArray<Vec3<double> >* const positivePts,
SArray<Vec3<double> >* const negativePts, const size_t sampling) const;
void ComputeExteriorPoints(const Plane& plane, const Mesh& mesh,
SArray<Vec3<double> >* const exteriorPts) const;
void ComputeClippedVolumes(const Plane& plane, double& positiveVolume, double& negativeVolume) const;
void SelectOnSurface(PrimitiveSet* const onSurfP) const;
void ComputeBB();
void Convert(Mesh& mesh, const VOXEL_VALUE value) const;
inline bool Add(Tetrahedron& tetrahedron);
PrimitiveSet* Create() const
{
return new TetrahedronSet();
}
static const double EPS;
const size_t GetNPrimitives() const { return m_tetrahedra.Size(); }
const size_t GetNPrimitivesOnSurf() const { return m_numTetrahedraOnSurface; }
const size_t GetNPrimitivesInsideSurf() const { return m_numTetrahedraInsideSurface; }
const Vec3<double>& GetMinBB() const { return m_minBB; }
const Vec3<double>& GetMaxBB() const { return m_maxBB; }
const Vec3<double>& GetBarycenter() const { return m_barycenter; }
const double GetEigenValue(AXIS axis) const { return m_D[axis][axis]; }
const double GetSacle() const { return m_scale; }
const double ComputeVolume() const;
const double ComputeMaxVolumeError() const;
void ComputeConvexHull(Mesh& meshCH, const size_t sampling = 1) const;
void ComputePrincipalAxes();
void AlignToPrincipalAxes();
void RevertAlignToPrincipalAxes();
void Clip(const Plane& plane, PrimitiveSet* const positivePart, PrimitiveSet* const negativePart) const;
void Intersect(const Plane& plane, SArray<Vec3<double> >* const positivePts,
SArray<Vec3<double> >* const negativePts, const size_t sampling) const;
void ComputeExteriorPoints(const Plane& plane, const Mesh& mesh,
SArray<Vec3<double> >* const exteriorPts) const;
void ComputeClippedVolumes(const Plane& plane, double& positiveVolume, double& negativeVolume) const;
void SelectOnSurface(PrimitiveSet* const onSurfP) const;
void ComputeBB();
void Convert(Mesh& mesh, const VOXEL_VALUE value) const;
inline bool Add(Tetrahedron& tetrahedron);
PrimitiveSet* Create() const
{
return new TetrahedronSet();
}
static const double EPS;
private:
void AddClippedTetrahedra(const Vec3<double> (&pts)[10], const int nPts);
void AddClippedTetrahedra(const Vec3<double> (&pts)[10], const int nPts);
size_t m_numTetrahedraOnSurface;
size_t m_numTetrahedraInsideSurface;
double m_scale;
Vec3<double> m_minBB;
Vec3<double> m_maxBB;
Vec3<double> m_barycenter;
SArray<Tetrahedron, 8> m_tetrahedra;
double m_Q[3][3];
double m_D[3][3];
size_t m_numTetrahedraOnSurface;
size_t m_numTetrahedraInsideSurface;
double m_scale;
Vec3<double> m_minBB;
Vec3<double> m_maxBB;
Vec3<double> m_barycenter;
SArray<Tetrahedron, 8> m_tetrahedra;
double m_Q[3][3];
double m_D[3][3];
};
//!
class Volume {
class Volume
{
public:
//! Destructor.
~Volume(void);
//! Destructor.
~Volume(void);
//! Constructor.
Volume();
//! Constructor.
Volume();
//! Voxelize
template <class T>
void Voxelize(const T* const points, const unsigned int stridePoints, const unsigned int nPoints,
const int* const triangles, const unsigned int strideTriangles, const unsigned int nTriangles,
const size_t dim, const Vec3<double>& barycenter, const double (&rot)[3][3]);
unsigned char& GetVoxel(const size_t i, const size_t j, const size_t k)
{
assert(i < m_dim[0] || i >= 0);
assert(j < m_dim[0] || j >= 0);
assert(k < m_dim[0] || k >= 0);
return m_data[i + j * m_dim[0] + k * m_dim[0] * m_dim[1]];
}
const unsigned char& GetVoxel(const size_t i, const size_t j, const size_t k) const
{
assert(i < m_dim[0] || i >= 0);
assert(j < m_dim[0] || j >= 0);
assert(k < m_dim[0] || k >= 0);
return m_data[i + j * m_dim[0] + k * m_dim[0] * m_dim[1]];
}
const size_t GetNPrimitivesOnSurf() const { return m_numVoxelsOnSurface; }
const size_t GetNPrimitivesInsideSurf() const { return m_numVoxelsInsideSurface; }
void Convert(Mesh& mesh, const VOXEL_VALUE value) const;
void Convert(VoxelSet& vset) const;
void Convert(TetrahedronSet& tset) const;
void AlignToPrincipalAxes(double (&rot)[3][3]) const;
//! Voxelize
template <class T>
void Voxelize(const T* const points, const unsigned int stridePoints, const unsigned int nPoints,
const int* const triangles, const unsigned int strideTriangles, const unsigned int nTriangles,
const size_t dim, const Vec3<double>& barycenter, const double (&rot)[3][3]);
unsigned char& GetVoxel(const size_t i, const size_t j, const size_t k)
{
assert(i < m_dim[0] || i >= 0);
assert(j < m_dim[0] || j >= 0);
assert(k < m_dim[0] || k >= 0);
return m_data[i + j * m_dim[0] + k * m_dim[0] * m_dim[1]];
}
const unsigned char& GetVoxel(const size_t i, const size_t j, const size_t k) const
{
assert(i < m_dim[0] || i >= 0);
assert(j < m_dim[0] || j >= 0);
assert(k < m_dim[0] || k >= 0);
return m_data[i + j * m_dim[0] + k * m_dim[0] * m_dim[1]];
}
const size_t GetNPrimitivesOnSurf() const { return m_numVoxelsOnSurface; }
const size_t GetNPrimitivesInsideSurf() const { return m_numVoxelsInsideSurface; }
void Convert(Mesh& mesh, const VOXEL_VALUE value) const;
void Convert(VoxelSet& vset) const;
void Convert(TetrahedronSet& tset) const;
void AlignToPrincipalAxes(double (&rot)[3][3]) const;
private:
void FillOutsideSurface(const size_t i0, const size_t j0, const size_t k0, const size_t i1,
const size_t j1, const size_t k1);
void FillInsideSurface();
template <class T>
void ComputeBB(const T* const points, const unsigned int stridePoints, const unsigned int nPoints,
const Vec3<double>& barycenter, const double (&rot)[3][3]);
void Allocate();
void Free();
void FillOutsideSurface(const size_t i0, const size_t j0, const size_t k0, const size_t i1,
const size_t j1, const size_t k1);
void FillInsideSurface();
template <class T>
void ComputeBB(const T* const points, const unsigned int stridePoints, const unsigned int nPoints,
const Vec3<double>& barycenter, const double (&rot)[3][3]);
void Allocate();
void Free();
Vec3<double> m_minBB;
Vec3<double> m_maxBB;
double m_scale;
size_t m_dim[3]; //>! dim
size_t m_numVoxelsOnSurface;
size_t m_numVoxelsInsideSurface;
size_t m_numVoxelsOutsideSurface;
unsigned char* m_data;
Vec3<double> m_minBB;
Vec3<double> m_maxBB;
double m_scale;
size_t m_dim[3]; //>! dim
size_t m_numVoxelsOnSurface;
size_t m_numVoxelsInsideSurface;
size_t m_numVoxelsOutsideSurface;
unsigned char* m_data;
};
int TriBoxOverlap(const Vec3<double>& boxcenter, const Vec3<double>& boxhalfsize, const Vec3<double>& triver0,
const Vec3<double>& triver1, const Vec3<double>& triver2);
const Vec3<double>& triver1, const Vec3<double>& triver2);
template <class T>
inline void ComputeAlignedPoint(const T* const points, const unsigned int idx, const Vec3<double>& barycenter,
const double (&rot)[3][3], Vec3<double>& pt){};
const double (&rot)[3][3], Vec3<double>& pt){};
template <>
inline void ComputeAlignedPoint<float>(const float* const points, const unsigned int idx, const Vec3<double>& barycenter, const double (&rot)[3][3], Vec3<double>& pt)
{
double x = points[idx + 0] - barycenter[0];
double y = points[idx + 1] - barycenter[1];
double z = points[idx + 2] - barycenter[2];
pt[0] = rot[0][0] * x + rot[1][0] * y + rot[2][0] * z;
pt[1] = rot[0][1] * x + rot[1][1] * y + rot[2][1] * z;
pt[2] = rot[0][2] * x + rot[1][2] * y + rot[2][2] * z;
double x = points[idx + 0] - barycenter[0];
double y = points[idx + 1] - barycenter[1];
double z = points[idx + 2] - barycenter[2];
pt[0] = rot[0][0] * x + rot[1][0] * y + rot[2][0] * z;
pt[1] = rot[0][1] * x + rot[1][1] * y + rot[2][1] * z;
pt[2] = rot[0][2] * x + rot[1][2] * y + rot[2][2] * z;
}
template <>
inline void ComputeAlignedPoint<double>(const double* const points, const unsigned int idx, const Vec3<double>& barycenter, const double (&rot)[3][3], Vec3<double>& pt)
{
double x = points[idx + 0] - barycenter[0];
double y = points[idx + 1] - barycenter[1];
double z = points[idx + 2] - barycenter[2];
pt[0] = rot[0][0] * x + rot[1][0] * y + rot[2][0] * z;
pt[1] = rot[0][1] * x + rot[1][1] * y + rot[2][1] * z;
pt[2] = rot[0][2] * x + rot[1][2] * y + rot[2][2] * z;
double x = points[idx + 0] - barycenter[0];
double y = points[idx + 1] - barycenter[1];
double z = points[idx + 2] - barycenter[2];
pt[0] = rot[0][0] * x + rot[1][0] * y + rot[2][0] * z;
pt[1] = rot[0][1] * x + rot[1][1] * y + rot[2][1] * z;
pt[2] = rot[0][2] * x + rot[1][2] * y + rot[2][2] * z;
}
template <class T>
void Volume::ComputeBB(const T* const points, const unsigned int stridePoints, const unsigned int nPoints,
const Vec3<double>& barycenter, const double (&rot)[3][3])
const Vec3<double>& barycenter, const double (&rot)[3][3])
{
Vec3<double> pt;
ComputeAlignedPoint(points, 0, barycenter, rot, pt);
m_maxBB = pt;
m_minBB = pt;
for (unsigned int v = 1; v < nPoints; ++v) {
ComputeAlignedPoint(points, v * stridePoints, barycenter, rot, pt);
for (int i = 0; i < 3; ++i) {
if (pt[i] < m_minBB[i])
m_minBB[i] = pt[i];
else if (pt[i] > m_maxBB[i])
m_maxBB[i] = pt[i];
}
}
Vec3<double> pt;
ComputeAlignedPoint(points, 0, barycenter, rot, pt);
m_maxBB = pt;
m_minBB = pt;
for (unsigned int v = 1; v < nPoints; ++v)
{
ComputeAlignedPoint(points, v * stridePoints, barycenter, rot, pt);
for (int i = 0; i < 3; ++i)
{
if (pt[i] < m_minBB[i])
m_minBB[i] = pt[i];
else if (pt[i] > m_maxBB[i])
m_maxBB[i] = pt[i];
}
}
}
template <class T>
void Volume::Voxelize(const T* const points, const unsigned int stridePoints, const unsigned int nPoints,
const int* const triangles, const unsigned int strideTriangles, const unsigned int nTriangles,
const size_t dim, const Vec3<double>& barycenter, const double (&rot)[3][3])
const int* const triangles, const unsigned int strideTriangles, const unsigned int nTriangles,
const size_t dim, const Vec3<double>& barycenter, const double (&rot)[3][3])
{
if (nPoints == 0) {
return;
}
ComputeBB(points, stridePoints, nPoints, barycenter, rot);
if (nPoints == 0)
{
return;
}
ComputeBB(points, stridePoints, nPoints, barycenter, rot);
double d[3] = { m_maxBB[0] - m_minBB[0], m_maxBB[1] - m_minBB[1], m_maxBB[2] - m_minBB[2] };
double r;
if (d[0] > d[1] && d[0] > d[2]) {
r = d[0];
m_dim[0] = dim;
m_dim[1] = 2 + static_cast<size_t>(dim * d[1] / d[0]);
m_dim[2] = 2 + static_cast<size_t>(dim * d[2] / d[0]);
}
else if (d[1] > d[0] && d[1] > d[2]) {
r = d[1];
m_dim[1] = dim;
m_dim[0] = 2 + static_cast<size_t>(dim * d[0] / d[1]);
m_dim[2] = 2 + static_cast<size_t>(dim * d[2] / d[1]);
}
else {
r = d[2];
m_dim[2] = dim;
m_dim[0] = 2 + static_cast<size_t>(dim * d[0] / d[2]);
m_dim[1] = 2 + static_cast<size_t>(dim * d[1] / d[2]);
}
double d[3] = {m_maxBB[0] - m_minBB[0], m_maxBB[1] - m_minBB[1], m_maxBB[2] - m_minBB[2]};
double r;
if (d[0] > d[1] && d[0] > d[2])
{
r = d[0];
m_dim[0] = dim;
m_dim[1] = 2 + static_cast<size_t>(dim * d[1] / d[0]);
m_dim[2] = 2 + static_cast<size_t>(dim * d[2] / d[0]);
}
else if (d[1] > d[0] && d[1] > d[2])
{
r = d[1];
m_dim[1] = dim;
m_dim[0] = 2 + static_cast<size_t>(dim * d[0] / d[1]);
m_dim[2] = 2 + static_cast<size_t>(dim * d[2] / d[1]);
}
else
{
r = d[2];
m_dim[2] = dim;
m_dim[0] = 2 + static_cast<size_t>(dim * d[0] / d[2]);
m_dim[1] = 2 + static_cast<size_t>(dim * d[1] / d[2]);
}
m_scale = r / (dim - 1);
double invScale = (dim - 1) / r;
m_scale = r / (dim - 1);
double invScale = (dim - 1) / r;
Allocate();
m_numVoxelsOnSurface = 0;
m_numVoxelsInsideSurface = 0;
m_numVoxelsOutsideSurface = 0;
Allocate();
m_numVoxelsOnSurface = 0;
m_numVoxelsInsideSurface = 0;
m_numVoxelsOutsideSurface = 0;
Vec3<double> p[3];
size_t i, j, k;
size_t i0, j0, k0;
size_t i1, j1, k1;
Vec3<double> boxcenter;
Vec3<double> pt;
const Vec3<double> boxhalfsize(0.5, 0.5, 0.5);
for (size_t t = 0, ti = 0; t < nTriangles; ++t, ti += strideTriangles) {
Vec3<int> tri(triangles[ti + 0],
triangles[ti + 1],
triangles[ti + 2]);
for (int c = 0; c < 3; ++c) {
ComputeAlignedPoint(points, tri[c] * stridePoints, barycenter, rot, pt);
p[c][0] = (pt[0] - m_minBB[0]) * invScale;
p[c][1] = (pt[1] - m_minBB[1]) * invScale;
p[c][2] = (pt[2] - m_minBB[2]) * invScale;
i = static_cast<size_t>(p[c][0] + 0.5);
j = static_cast<size_t>(p[c][1] + 0.5);
k = static_cast<size_t>(p[c][2] + 0.5);
assert(i < m_dim[0] && i >= 0 && j < m_dim[1] && j >= 0 && k < m_dim[2] && k >= 0);
Vec3<double> p[3];
size_t i, j, k;
size_t i0, j0, k0;
size_t i1, j1, k1;
Vec3<double> boxcenter;
Vec3<double> pt;
const Vec3<double> boxhalfsize(0.5, 0.5, 0.5);
for (size_t t = 0, ti = 0; t < nTriangles; ++t, ti += strideTriangles)
{
Vec3<int> tri(triangles[ti + 0],
triangles[ti + 1],
triangles[ti + 2]);
for (int c = 0; c < 3; ++c)
{
ComputeAlignedPoint(points, tri[c] * stridePoints, barycenter, rot, pt);
p[c][0] = (pt[0] - m_minBB[0]) * invScale;
p[c][1] = (pt[1] - m_minBB[1]) * invScale;
p[c][2] = (pt[2] - m_minBB[2]) * invScale;
i = static_cast<size_t>(p[c][0] + 0.5);
j = static_cast<size_t>(p[c][1] + 0.5);
k = static_cast<size_t>(p[c][2] + 0.5);
assert(i < m_dim[0] && i >= 0 && j < m_dim[1] && j >= 0 && k < m_dim[2] && k >= 0);
if (c == 0) {
i0 = i1 = i;
j0 = j1 = j;
k0 = k1 = k;
}
else {
if (i < i0)
i0 = i;
if (j < j0)
j0 = j;
if (k < k0)
k0 = k;
if (i > i1)
i1 = i;
if (j > j1)
j1 = j;
if (k > k1)
k1 = k;
}
}
if (i0 > 0)
--i0;
if (j0 > 0)
--j0;
if (k0 > 0)
--k0;
if (i1 < m_dim[0])
++i1;
if (j1 < m_dim[1])
++j1;
if (k1 < m_dim[2])
++k1;
for (size_t i = i0; i < i1; ++i) {
boxcenter[0] = (double)i;
for (size_t j = j0; j < j1; ++j) {
boxcenter[1] = (double)j;
for (size_t k = k0; k < k1; ++k) {
boxcenter[2] = (double)k;
int res = TriBoxOverlap(boxcenter, boxhalfsize, p[0], p[1], p[2]);
unsigned char& value = GetVoxel(i, j, k);
if (res == 1 && value == PRIMITIVE_UNDEFINED) {
value = PRIMITIVE_ON_SURFACE;
++m_numVoxelsOnSurface;
}
}
}
}
}
FillOutsideSurface(0, 0, 0, m_dim[0], m_dim[1], 1);
FillOutsideSurface(0, 0, m_dim[2] - 1, m_dim[0], m_dim[1], m_dim[2]);
FillOutsideSurface(0, 0, 0, m_dim[0], 1, m_dim[2]);
FillOutsideSurface(0, m_dim[1] - 1, 0, m_dim[0], m_dim[1], m_dim[2]);
FillOutsideSurface(0, 0, 0, 1, m_dim[1], m_dim[2]);
FillOutsideSurface(m_dim[0] - 1, 0, 0, m_dim[0], m_dim[1], m_dim[2]);
FillInsideSurface();
if (c == 0)
{
i0 = i1 = i;
j0 = j1 = j;
k0 = k1 = k;
}
else
{
if (i < i0)
i0 = i;
if (j < j0)
j0 = j;
if (k < k0)
k0 = k;
if (i > i1)
i1 = i;
if (j > j1)
j1 = j;
if (k > k1)
k1 = k;
}
}
if (i0 > 0)
--i0;
if (j0 > 0)
--j0;
if (k0 > 0)
--k0;
if (i1 < m_dim[0])
++i1;
if (j1 < m_dim[1])
++j1;
if (k1 < m_dim[2])
++k1;
for (size_t i = i0; i < i1; ++i)
{
boxcenter[0] = (double)i;
for (size_t j = j0; j < j1; ++j)
{
boxcenter[1] = (double)j;
for (size_t k = k0; k < k1; ++k)
{
boxcenter[2] = (double)k;
int res = TriBoxOverlap(boxcenter, boxhalfsize, p[0], p[1], p[2]);
unsigned char& value = GetVoxel(i, j, k);
if (res == 1 && value == PRIMITIVE_UNDEFINED)
{
value = PRIMITIVE_ON_SURFACE;
++m_numVoxelsOnSurface;
}
}
}
}
}
FillOutsideSurface(0, 0, 0, m_dim[0], m_dim[1], 1);
FillOutsideSurface(0, 0, m_dim[2] - 1, m_dim[0], m_dim[1], m_dim[2]);
FillOutsideSurface(0, 0, 0, m_dim[0], 1, m_dim[2]);
FillOutsideSurface(0, m_dim[1] - 1, 0, m_dim[0], m_dim[1], m_dim[2]);
FillOutsideSurface(0, 0, 0, 1, m_dim[1], m_dim[2]);
FillOutsideSurface(m_dim[0] - 1, 0, 0, m_dim[0], m_dim[1], m_dim[2]);
FillInsideSurface();
}
}
#endif // VHACD_VOLUME_H
} // namespace VHACD
#endif // VHACD_VOLUME_H

View File

@@ -19,103 +19,105 @@
#define VHACD_VERSION_MAJOR 2
#define VHACD_VERSION_MINOR 2
namespace VHACD {
class IVHACD {
namespace VHACD
{
class IVHACD
{
public:
class IUserCallback {
public:
virtual ~IUserCallback(){};
virtual void Update(const double overallProgress,
const double stageProgress,
const double operationProgress,
const char* const stage,
const char* const operation)
= 0;
};
class IUserCallback
{
public:
virtual ~IUserCallback(){};
virtual void Update(const double overallProgress,
const double stageProgress,
const double operationProgress,
const char* const stage,
const char* const operation) = 0;
};
class IUserLogger {
public:
virtual ~IUserLogger(){};
virtual void Log(const char* const msg) = 0;
};
class IUserLogger
{
public:
virtual ~IUserLogger(){};
virtual void Log(const char* const msg) = 0;
};
class ConvexHull {
public:
double* m_points;
int* m_triangles;
unsigned int m_nPoints;
unsigned int m_nTriangles;
};
class ConvexHull
{
public:
double* m_points;
int* m_triangles;
unsigned int m_nPoints;
unsigned int m_nTriangles;
};
class Parameters {
public:
Parameters(void) { Init(); }
void Init(void)
{
m_resolution = 1000000;
m_depth = 20;
m_concavity = 0.001;
m_planeDownsampling = 4;
m_convexhullDownsampling = 4;
m_alpha = 0.05;
m_beta = 0.05;
m_gamma = 0.0005;
m_pca = 0;
m_mode = 0; // 0: voxel-based (recommended), 1: tetrahedron-based
m_maxNumVerticesPerCH = 64;
m_minVolumePerCH = 0.0001;
m_callback = 0;
m_logger = 0;
m_convexhullApproximation = true;
m_oclAcceleration = true;
}
double m_concavity;
double m_alpha;
double m_beta;
double m_gamma;
double m_minVolumePerCH;
IUserCallback* m_callback;
IUserLogger* m_logger;
unsigned int m_resolution;
unsigned int m_maxNumVerticesPerCH;
int m_depth;
int m_planeDownsampling;
int m_convexhullDownsampling;
int m_pca;
int m_mode;
int m_convexhullApproximation;
int m_oclAcceleration;
};
class Parameters
{
public:
Parameters(void) { Init(); }
void Init(void)
{
m_resolution = 1000000;
m_depth = 20;
m_concavity = 0.001;
m_planeDownsampling = 4;
m_convexhullDownsampling = 4;
m_alpha = 0.05;
m_beta = 0.05;
m_gamma = 0.0005;
m_pca = 0;
m_mode = 0; // 0: voxel-based (recommended), 1: tetrahedron-based
m_maxNumVerticesPerCH = 64;
m_minVolumePerCH = 0.0001;
m_callback = 0;
m_logger = 0;
m_convexhullApproximation = true;
m_oclAcceleration = true;
}
double m_concavity;
double m_alpha;
double m_beta;
double m_gamma;
double m_minVolumePerCH;
IUserCallback* m_callback;
IUserLogger* m_logger;
unsigned int m_resolution;
unsigned int m_maxNumVerticesPerCH;
int m_depth;
int m_planeDownsampling;
int m_convexhullDownsampling;
int m_pca;
int m_mode;
int m_convexhullApproximation;
int m_oclAcceleration;
};
virtual void Cancel() = 0;
virtual bool Compute(const float* const points,
const unsigned int stridePoints,
const unsigned int countPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int countTriangles,
const Parameters& params)
= 0;
virtual bool Compute(const double* const points,
const unsigned int stridePoints,
const unsigned int countPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int countTriangles,
const Parameters& params)
= 0;
virtual unsigned int GetNConvexHulls() const = 0;
virtual void GetConvexHull(const unsigned int index, ConvexHull& ch) const = 0;
virtual void Clean(void) = 0; // release internally allocated memory
virtual void Release(void) = 0; // release IVHACD
virtual bool OCLInit(void* const oclDevice,
IUserLogger* const logger = 0)
= 0;
virtual bool OCLRelease(IUserLogger* const logger = 0) = 0;
virtual void Cancel() = 0;
virtual bool Compute(const float* const points,
const unsigned int stridePoints,
const unsigned int countPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int countTriangles,
const Parameters& params) = 0;
virtual bool Compute(const double* const points,
const unsigned int stridePoints,
const unsigned int countPoints,
const int* const triangles,
const unsigned int strideTriangles,
const unsigned int countTriangles,
const Parameters& params) = 0;
virtual unsigned int GetNConvexHulls() const = 0;
virtual void GetConvexHull(const unsigned int index, ConvexHull& ch) const = 0;
virtual void Clean(void) = 0; // release internally allocated memory
virtual void Release(void) = 0; // release IVHACD
virtual bool OCLInit(void* const oclDevice,
IUserLogger* const logger = 0) = 0;
virtual bool OCLRelease(IUserLogger* const logger = 0) = 0;
protected:
virtual ~IVHACD(void) {}
virtual ~IVHACD(void) {}
};
IVHACD* CreateVHACD(void);
}
#endif // VHACD_H
} // namespace VHACD
#endif // VHACD_H

File diff suppressed because it is too large Load Diff

View File

@@ -17,16 +17,16 @@ subject to the following restrictions:
int gNumAlignedAllocs = 0;
int gNumAlignedFree = 0;
int gTotalBytesAlignedAllocs = 0; //detect memory leaks
int gTotalBytesAlignedAllocs = 0; //detect memory leaks
static void* btAllocDefault(size_t size)
{
return malloc(size);
return malloc(size);
}
static void btFreeDefault(void* ptr)
{
free(ptr);
free(ptr);
}
static btAllocFunc* sAllocFunc = btAllocDefault;
@@ -36,52 +36,55 @@ static btFreeFunc* sFreeFunc = btFreeDefault;
#include <malloc.h>
static void* btAlignedAllocDefault(size_t size, int alignment)
{
return _aligned_malloc(size, (size_t)alignment);
return _aligned_malloc(size, (size_t)alignment);
}
static void btAlignedFreeDefault(void* ptr)
{
_aligned_free(ptr);
_aligned_free(ptr);
}
#elif defined(__CELLOS_LV2__)
#include <stdlib.h>
static inline void* btAlignedAllocDefault(size_t size, int alignment)
{
return memalign(alignment, size);
return memalign(alignment, size);
}
static inline void btAlignedFreeDefault(void* ptr)
{
free(ptr);
free(ptr);
}
#else
static inline void* btAlignedAllocDefault(size_t size, int alignment)
{
void* ret;
char* real;
unsigned long offset;
void* ret;
char* real;
unsigned long offset;
real = (char*)sAllocFunc(size + sizeof(void*) + (alignment - 1));
if (real) {
offset = (alignment - (unsigned long)(real + sizeof(void*))) & (alignment - 1);
ret = (void*)((real + sizeof(void*)) + offset);
*((void**)(ret)-1) = (void*)(real);
}
else {
ret = (void*)(real);
}
return (ret);
real = (char*)sAllocFunc(size + sizeof(void*) + (alignment - 1));
if (real)
{
offset = (alignment - (unsigned long)(real + sizeof(void*))) & (alignment - 1);
ret = (void*)((real + sizeof(void*)) + offset);
*((void**)(ret)-1) = (void*)(real);
}
else
{
ret = (void*)(real);
}
return (ret);
}
static inline void btAlignedFreeDefault(void* ptr)
{
void* real;
void* real;
if (ptr) {
real = *((void**)(ptr)-1);
sFreeFunc(real);
}
if (ptr)
{
real = *((void**)(ptr)-1);
sFreeFunc(real);
}
}
#endif
@@ -90,14 +93,14 @@ static btAlignedFreeFunc* sAlignedFreeFunc = btAlignedFreeDefault;
void btAlignedAllocSetCustomAligned(btAlignedAllocFunc* allocFunc, btAlignedFreeFunc* freeFunc)
{
sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
}
void btAlignedAllocSetCustom(btAllocFunc* allocFunc, btFreeFunc* freeFunc)
{
sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
}
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
@@ -106,71 +109,75 @@ void btAlignedAllocSetCustom(btAllocFunc* allocFunc, btFreeFunc* freeFunc)
void* btAlignedAllocInternal(size_t size, int alignment, int line, char* filename)
{
void* ret;
char* real;
unsigned long offset;
void* ret;
char* real;
unsigned long offset;
gTotalBytesAlignedAllocs += size;
gNumAlignedAllocs++;
gTotalBytesAlignedAllocs += size;
gNumAlignedAllocs++;
real = (char*)sAllocFunc(size + 2 * sizeof(void*) + (alignment - 1));
if (real) {
offset = (alignment - (unsigned long)(real + 2 * sizeof(void*))) & (alignment - 1);
ret = (void*)((real + 2 * sizeof(void*)) + offset);
*((void**)(ret)-1) = (void*)(real);
*((int*)(ret)-2) = size;
}
else {
ret = (void*)(real); //??
}
real = (char*)sAllocFunc(size + 2 * sizeof(void*) + (alignment - 1));
if (real)
{
offset = (alignment - (unsigned long)(real + 2 * sizeof(void*))) & (alignment - 1);
ret = (void*)((real + 2 * sizeof(void*)) + offset);
*((void**)(ret)-1) = (void*)(real);
*((int*)(ret)-2) = size;
}
else
{
ret = (void*)(real); //??
}
printf("allocation#%d at address %x, from %s,line %d, size %d\n", gNumAlignedAllocs, real, filename, line, size);
printf("allocation#%d at address %x, from %s,line %d, size %d\n", gNumAlignedAllocs, real, filename, line, size);
int* ptr = (int*)ret;
*ptr = 12;
return (ret);
int* ptr = (int*)ret;
*ptr = 12;
return (ret);
}
void btAlignedFreeInternal(void* ptr, int line, char* filename)
{
void* real;
gNumAlignedFree++;
void* real;
gNumAlignedFree++;
if (ptr)
{
real = *((void**)(ptr)-1);
int size = *((int*)(ptr)-2);
gTotalBytesAlignedAllocs -= size;
if (ptr) {
real = *((void**)(ptr)-1);
int size = *((int*)(ptr)-2);
gTotalBytesAlignedAllocs -= size;
printf("free #%d at address %x, from %s,line %d, size %d\n", gNumAlignedFree, real, filename, line, size);
printf("free #%d at address %x, from %s,line %d, size %d\n", gNumAlignedFree, real, filename, line, size);
sFreeFunc(real);
}
else {
printf("NULL ptr\n");
}
sFreeFunc(real);
}
else
{
printf("NULL ptr\n");
}
}
#else //BT_DEBUG_MEMORY_ALLOCATIONS
#else //BT_DEBUG_MEMORY_ALLOCATIONS
void* btAlignedAllocInternal(size_t size, int alignment)
{
gNumAlignedAllocs++;
void* ptr;
ptr = sAlignedAllocFunc(size, alignment);
// printf("btAlignedAllocInternal %d, %x\n",size,ptr);
return ptr;
gNumAlignedAllocs++;
void* ptr;
ptr = sAlignedAllocFunc(size, alignment);
// printf("btAlignedAllocInternal %d, %x\n",size,ptr);
return ptr;
}
void btAlignedFreeInternal(void* ptr)
{
if (!ptr) {
return;
}
if (!ptr)
{
return;
}
gNumAlignedFree++;
// printf("btAlignedFreeInternal %x\n",ptr);
sAlignedFreeFunc(ptr);
gNumAlignedFree++;
// printf("btAlignedFreeInternal %x\n",ptr);
sAlignedFreeFunc(ptr);
}
#endif //BT_DEBUG_MEMORY_ALLOCATIONS
#endif //BT_DEBUG_MEMORY_ALLOCATIONS

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -13,18 +13,19 @@
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "vhacdManifoldMesh.h"
namespace VHACD {
namespace VHACD
{
TMMVertex::TMMVertex(void)
{
Initialize();
Initialize();
}
void TMMVertex::Initialize()
{
m_name = 0;
m_id = 0;
m_duplicate = 0;
m_onHull = false;
m_tag = false;
m_name = 0;
m_id = 0;
m_duplicate = 0;
m_onHull = false;
m_tag = false;
}
TMMVertex::~TMMVertex(void)
@@ -32,29 +33,30 @@ TMMVertex::~TMMVertex(void)
}
TMMEdge::TMMEdge(void)
{
Initialize();
Initialize();
}
void TMMEdge::Initialize()
{
m_id = 0;
m_triangles[0] = m_triangles[1] = m_newFace = 0;
m_vertices[0] = m_vertices[1] = 0;
m_id = 0;
m_triangles[0] = m_triangles[1] = m_newFace = 0;
m_vertices[0] = m_vertices[1] = 0;
}
TMMEdge::~TMMEdge(void)
{
}
void TMMTriangle::Initialize()
{
m_id = 0;
for (int i = 0; i < 3; i++) {
m_edges[i] = 0;
m_vertices[0] = 0;
}
m_visible = false;
m_id = 0;
for (int i = 0; i < 3; i++)
{
m_edges[i] = 0;
m_vertices[0] = 0;
}
m_visible = false;
}
TMMTriangle::TMMTriangle(void)
{
Initialize();
Initialize();
}
TMMTriangle::~TMMTriangle(void)
{
@@ -67,136 +69,167 @@ TMMesh::~TMMesh(void)
}
void TMMesh::GetIFS(Vec3<double>* const points, Vec3<int>* const triangles)
{
size_t nV = m_vertices.GetSize();
size_t nT = m_triangles.GetSize();
size_t nV = m_vertices.GetSize();
size_t nT = m_triangles.GetSize();
for (size_t v = 0; v < nV; v++) {
points[v] = m_vertices.GetData().m_pos;
m_vertices.GetData().m_id = v;
m_vertices.Next();
}
for (size_t f = 0; f < nT; f++) {
TMMTriangle& currentTriangle = m_triangles.GetData();
triangles[f].X() = static_cast<int>(currentTriangle.m_vertices[0]->GetData().m_id);
triangles[f].Y() = static_cast<int>(currentTriangle.m_vertices[1]->GetData().m_id);
triangles[f].Z() = static_cast<int>(currentTriangle.m_vertices[2]->GetData().m_id);
m_triangles.Next();
}
for (size_t v = 0; v < nV; v++)
{
points[v] = m_vertices.GetData().m_pos;
m_vertices.GetData().m_id = v;
m_vertices.Next();
}
for (size_t f = 0; f < nT; f++)
{
TMMTriangle& currentTriangle = m_triangles.GetData();
triangles[f].X() = static_cast<int>(currentTriangle.m_vertices[0]->GetData().m_id);
triangles[f].Y() = static_cast<int>(currentTriangle.m_vertices[1]->GetData().m_id);
triangles[f].Z() = static_cast<int>(currentTriangle.m_vertices[2]->GetData().m_id);
m_triangles.Next();
}
}
void TMMesh::Clear()
{
m_vertices.Clear();
m_edges.Clear();
m_triangles.Clear();
m_vertices.Clear();
m_edges.Clear();
m_triangles.Clear();
}
void TMMesh::Copy(TMMesh& mesh)
{
Clear();
// updating the id's
size_t nV = mesh.m_vertices.GetSize();
size_t nE = mesh.m_edges.GetSize();
size_t nT = mesh.m_triangles.GetSize();
for (size_t v = 0; v < nV; v++) {
mesh.m_vertices.GetData().m_id = v;
mesh.m_vertices.Next();
}
for (size_t e = 0; e < nE; e++) {
mesh.m_edges.GetData().m_id = e;
mesh.m_edges.Next();
}
for (size_t f = 0; f < nT; f++) {
mesh.m_triangles.GetData().m_id = f;
mesh.m_triangles.Next();
}
// copying data
m_vertices = mesh.m_vertices;
m_edges = mesh.m_edges;
m_triangles = mesh.m_triangles;
Clear();
// updating the id's
size_t nV = mesh.m_vertices.GetSize();
size_t nE = mesh.m_edges.GetSize();
size_t nT = mesh.m_triangles.GetSize();
for (size_t v = 0; v < nV; v++)
{
mesh.m_vertices.GetData().m_id = v;
mesh.m_vertices.Next();
}
for (size_t e = 0; e < nE; e++)
{
mesh.m_edges.GetData().m_id = e;
mesh.m_edges.Next();
}
for (size_t f = 0; f < nT; f++)
{
mesh.m_triangles.GetData().m_id = f;
mesh.m_triangles.Next();
}
// copying data
m_vertices = mesh.m_vertices;
m_edges = mesh.m_edges;
m_triangles = mesh.m_triangles;
// generate mapping
CircularListElement<TMMVertex>** vertexMap = new CircularListElement<TMMVertex>*[nV];
CircularListElement<TMMEdge>** edgeMap = new CircularListElement<TMMEdge>*[nE];
CircularListElement<TMMTriangle>** triangleMap = new CircularListElement<TMMTriangle>*[nT];
for (size_t v = 0; v < nV; v++) {
vertexMap[v] = m_vertices.GetHead();
m_vertices.Next();
}
for (size_t e = 0; e < nE; e++) {
edgeMap[e] = m_edges.GetHead();
m_edges.Next();
}
for (size_t f = 0; f < nT; f++) {
triangleMap[f] = m_triangles.GetHead();
m_triangles.Next();
}
// generate mapping
CircularListElement<TMMVertex>** vertexMap = new CircularListElement<TMMVertex>*[nV];
CircularListElement<TMMEdge>** edgeMap = new CircularListElement<TMMEdge>*[nE];
CircularListElement<TMMTriangle>** triangleMap = new CircularListElement<TMMTriangle>*[nT];
for (size_t v = 0; v < nV; v++)
{
vertexMap[v] = m_vertices.GetHead();
m_vertices.Next();
}
for (size_t e = 0; e < nE; e++)
{
edgeMap[e] = m_edges.GetHead();
m_edges.Next();
}
for (size_t f = 0; f < nT; f++)
{
triangleMap[f] = m_triangles.GetHead();
m_triangles.Next();
}
// updating pointers
for (size_t v = 0; v < nV; v++) {
if (vertexMap[v]->GetData().m_duplicate) {
vertexMap[v]->GetData().m_duplicate = edgeMap[vertexMap[v]->GetData().m_duplicate->GetData().m_id];
}
}
for (size_t e = 0; e < nE; e++) {
if (edgeMap[e]->GetData().m_newFace) {
edgeMap[e]->GetData().m_newFace = triangleMap[edgeMap[e]->GetData().m_newFace->GetData().m_id];
}
if (nT > 0) {
for (int f = 0; f < 2; f++) {
if (edgeMap[e]->GetData().m_triangles[f]) {
edgeMap[e]->GetData().m_triangles[f] = triangleMap[edgeMap[e]->GetData().m_triangles[f]->GetData().m_id];
}
}
}
for (int v = 0; v < 2; v++) {
if (edgeMap[e]->GetData().m_vertices[v]) {
edgeMap[e]->GetData().m_vertices[v] = vertexMap[edgeMap[e]->GetData().m_vertices[v]->GetData().m_id];
}
}
}
for (size_t f = 0; f < nT; f++) {
if (nE > 0) {
for (int e = 0; e < 3; e++) {
if (triangleMap[f]->GetData().m_edges[e]) {
triangleMap[f]->GetData().m_edges[e] = edgeMap[triangleMap[f]->GetData().m_edges[e]->GetData().m_id];
}
}
}
for (int v = 0; v < 3; v++) {
if (triangleMap[f]->GetData().m_vertices[v]) {
triangleMap[f]->GetData().m_vertices[v] = vertexMap[triangleMap[f]->GetData().m_vertices[v]->GetData().m_id];
}
}
}
delete[] vertexMap;
delete[] edgeMap;
delete[] triangleMap;
// updating pointers
for (size_t v = 0; v < nV; v++)
{
if (vertexMap[v]->GetData().m_duplicate)
{
vertexMap[v]->GetData().m_duplicate = edgeMap[vertexMap[v]->GetData().m_duplicate->GetData().m_id];
}
}
for (size_t e = 0; e < nE; e++)
{
if (edgeMap[e]->GetData().m_newFace)
{
edgeMap[e]->GetData().m_newFace = triangleMap[edgeMap[e]->GetData().m_newFace->GetData().m_id];
}
if (nT > 0)
{
for (int f = 0; f < 2; f++)
{
if (edgeMap[e]->GetData().m_triangles[f])
{
edgeMap[e]->GetData().m_triangles[f] = triangleMap[edgeMap[e]->GetData().m_triangles[f]->GetData().m_id];
}
}
}
for (int v = 0; v < 2; v++)
{
if (edgeMap[e]->GetData().m_vertices[v])
{
edgeMap[e]->GetData().m_vertices[v] = vertexMap[edgeMap[e]->GetData().m_vertices[v]->GetData().m_id];
}
}
}
for (size_t f = 0; f < nT; f++)
{
if (nE > 0)
{
for (int e = 0; e < 3; e++)
{
if (triangleMap[f]->GetData().m_edges[e])
{
triangleMap[f]->GetData().m_edges[e] = edgeMap[triangleMap[f]->GetData().m_edges[e]->GetData().m_id];
}
}
}
for (int v = 0; v < 3; v++)
{
if (triangleMap[f]->GetData().m_vertices[v])
{
triangleMap[f]->GetData().m_vertices[v] = vertexMap[triangleMap[f]->GetData().m_vertices[v]->GetData().m_id];
}
}
}
delete[] vertexMap;
delete[] edgeMap;
delete[] triangleMap;
}
bool TMMesh::CheckConsistancy()
{
size_t nE = m_edges.GetSize();
size_t nT = m_triangles.GetSize();
for (size_t e = 0; e < nE; e++) {
for (int f = 0; f < 2; f++) {
if (!m_edges.GetHead()->GetData().m_triangles[f]) {
return false;
}
}
m_edges.Next();
}
for (size_t f = 0; f < nT; f++) {
for (int e = 0; e < 3; e++) {
int found = 0;
for (int k = 0; k < 2; k++) {
if (m_triangles.GetHead()->GetData().m_edges[e]->GetData().m_triangles[k] == m_triangles.GetHead()) {
found++;
}
}
if (found != 1) {
return false;
}
}
m_triangles.Next();
}
return true;
size_t nE = m_edges.GetSize();
size_t nT = m_triangles.GetSize();
for (size_t e = 0; e < nE; e++)
{
for (int f = 0; f < 2; f++)
{
if (!m_edges.GetHead()->GetData().m_triangles[f])
{
return false;
}
}
m_edges.Next();
}
for (size_t f = 0; f < nT; f++)
{
for (int e = 0; e < 3; e++)
{
int found = 0;
for (int k = 0; k < 2; k++)
{
if (m_triangles.GetHead()->GetData().m_edges[e]->GetData().m_triangles[k] == m_triangles.GetHead())
{
found++;
}
}
if (found != 1)
{
return false;
}
}
m_triangles.Next();
}
return true;
}
}
} // namespace VHACD

View File

@@ -23,301 +23,336 @@
#include <stdlib.h>
#include <string>
namespace VHACD {
namespace VHACD
{
Mesh::Mesh()
{
m_diag = 1.0;
m_diag = 1.0;
}
Mesh::~Mesh()
{
}
double Mesh::ComputeVolume() const
{
const size_t nV = GetNPoints();
const size_t nT = GetNTriangles();
if (nV == 0 || nT == 0) {
return 0.0;
}
const size_t nV = GetNPoints();
const size_t nT = GetNTriangles();
if (nV == 0 || nT == 0)
{
return 0.0;
}
Vec3<double> bary(0.0, 0.0, 0.0);
for (size_t v = 0; v < nV; v++) {
bary += GetPoint(v);
}
bary /= static_cast<double>(nV);
Vec3<double> bary(0.0, 0.0, 0.0);
for (size_t v = 0; v < nV; v++)
{
bary += GetPoint(v);
}
bary /= static_cast<double>(nV);
Vec3<double> ver0, ver1, ver2;
double totalVolume = 0.0;
for (int t = 0; t < nT; t++) {
const Vec3<int>& tri = GetTriangle(t);
ver0 = GetPoint(tri[0]);
ver1 = GetPoint(tri[1]);
ver2 = GetPoint(tri[2]);
totalVolume += ComputeVolume4(ver0, ver1, ver2, bary);
}
return totalVolume / 6.0;
Vec3<double> ver0, ver1, ver2;
double totalVolume = 0.0;
for (int t = 0; t < nT; t++)
{
const Vec3<int>& tri = GetTriangle(t);
ver0 = GetPoint(tri[0]);
ver1 = GetPoint(tri[1]);
ver2 = GetPoint(tri[2]);
totalVolume += ComputeVolume4(ver0, ver1, ver2, bary);
}
return totalVolume / 6.0;
}
void Mesh::ComputeConvexHull(const double* const pts,
const size_t nPts)
const size_t nPts)
{
ResizePoints(0);
ResizeTriangles(0);
btConvexHullComputer ch;
ch.compute(pts, 3 * sizeof(double), (int)nPts, -1.0, -1.0);
for (int v = 0; v < ch.vertices.size(); v++) {
AddPoint(Vec3<double>(ch.vertices[v].getX(), ch.vertices[v].getY(), ch.vertices[v].getZ()));
}
const int nt = ch.faces.size();
for (int t = 0; t < nt; ++t) {
const btConvexHullComputer::Edge* sourceEdge = &(ch.edges[ch.faces[t]]);
int a = sourceEdge->getSourceVertex();
int b = sourceEdge->getTargetVertex();
const btConvexHullComputer::Edge* edge = sourceEdge->getNextEdgeOfFace();
int c = edge->getTargetVertex();
while (c != a) {
AddTriangle(Vec3<int>(a, b, c));
edge = edge->getNextEdgeOfFace();
b = c;
c = edge->getTargetVertex();
}
}
ResizePoints(0);
ResizeTriangles(0);
btConvexHullComputer ch;
ch.compute(pts, 3 * sizeof(double), (int)nPts, -1.0, -1.0);
for (int v = 0; v < ch.vertices.size(); v++)
{
AddPoint(Vec3<double>(ch.vertices[v].getX(), ch.vertices[v].getY(), ch.vertices[v].getZ()));
}
const int nt = ch.faces.size();
for (int t = 0; t < nt; ++t)
{
const btConvexHullComputer::Edge* sourceEdge = &(ch.edges[ch.faces[t]]);
int a = sourceEdge->getSourceVertex();
int b = sourceEdge->getTargetVertex();
const btConvexHullComputer::Edge* edge = sourceEdge->getNextEdgeOfFace();
int c = edge->getTargetVertex();
while (c != a)
{
AddTriangle(Vec3<int>(a, b, c));
edge = edge->getNextEdgeOfFace();
b = c;
c = edge->getTargetVertex();
}
}
}
void Mesh::Clip(const Plane& plane,
SArray<Vec3<double> >& positivePart,
SArray<Vec3<double> >& negativePart) const
SArray<Vec3<double> >& positivePart,
SArray<Vec3<double> >& negativePart) const
{
const size_t nV = GetNPoints();
if (nV == 0) {
return;
}
double d;
for (size_t v = 0; v < nV; v++) {
const Vec3<double>& pt = GetPoint(v);
d = plane.m_a * pt[0] + plane.m_b * pt[1] + plane.m_c * pt[2] + plane.m_d;
if (d > 0.0) {
positivePart.PushBack(pt);
}
else if (d < 0.0) {
negativePart.PushBack(pt);
}
else {
positivePart.PushBack(pt);
negativePart.PushBack(pt);
}
}
const size_t nV = GetNPoints();
if (nV == 0)
{
return;
}
double d;
for (size_t v = 0; v < nV; v++)
{
const Vec3<double>& pt = GetPoint(v);
d = plane.m_a * pt[0] + plane.m_b * pt[1] + plane.m_c * pt[2] + plane.m_d;
if (d > 0.0)
{
positivePart.PushBack(pt);
}
else if (d < 0.0)
{
negativePart.PushBack(pt);
}
else
{
positivePart.PushBack(pt);
negativePart.PushBack(pt);
}
}
}
bool Mesh::IsInside(const Vec3<double>& pt) const
{
const size_t nV = GetNPoints();
const size_t nT = GetNTriangles();
if (nV == 0 || nT == 0) {
return false;
}
Vec3<double> ver0, ver1, ver2;
double volume;
for (int t = 0; t < nT; t++) {
const Vec3<int>& tri = GetTriangle(t);
ver0 = GetPoint(tri[0]);
ver1 = GetPoint(tri[1]);
ver2 = GetPoint(tri[2]);
volume = ComputeVolume4(ver0, ver1, ver2, pt);
if (volume < 0.0) {
return false;
}
}
return true;
const size_t nV = GetNPoints();
const size_t nT = GetNTriangles();
if (nV == 0 || nT == 0)
{
return false;
}
Vec3<double> ver0, ver1, ver2;
double volume;
for (int t = 0; t < nT; t++)
{
const Vec3<int>& tri = GetTriangle(t);
ver0 = GetPoint(tri[0]);
ver1 = GetPoint(tri[1]);
ver2 = GetPoint(tri[2]);
volume = ComputeVolume4(ver0, ver1, ver2, pt);
if (volume < 0.0)
{
return false;
}
}
return true;
}
double Mesh::ComputeDiagBB()
{
const size_t nPoints = GetNPoints();
if (nPoints == 0)
return 0.0;
Vec3<double> minBB = m_points[0];
Vec3<double> maxBB = m_points[0];
double x, y, z;
for (size_t v = 1; v < nPoints; v++) {
x = m_points[v][0];
y = m_points[v][1];
z = m_points[v][2];
if (x < minBB[0])
minBB[0] = x;
else if (x > maxBB[0])
maxBB[0] = x;
if (y < minBB[1])
minBB[1] = y;
else if (y > maxBB[1])
maxBB[1] = y;
if (z < minBB[2])
minBB[2] = z;
else if (z > maxBB[2])
maxBB[2] = z;
}
return (m_diag = (maxBB - minBB).GetNorm());
const size_t nPoints = GetNPoints();
if (nPoints == 0)
return 0.0;
Vec3<double> minBB = m_points[0];
Vec3<double> maxBB = m_points[0];
double x, y, z;
for (size_t v = 1; v < nPoints; v++)
{
x = m_points[v][0];
y = m_points[v][1];
z = m_points[v][2];
if (x < minBB[0])
minBB[0] = x;
else if (x > maxBB[0])
maxBB[0] = x;
if (y < minBB[1])
minBB[1] = y;
else if (y > maxBB[1])
maxBB[1] = y;
if (z < minBB[2])
minBB[2] = z;
else if (z > maxBB[2])
maxBB[2] = z;
}
return (m_diag = (maxBB - minBB).GetNorm());
}
#ifdef VHACD_DEBUG_MESH
bool Mesh::SaveVRML2(const std::string& fileName) const
{
std::ofstream fout(fileName.c_str());
if (fout.is_open()) {
const Material material;
std::ofstream fout(fileName.c_str());
if (fout.is_open())
{
const Material material;
if (SaveVRML2(fout, material)) {
fout.close();
return true;
}
return false;
}
return false;
if (SaveVRML2(fout, material))
{
fout.close();
return true;
}
return false;
}
return false;
}
bool Mesh::SaveVRML2(std::ofstream& fout, const Material& material) const
{
if (fout.is_open()) {
fout.setf(std::ios::fixed, std::ios::floatfield);
fout.setf(std::ios::showpoint);
fout.precision(6);
size_t nV = m_points.Size();
size_t nT = m_triangles.Size();
fout << "#VRML V2.0 utf8" << std::endl;
fout << "" << std::endl;
fout << "# Vertices: " << nV << std::endl;
fout << "# Triangles: " << nT << std::endl;
fout << "" << std::endl;
fout << "Group {" << std::endl;
fout << " children [" << std::endl;
fout << " Shape {" << std::endl;
fout << " appearance Appearance {" << std::endl;
fout << " material Material {" << std::endl;
fout << " diffuseColor " << material.m_diffuseColor[0] << " "
<< material.m_diffuseColor[1] << " "
<< material.m_diffuseColor[2] << std::endl;
fout << " ambientIntensity " << material.m_ambientIntensity << std::endl;
fout << " specularColor " << material.m_specularColor[0] << " "
<< material.m_specularColor[1] << " "
<< material.m_specularColor[2] << std::endl;
fout << " emissiveColor " << material.m_emissiveColor[0] << " "
<< material.m_emissiveColor[1] << " "
<< material.m_emissiveColor[2] << std::endl;
fout << " shininess " << material.m_shininess << std::endl;
fout << " transparency " << material.m_transparency << std::endl;
fout << " }" << std::endl;
fout << " }" << std::endl;
fout << " geometry IndexedFaceSet {" << std::endl;
fout << " ccw TRUE" << std::endl;
fout << " solid TRUE" << std::endl;
fout << " convex TRUE" << std::endl;
if (nV > 0) {
fout << " coord DEF co Coordinate {" << std::endl;
fout << " point [" << std::endl;
for (size_t v = 0; v < nV; v++) {
fout << " " << m_points[v][0] << " "
<< m_points[v][1] << " "
<< m_points[v][2] << "," << std::endl;
}
fout << " ]" << std::endl;
fout << " }" << std::endl;
}
if (nT > 0) {
fout << " coordIndex [ " << std::endl;
for (size_t f = 0; f < nT; f++) {
fout << " " << m_triangles[f][0] << ", "
<< m_triangles[f][1] << ", "
<< m_triangles[f][2] << ", -1," << std::endl;
}
fout << " ]" << std::endl;
}
fout << " }" << std::endl;
fout << " }" << std::endl;
fout << " ]" << std::endl;
fout << "}" << std::endl;
return true;
}
return false;
if (fout.is_open())
{
fout.setf(std::ios::fixed, std::ios::floatfield);
fout.setf(std::ios::showpoint);
fout.precision(6);
size_t nV = m_points.Size();
size_t nT = m_triangles.Size();
fout << "#VRML V2.0 utf8" << std::endl;
fout << "" << std::endl;
fout << "# Vertices: " << nV << std::endl;
fout << "# Triangles: " << nT << std::endl;
fout << "" << std::endl;
fout << "Group {" << std::endl;
fout << " children [" << std::endl;
fout << " Shape {" << std::endl;
fout << " appearance Appearance {" << std::endl;
fout << " material Material {" << std::endl;
fout << " diffuseColor " << material.m_diffuseColor[0] << " "
<< material.m_diffuseColor[1] << " "
<< material.m_diffuseColor[2] << std::endl;
fout << " ambientIntensity " << material.m_ambientIntensity << std::endl;
fout << " specularColor " << material.m_specularColor[0] << " "
<< material.m_specularColor[1] << " "
<< material.m_specularColor[2] << std::endl;
fout << " emissiveColor " << material.m_emissiveColor[0] << " "
<< material.m_emissiveColor[1] << " "
<< material.m_emissiveColor[2] << std::endl;
fout << " shininess " << material.m_shininess << std::endl;
fout << " transparency " << material.m_transparency << std::endl;
fout << " }" << std::endl;
fout << " }" << std::endl;
fout << " geometry IndexedFaceSet {" << std::endl;
fout << " ccw TRUE" << std::endl;
fout << " solid TRUE" << std::endl;
fout << " convex TRUE" << std::endl;
if (nV > 0)
{
fout << " coord DEF co Coordinate {" << std::endl;
fout << " point [" << std::endl;
for (size_t v = 0; v < nV; v++)
{
fout << " " << m_points[v][0] << " "
<< m_points[v][1] << " "
<< m_points[v][2] << "," << std::endl;
}
fout << " ]" << std::endl;
fout << " }" << std::endl;
}
if (nT > 0)
{
fout << " coordIndex [ " << std::endl;
for (size_t f = 0; f < nT; f++)
{
fout << " " << m_triangles[f][0] << ", "
<< m_triangles[f][1] << ", "
<< m_triangles[f][2] << ", -1," << std::endl;
}
fout << " ]" << std::endl;
}
fout << " }" << std::endl;
fout << " }" << std::endl;
fout << " ]" << std::endl;
fout << "}" << std::endl;
return true;
}
return false;
}
bool Mesh::SaveOFF(const std::string& fileName) const
{
std::ofstream fout(fileName.c_str());
if (fout.is_open()) {
size_t nV = m_points.Size();
size_t nT = m_triangles.Size();
fout << "OFF" << std::endl;
fout << nV << " " << nT << " " << 0 << std::endl;
for (size_t v = 0; v < nV; v++) {
fout << m_points[v][0] << " "
<< m_points[v][1] << " "
<< m_points[v][2] << std::endl;
}
for (size_t f = 0; f < nT; f++) {
fout << "3 " << m_triangles[f][0] << " "
<< m_triangles[f][1] << " "
<< m_triangles[f][2] << std::endl;
}
fout.close();
return true;
}
return false;
std::ofstream fout(fileName.c_str());
if (fout.is_open())
{
size_t nV = m_points.Size();
size_t nT = m_triangles.Size();
fout << "OFF" << std::endl;
fout << nV << " " << nT << " " << 0 << std::endl;
for (size_t v = 0; v < nV; v++)
{
fout << m_points[v][0] << " "
<< m_points[v][1] << " "
<< m_points[v][2] << std::endl;
}
for (size_t f = 0; f < nT; f++)
{
fout << "3 " << m_triangles[f][0] << " "
<< m_triangles[f][1] << " "
<< m_triangles[f][2] << std::endl;
}
fout.close();
return true;
}
return false;
}
bool Mesh::LoadOFF(const std::string& fileName, bool invert)
{
FILE* fid = fopen(fileName.c_str(), "r");
if (fid) {
const std::string strOFF("OFF");
char temp[1024];
fscanf(fid, "%s", temp);
if (std::string(temp) != strOFF) {
fclose(fid);
return false;
}
else {
int nv = 0;
int nf = 0;
int ne = 0;
fscanf(fid, "%i", &nv);
fscanf(fid, "%i", &nf);
fscanf(fid, "%i", &ne);
m_points.Resize(nv);
m_triangles.Resize(nf);
Vec3<double> coord;
float x, y, z;
for (int p = 0; p < nv; p++) {
fscanf(fid, "%f", &x);
fscanf(fid, "%f", &y);
fscanf(fid, "%f", &z);
m_points[p][0] = x;
m_points[p][1] = y;
m_points[p][2] = z;
}
int i, j, k, s;
for (int t = 0; t < nf; ++t) {
fscanf(fid, "%i", &s);
if (s == 3) {
fscanf(fid, "%i", &i);
fscanf(fid, "%i", &j);
fscanf(fid, "%i", &k);
m_triangles[t][0] = i;
if (invert) {
m_triangles[t][1] = k;
m_triangles[t][2] = j;
}
else {
m_triangles[t][1] = j;
m_triangles[t][2] = k;
}
}
else // Fix me: support only triangular meshes
{
for (int h = 0; h < s; ++h)
fscanf(fid, "%i", &s);
}
}
fclose(fid);
}
}
else {
return false;
}
return true;
}
#endif // VHACD_DEBUG_MESH
FILE* fid = fopen(fileName.c_str(), "r");
if (fid)
{
const std::string strOFF("OFF");
char temp[1024];
fscanf(fid, "%s", temp);
if (std::string(temp) != strOFF)
{
fclose(fid);
return false;
}
else
{
int nv = 0;
int nf = 0;
int ne = 0;
fscanf(fid, "%i", &nv);
fscanf(fid, "%i", &nf);
fscanf(fid, "%i", &ne);
m_points.Resize(nv);
m_triangles.Resize(nf);
Vec3<double> coord;
float x, y, z;
for (int p = 0; p < nv; p++)
{
fscanf(fid, "%f", &x);
fscanf(fid, "%f", &y);
fscanf(fid, "%f", &z);
m_points[p][0] = x;
m_points[p][1] = y;
m_points[p][2] = z;
}
int i, j, k, s;
for (int t = 0; t < nf; ++t)
{
fscanf(fid, "%i", &s);
if (s == 3)
{
fscanf(fid, "%i", &i);
fscanf(fid, "%i", &j);
fscanf(fid, "%i", &k);
m_triangles[t][0] = i;
if (invert)
{
m_triangles[t][1] = k;
m_triangles[t][2] = j;
}
else
{
m_triangles[t][1] = j;
m_triangles[t][2] = k;
}
}
else // Fix me: support only triangular meshes
{
for (int h = 0; h < s; ++h)
fscanf(fid, "%i", &s);
}
}
fclose(fid);
}
}
else
{
return false;
}
return true;
}
#endif // VHACD_DEBUG_MESH
} // namespace VHACD

File diff suppressed because it is too large Load Diff

View File

@@ -27,24 +27,26 @@
#include <CL/cl.h>
#endif
class OCLHelper {
class OCLHelper
{
public:
OCLHelper(void){};
~OCLHelper(void){};
bool InitPlatform(const unsigned int platformIndex = 0);
bool InitDevice(const unsigned int deviceIndex);
bool GetPlatformsInfo(std::vector<std::string>& info, const std::string& indentation);
bool GetDevicesInfo(std::vector<std::string>& info, const std::string& indentation);
cl_platform_id* GetPlatform() { return &m_platform; }
const cl_platform_id* GetPlatform() const { return &m_platform; }
cl_device_id* GetDevice() { return &m_device; }
const cl_device_id* GetDevice() const { return &m_device; }
OCLHelper(void){};
~OCLHelper(void){};
bool InitPlatform(const unsigned int platformIndex = 0);
bool InitDevice(const unsigned int deviceIndex);
bool GetPlatformsInfo(std::vector<std::string>& info, const std::string& indentation);
bool GetDevicesInfo(std::vector<std::string>& info, const std::string& indentation);
cl_platform_id* GetPlatform() { return &m_platform; }
const cl_platform_id* GetPlatform() const { return &m_platform; }
cl_device_id* GetDevice() { return &m_device; }
const cl_device_id* GetDevice() const { return &m_device; }
private:
cl_platform_id m_platform;
cl_device_id m_device;
cl_int m_lastError;
cl_platform_id m_platform;
cl_device_id m_device;
cl_int m_lastError;
};
#endif // OCL_HELPER_H
#endif // OCL_HELPER_H
#endif //OPENCL_FOUND
#endif //OPENCL_FOUND

File diff suppressed because it is too large Load Diff

View File

@@ -20,310 +20,349 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
bool OCLHelper::InitPlatform(const unsigned int platformIndex)
{
cl_uint numPlatforms;
m_lastError = clGetPlatformIDs(1, NULL, &numPlatforms);
if (m_lastError != CL_SUCCESS || platformIndex >= numPlatforms)
return false;
cl_uint numPlatforms;
m_lastError = clGetPlatformIDs(1, NULL, &numPlatforms);
if (m_lastError != CL_SUCCESS || platformIndex >= numPlatforms)
return false;
cl_platform_id* platforms = new cl_platform_id[numPlatforms];
m_lastError = clGetPlatformIDs(numPlatforms, platforms, NULL);
if (m_lastError != CL_SUCCESS) {
delete[] platforms;
return false;
}
cl_platform_id* platforms = new cl_platform_id[numPlatforms];
m_lastError = clGetPlatformIDs(numPlatforms, platforms, NULL);
if (m_lastError != CL_SUCCESS)
{
delete[] platforms;
return false;
}
m_platform = platforms[platformIndex];
delete[] platforms;
return true;
m_platform = platforms[platformIndex];
delete[] platforms;
return true;
}
bool OCLHelper::GetPlatformsInfo(std::vector<std::string>& info, const std::string& indentation)
{
const char* platformInfoParameters[] = { "CL_PLATFORM_NAME",
"CL_PLATFORM_VENDOR",
"CL_PLATFORM_VERSION",
"CL_PLATFORM_PROFILE",
"CL_PLATFORM_EXTENSIONS" };
const char* platformInfoParameters[] = {"CL_PLATFORM_NAME",
"CL_PLATFORM_VENDOR",
"CL_PLATFORM_VERSION",
"CL_PLATFORM_PROFILE",
"CL_PLATFORM_EXTENSIONS"};
cl_uint numPlatforms;
m_lastError = clGetPlatformIDs(1, NULL, &numPlatforms);
if (m_lastError != CL_SUCCESS)
return false;
cl_uint numPlatforms;
m_lastError = clGetPlatformIDs(1, NULL, &numPlatforms);
if (m_lastError != CL_SUCCESS)
return false;
cl_platform_id* platforms = new cl_platform_id[numPlatforms];
m_lastError = clGetPlatformIDs(numPlatforms, platforms, NULL);
if (m_lastError != CL_SUCCESS) {
delete[] platforms;
return false;
}
cl_platform_id* platforms = new cl_platform_id[numPlatforms];
m_lastError = clGetPlatformIDs(numPlatforms, platforms, NULL);
if (m_lastError != CL_SUCCESS)
{
delete[] platforms;
return false;
}
size_t bufferSize = 4096;
char* buffer = new char[bufferSize];
size_t size;
info.resize(numPlatforms);
for (cl_uint i = 0; i < numPlatforms; ++i) {
for (int j = CL_PLATFORM_PROFILE; j <= CL_PLATFORM_EXTENSIONS; ++j) {
info[i] += indentation + platformInfoParameters[j - CL_PLATFORM_PROFILE] + std::string(": ");
m_lastError = clGetPlatformInfo(platforms[i], j, 0, NULL, &size);
if (m_lastError != CL_SUCCESS) {
delete[] buffer;
delete[] platforms;
return false;
}
if (bufferSize < size) {
delete[] buffer;
bufferSize = size;
buffer = new char[bufferSize];
}
m_lastError = clGetPlatformInfo(platforms[i], j, size, buffer, NULL);
if (m_lastError != CL_SUCCESS) {
delete[] buffer;
delete[] platforms;
return false;
}
info[i] += buffer + std::string("\n");
}
}
delete[] platforms;
delete[] buffer;
return true;
size_t bufferSize = 4096;
char* buffer = new char[bufferSize];
size_t size;
info.resize(numPlatforms);
for (cl_uint i = 0; i < numPlatforms; ++i)
{
for (int j = CL_PLATFORM_PROFILE; j <= CL_PLATFORM_EXTENSIONS; ++j)
{
info[i] += indentation + platformInfoParameters[j - CL_PLATFORM_PROFILE] + std::string(": ");
m_lastError = clGetPlatformInfo(platforms[i], j, 0, NULL, &size);
if (m_lastError != CL_SUCCESS)
{
delete[] buffer;
delete[] platforms;
return false;
}
if (bufferSize < size)
{
delete[] buffer;
bufferSize = size;
buffer = new char[bufferSize];
}
m_lastError = clGetPlatformInfo(platforms[i], j, size, buffer, NULL);
if (m_lastError != CL_SUCCESS)
{
delete[] buffer;
delete[] platforms;
return false;
}
info[i] += buffer + std::string("\n");
}
}
delete[] platforms;
delete[] buffer;
return true;
}
bool OCLHelper::InitDevice(const unsigned int deviceIndex)
{
cl_uint numDevices;
m_lastError = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_ALL, 0, NULL, &numDevices);
if (m_lastError != CL_SUCCESS || deviceIndex >= numDevices)
return false;
cl_uint numDevices;
m_lastError = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_ALL, 0, NULL, &numDevices);
if (m_lastError != CL_SUCCESS || deviceIndex >= numDevices)
return false;
cl_device_id* devices = new cl_device_id[numDevices];
m_lastError = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_ALL, numDevices, devices, NULL);
if (m_lastError != CL_SUCCESS) {
delete[] devices;
return false;
}
m_device = devices[deviceIndex];
delete[] devices;
return true;
cl_device_id* devices = new cl_device_id[numDevices];
m_lastError = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_ALL, numDevices, devices, NULL);
if (m_lastError != CL_SUCCESS)
{
delete[] devices;
return false;
}
m_device = devices[deviceIndex];
delete[] devices;
return true;
}
bool OCLHelper::GetDevicesInfo(std::vector<std::string>& info, const std::string& indentation)
{
enum {
DATA_TYPE_CL_UINT,
DATA_TYPE_CL_BOOL,
DATA_TYPE_STRING,
DATA_TYPE_CL_ULONG,
DATA_TYPE_CL_DEVICE_FP_CONFIG,
DATA_TYPE_CL_DEVICE_EXEC_CAPABILITIES,
DATA_TYPE_CL_DEVICE_MEM_CACHE_TYPE,
DATA_TYPE_CL_DEVICE_MEM_LOCAL_TYPE,
DATA_TYPE_CL_DEVICE_CMD_QUEUE_PROP,
DATA_TYPE_CL_DEVICE_TYPE,
DATA_TYPE_SIZE_T,
DATA_TYPE_SIZE_T_3,
};
typedef struct
{
cl_device_info id;
const char* name;
int type;
} DeviceInfoParam;
const int numDeviceInfoParameters = 49;
const DeviceInfoParam deviceInfoParameters[numDeviceInfoParameters] = {
{ CL_DEVICE_NAME, "CL_DEVICE_NAME", DATA_TYPE_STRING },
{ CL_DEVICE_PROFILE, "CL_DEVICE_PROFILE", DATA_TYPE_STRING },
{ CL_DEVICE_VENDOR, "CL_DEVICE_VENDOR", DATA_TYPE_STRING },
{ CL_DEVICE_VERSION, "CL_DEVICE_VERSION", DATA_TYPE_STRING },
{ CL_DRIVER_VERSION, "CL_DRIVER_VERSION", DATA_TYPE_STRING },
{ CL_DEVICE_EXTENSIONS, "CL_DEVICE_EXTENSIONS", DATA_TYPE_STRING },
{ CL_DEVICE_VERSION, "CL_DEVICE_VERSION", DATA_TYPE_STRING },
{ CL_DEVICE_ADDRESS_BITS, "CL_DEVICE_ADDRESS_BITS", DATA_TYPE_CL_UINT },
{ CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, "CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE", DATA_TYPE_CL_UINT },
{ CL_DEVICE_MAX_CLOCK_FREQUENCY, "CL_DEVICE_MAX_CLOCK_FREQUENCY", DATA_TYPE_CL_UINT },
{ CL_DEVICE_MAX_COMPUTE_UNITS, "CL_DEVICE_MAX_COMPUTE_UNITS", DATA_TYPE_CL_UINT },
{ CL_DEVICE_MAX_CONSTANT_ARGS, "CL_DEVICE_MAX_CONSTANT_ARGS", DATA_TYPE_CL_UINT },
{ CL_DEVICE_MAX_READ_IMAGE_ARGS, "CL_DEVICE_MAX_READ_IMAGE_ARGS", DATA_TYPE_CL_UINT },
{ CL_DEVICE_MAX_SAMPLERS, "CL_DEVICE_MAX_SAMPLERS", DATA_TYPE_CL_UINT },
{ CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, "CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS", DATA_TYPE_CL_UINT },
{ CL_DEVICE_MAX_WRITE_IMAGE_ARGS, "CL_DEVICE_MAX_WRITE_IMAGE_ARGS", DATA_TYPE_CL_UINT },
{ CL_DEVICE_MEM_BASE_ADDR_ALIGN, "CL_DEVICE_MEM_BASE_ADDR_ALIGN", DATA_TYPE_CL_UINT },
{ CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, "CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE", DATA_TYPE_CL_UINT },
{ CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, "CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR", DATA_TYPE_CL_UINT },
{ CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, "CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT", DATA_TYPE_CL_UINT },
{ CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, "CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT", DATA_TYPE_CL_UINT },
{ CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, "CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG", DATA_TYPE_CL_UINT },
{ CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, "CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT", DATA_TYPE_CL_UINT },
{ CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, "CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE", DATA_TYPE_CL_UINT },
{ CL_DEVICE_VENDOR_ID, "CL_DEVICE_VENDOR_ID", DATA_TYPE_CL_UINT },
{ CL_DEVICE_AVAILABLE, "CL_DEVICE_AVAILABLE", DATA_TYPE_CL_BOOL },
{ CL_DEVICE_COMPILER_AVAILABLE, "CL_DEVICE_COMPILER_AVAILABLE", DATA_TYPE_CL_BOOL },
{ CL_DEVICE_ENDIAN_LITTLE, "CL_DEVICE_ENDIAN_LITTLE", DATA_TYPE_CL_BOOL },
{ CL_DEVICE_ERROR_CORRECTION_SUPPORT, "CL_DEVICE_ERROR_CORRECTION_SUPPORT", DATA_TYPE_CL_BOOL },
{ CL_DEVICE_IMAGE_SUPPORT, "CL_DEVICE_IMAGE_SUPPORT", DATA_TYPE_CL_BOOL },
{ CL_DEVICE_EXECUTION_CAPABILITIES, "CL_DEVICE_EXECUTION_CAPABILITIES", DATA_TYPE_CL_DEVICE_EXEC_CAPABILITIES },
{ CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, "CL_DEVICE_GLOBAL_MEM_CACHE_SIZE", DATA_TYPE_CL_ULONG },
{ CL_DEVICE_GLOBAL_MEM_SIZE, "CL_DEVICE_GLOBAL_MEM_SIZE", DATA_TYPE_CL_ULONG },
{ CL_DEVICE_LOCAL_MEM_SIZE, "CL_DEVICE_LOCAL_MEM_SIZE", DATA_TYPE_CL_ULONG },
{ CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, "CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE", DATA_TYPE_CL_ULONG },
{ CL_DEVICE_MAX_MEM_ALLOC_SIZE, "CL_DEVICE_MAX_MEM_ALLOC_SIZE", DATA_TYPE_CL_ULONG },
{ CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, "CL_DEVICE_GLOBAL_MEM_CACHE_TYPE", DATA_TYPE_CL_DEVICE_MEM_CACHE_TYPE },
{ CL_DEVICE_IMAGE2D_MAX_HEIGHT, "CL_DEVICE_IMAGE2D_MAX_HEIGHT", DATA_TYPE_SIZE_T },
{ CL_DEVICE_IMAGE2D_MAX_WIDTH, "CL_DEVICE_IMAGE2D_MAX_WIDTH", DATA_TYPE_SIZE_T },
{ CL_DEVICE_IMAGE3D_MAX_DEPTH, "CL_DEVICE_IMAGE3D_MAX_DEPTH", DATA_TYPE_SIZE_T },
{ CL_DEVICE_IMAGE3D_MAX_HEIGHT, "CL_DEVICE_IMAGE3D_MAX_HEIGHT", DATA_TYPE_SIZE_T },
{ CL_DEVICE_IMAGE3D_MAX_WIDTH, "CL_DEVICE_IMAGE3D_MAX_WIDTH", DATA_TYPE_SIZE_T },
{ CL_DEVICE_MAX_PARAMETER_SIZE, "CL_DEVICE_MAX_PARAMETER_SIZE", DATA_TYPE_SIZE_T },
{ CL_DEVICE_MAX_WORK_GROUP_SIZE, "CL_DEVICE_MAX_WORK_GROUP_SIZE", DATA_TYPE_SIZE_T },
{ CL_DEVICE_PROFILING_TIMER_RESOLUTION, "CL_DEVICE_PROFILING_TIMER_RESOLUTION", DATA_TYPE_SIZE_T },
{ CL_DEVICE_QUEUE_PROPERTIES, "CL_DEVICE_QUEUE_PROPERTIES", DATA_TYPE_CL_DEVICE_CMD_QUEUE_PROP },
{ CL_DEVICE_TYPE, "CL_DEVICE_TYPE", DATA_TYPE_CL_DEVICE_TYPE },
{ CL_DEVICE_LOCAL_MEM_TYPE, "CL_DEVICE_LOCAL_MEM_TYPE", DATA_TYPE_CL_DEVICE_MEM_LOCAL_TYPE },
{ CL_DEVICE_MAX_WORK_ITEM_SIZES, "CL_DEVICE_MAX_WORK_ITEM_SIZES", DATA_TYPE_SIZE_T_3 }
// { CL_DEVICE_DOUBLE_FP_CONFIG, "CL_DEVICE_DOUBLE_FP_CONFIG", DATA_TYPE_CL_DEVICE_FP_CONFIG },
//
};
cl_uint numDevices;
m_lastError = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_ALL, 0, NULL, &numDevices);
if (m_lastError != CL_SUCCESS)
return false;
enum
{
DATA_TYPE_CL_UINT,
DATA_TYPE_CL_BOOL,
DATA_TYPE_STRING,
DATA_TYPE_CL_ULONG,
DATA_TYPE_CL_DEVICE_FP_CONFIG,
DATA_TYPE_CL_DEVICE_EXEC_CAPABILITIES,
DATA_TYPE_CL_DEVICE_MEM_CACHE_TYPE,
DATA_TYPE_CL_DEVICE_MEM_LOCAL_TYPE,
DATA_TYPE_CL_DEVICE_CMD_QUEUE_PROP,
DATA_TYPE_CL_DEVICE_TYPE,
DATA_TYPE_SIZE_T,
DATA_TYPE_SIZE_T_3,
};
typedef struct
{
cl_device_info id;
const char* name;
int type;
} DeviceInfoParam;
const int numDeviceInfoParameters = 49;
const DeviceInfoParam deviceInfoParameters[numDeviceInfoParameters] = {
{CL_DEVICE_NAME, "CL_DEVICE_NAME", DATA_TYPE_STRING},
{CL_DEVICE_PROFILE, "CL_DEVICE_PROFILE", DATA_TYPE_STRING},
{CL_DEVICE_VENDOR, "CL_DEVICE_VENDOR", DATA_TYPE_STRING},
{CL_DEVICE_VERSION, "CL_DEVICE_VERSION", DATA_TYPE_STRING},
{CL_DRIVER_VERSION, "CL_DRIVER_VERSION", DATA_TYPE_STRING},
{CL_DEVICE_EXTENSIONS, "CL_DEVICE_EXTENSIONS", DATA_TYPE_STRING},
{CL_DEVICE_VERSION, "CL_DEVICE_VERSION", DATA_TYPE_STRING},
{CL_DEVICE_ADDRESS_BITS, "CL_DEVICE_ADDRESS_BITS", DATA_TYPE_CL_UINT},
{CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, "CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE", DATA_TYPE_CL_UINT},
{CL_DEVICE_MAX_CLOCK_FREQUENCY, "CL_DEVICE_MAX_CLOCK_FREQUENCY", DATA_TYPE_CL_UINT},
{CL_DEVICE_MAX_COMPUTE_UNITS, "CL_DEVICE_MAX_COMPUTE_UNITS", DATA_TYPE_CL_UINT},
{CL_DEVICE_MAX_CONSTANT_ARGS, "CL_DEVICE_MAX_CONSTANT_ARGS", DATA_TYPE_CL_UINT},
{CL_DEVICE_MAX_READ_IMAGE_ARGS, "CL_DEVICE_MAX_READ_IMAGE_ARGS", DATA_TYPE_CL_UINT},
{CL_DEVICE_MAX_SAMPLERS, "CL_DEVICE_MAX_SAMPLERS", DATA_TYPE_CL_UINT},
{CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, "CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS", DATA_TYPE_CL_UINT},
{CL_DEVICE_MAX_WRITE_IMAGE_ARGS, "CL_DEVICE_MAX_WRITE_IMAGE_ARGS", DATA_TYPE_CL_UINT},
{CL_DEVICE_MEM_BASE_ADDR_ALIGN, "CL_DEVICE_MEM_BASE_ADDR_ALIGN", DATA_TYPE_CL_UINT},
{CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, "CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE", DATA_TYPE_CL_UINT},
{CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, "CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR", DATA_TYPE_CL_UINT},
{CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, "CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT", DATA_TYPE_CL_UINT},
{CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, "CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT", DATA_TYPE_CL_UINT},
{CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, "CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG", DATA_TYPE_CL_UINT},
{CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, "CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT", DATA_TYPE_CL_UINT},
{CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, "CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE", DATA_TYPE_CL_UINT},
{CL_DEVICE_VENDOR_ID, "CL_DEVICE_VENDOR_ID", DATA_TYPE_CL_UINT},
{CL_DEVICE_AVAILABLE, "CL_DEVICE_AVAILABLE", DATA_TYPE_CL_BOOL},
{CL_DEVICE_COMPILER_AVAILABLE, "CL_DEVICE_COMPILER_AVAILABLE", DATA_TYPE_CL_BOOL},
{CL_DEVICE_ENDIAN_LITTLE, "CL_DEVICE_ENDIAN_LITTLE", DATA_TYPE_CL_BOOL},
{CL_DEVICE_ERROR_CORRECTION_SUPPORT, "CL_DEVICE_ERROR_CORRECTION_SUPPORT", DATA_TYPE_CL_BOOL},
{CL_DEVICE_IMAGE_SUPPORT, "CL_DEVICE_IMAGE_SUPPORT", DATA_TYPE_CL_BOOL},
{CL_DEVICE_EXECUTION_CAPABILITIES, "CL_DEVICE_EXECUTION_CAPABILITIES", DATA_TYPE_CL_DEVICE_EXEC_CAPABILITIES},
{CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, "CL_DEVICE_GLOBAL_MEM_CACHE_SIZE", DATA_TYPE_CL_ULONG},
{CL_DEVICE_GLOBAL_MEM_SIZE, "CL_DEVICE_GLOBAL_MEM_SIZE", DATA_TYPE_CL_ULONG},
{CL_DEVICE_LOCAL_MEM_SIZE, "CL_DEVICE_LOCAL_MEM_SIZE", DATA_TYPE_CL_ULONG},
{CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, "CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE", DATA_TYPE_CL_ULONG},
{CL_DEVICE_MAX_MEM_ALLOC_SIZE, "CL_DEVICE_MAX_MEM_ALLOC_SIZE", DATA_TYPE_CL_ULONG},
{CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, "CL_DEVICE_GLOBAL_MEM_CACHE_TYPE", DATA_TYPE_CL_DEVICE_MEM_CACHE_TYPE},
{CL_DEVICE_IMAGE2D_MAX_HEIGHT, "CL_DEVICE_IMAGE2D_MAX_HEIGHT", DATA_TYPE_SIZE_T},
{CL_DEVICE_IMAGE2D_MAX_WIDTH, "CL_DEVICE_IMAGE2D_MAX_WIDTH", DATA_TYPE_SIZE_T},
{CL_DEVICE_IMAGE3D_MAX_DEPTH, "CL_DEVICE_IMAGE3D_MAX_DEPTH", DATA_TYPE_SIZE_T},
{CL_DEVICE_IMAGE3D_MAX_HEIGHT, "CL_DEVICE_IMAGE3D_MAX_HEIGHT", DATA_TYPE_SIZE_T},
{CL_DEVICE_IMAGE3D_MAX_WIDTH, "CL_DEVICE_IMAGE3D_MAX_WIDTH", DATA_TYPE_SIZE_T},
{CL_DEVICE_MAX_PARAMETER_SIZE, "CL_DEVICE_MAX_PARAMETER_SIZE", DATA_TYPE_SIZE_T},
{CL_DEVICE_MAX_WORK_GROUP_SIZE, "CL_DEVICE_MAX_WORK_GROUP_SIZE", DATA_TYPE_SIZE_T},
{CL_DEVICE_PROFILING_TIMER_RESOLUTION, "CL_DEVICE_PROFILING_TIMER_RESOLUTION", DATA_TYPE_SIZE_T},
{CL_DEVICE_QUEUE_PROPERTIES, "CL_DEVICE_QUEUE_PROPERTIES", DATA_TYPE_CL_DEVICE_CMD_QUEUE_PROP},
{CL_DEVICE_TYPE, "CL_DEVICE_TYPE", DATA_TYPE_CL_DEVICE_TYPE},
{CL_DEVICE_LOCAL_MEM_TYPE, "CL_DEVICE_LOCAL_MEM_TYPE", DATA_TYPE_CL_DEVICE_MEM_LOCAL_TYPE},
{CL_DEVICE_MAX_WORK_ITEM_SIZES, "CL_DEVICE_MAX_WORK_ITEM_SIZES", DATA_TYPE_SIZE_T_3}
// { CL_DEVICE_DOUBLE_FP_CONFIG, "CL_DEVICE_DOUBLE_FP_CONFIG", DATA_TYPE_CL_DEVICE_FP_CONFIG },
//
};
cl_uint numDevices;
m_lastError = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_ALL, 0, NULL, &numDevices);
if (m_lastError != CL_SUCCESS)
return false;
cl_device_id* devices = new cl_device_id[numDevices];
m_lastError = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_ALL, numDevices, devices, NULL);
if (m_lastError != CL_SUCCESS) {
delete[] devices;
return false;
}
size_t bufferSize = 4096;
char* buffer = new char[bufferSize];
size_t size;
info.resize(numDevices);
cl_device_id* devices = new cl_device_id[numDevices];
m_lastError = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_ALL, numDevices, devices, NULL);
if (m_lastError != CL_SUCCESS)
{
delete[] devices;
return false;
}
size_t bufferSize = 4096;
char* buffer = new char[bufferSize];
size_t size;
info.resize(numDevices);
for (cl_uint i = 0; i < numDevices; ++i) {
for (int j = 0; j < numDeviceInfoParameters; ++j) {
const DeviceInfoParam& infoParam = deviceInfoParameters[j];
info[i] += indentation + infoParam.name + std::string(": ");
for (cl_uint i = 0; i < numDevices; ++i)
{
for (int j = 0; j < numDeviceInfoParameters; ++j)
{
const DeviceInfoParam& infoParam = deviceInfoParameters[j];
info[i] += indentation + infoParam.name + std::string(": ");
if (infoParam.type == DATA_TYPE_STRING) {
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, 0, NULL, &size);
if (m_lastError == CL_SUCCESS) {
if (bufferSize < size) {
delete[] buffer;
bufferSize = size;
buffer = new char[bufferSize];
}
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, size, buffer, NULL);
if (m_lastError != CL_SUCCESS) {
delete[] devices;
delete[] buffer;
return false;
}
info[i] += buffer + std::string("\n");
}
}
else if (infoParam.type == DATA_TYPE_CL_UINT) {
cl_uint value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_uint), &value, &size);
if (m_lastError == CL_SUCCESS) {
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_BOOL) {
cl_bool value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_bool), &value, &size);
if (m_lastError == CL_SUCCESS) {
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_ULONG) {
cl_ulong value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_ulong), &value, &size);
if (m_lastError == CL_SUCCESS) {
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_DEVICE_FP_CONFIG) {
cl_device_fp_config value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_device_fp_config), &value, &size);
if (m_lastError == CL_SUCCESS) {
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_DEVICE_EXEC_CAPABILITIES) {
cl_device_exec_capabilities value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_device_exec_capabilities), &value, &size);
if (m_lastError == CL_SUCCESS) {
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_DEVICE_MEM_CACHE_TYPE) {
cl_device_mem_cache_type value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_device_mem_cache_type), &value, &size);
if (m_lastError == CL_SUCCESS) {
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_DEVICE_MEM_LOCAL_TYPE) {
cl_device_local_mem_type value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_device_local_mem_type), &value, &size);
if (m_lastError == CL_SUCCESS) {
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_DEVICE_CMD_QUEUE_PROP) {
cl_command_queue_properties value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_command_queue_properties), &value, &size);
if (m_lastError == CL_SUCCESS) {
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_DEVICE_TYPE) {
cl_device_type value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_device_type), &value, &size);
if (m_lastError == CL_SUCCESS) {
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_SIZE_T) {
size_t value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(size_t), &value, &size);
if (m_lastError == CL_SUCCESS) {
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_SIZE_T_3) {
size_t value[3];
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, 3 * sizeof(size_t), &value, &size);
if (m_lastError == CL_SUCCESS) {
std::ostringstream svalue;
svalue << "(" << value[0] << ", " << value[1] << ", " << value[2] << ")";
info[i] += svalue.str() + "\n";
}
}
else {
assert(0);
}
}
}
delete[] devices;
delete[] buffer;
return true;
if (infoParam.type == DATA_TYPE_STRING)
{
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, 0, NULL, &size);
if (m_lastError == CL_SUCCESS)
{
if (bufferSize < size)
{
delete[] buffer;
bufferSize = size;
buffer = new char[bufferSize];
}
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, size, buffer, NULL);
if (m_lastError != CL_SUCCESS)
{
delete[] devices;
delete[] buffer;
return false;
}
info[i] += buffer + std::string("\n");
}
}
else if (infoParam.type == DATA_TYPE_CL_UINT)
{
cl_uint value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_uint), &value, &size);
if (m_lastError == CL_SUCCESS)
{
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_BOOL)
{
cl_bool value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_bool), &value, &size);
if (m_lastError == CL_SUCCESS)
{
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_ULONG)
{
cl_ulong value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_ulong), &value, &size);
if (m_lastError == CL_SUCCESS)
{
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_DEVICE_FP_CONFIG)
{
cl_device_fp_config value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_device_fp_config), &value, &size);
if (m_lastError == CL_SUCCESS)
{
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_DEVICE_EXEC_CAPABILITIES)
{
cl_device_exec_capabilities value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_device_exec_capabilities), &value, &size);
if (m_lastError == CL_SUCCESS)
{
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_DEVICE_MEM_CACHE_TYPE)
{
cl_device_mem_cache_type value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_device_mem_cache_type), &value, &size);
if (m_lastError == CL_SUCCESS)
{
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_DEVICE_MEM_LOCAL_TYPE)
{
cl_device_local_mem_type value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_device_local_mem_type), &value, &size);
if (m_lastError == CL_SUCCESS)
{
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_DEVICE_CMD_QUEUE_PROP)
{
cl_command_queue_properties value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_command_queue_properties), &value, &size);
if (m_lastError == CL_SUCCESS)
{
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_CL_DEVICE_TYPE)
{
cl_device_type value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(cl_device_type), &value, &size);
if (m_lastError == CL_SUCCESS)
{
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_SIZE_T)
{
size_t value;
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, sizeof(size_t), &value, &size);
if (m_lastError == CL_SUCCESS)
{
std::ostringstream svalue;
svalue << value;
info[i] += svalue.str() + "\n";
}
}
else if (infoParam.type == DATA_TYPE_SIZE_T_3)
{
size_t value[3];
m_lastError = clGetDeviceInfo(devices[i], infoParam.id, 3 * sizeof(size_t), &value, &size);
if (m_lastError == CL_SUCCESS)
{
std::ostringstream svalue;
svalue << "(" << value[0] << ", " << value[1] << ", " << value[2] << ")";
info[i] += svalue.str() + "\n";
}
}
else
{
assert(0);
}
}
}
delete[] devices;
delete[] buffer;
return true;
}
#endif // OPENCL_FOUND
#endif // OPENCL_FOUND