add bullet

This commit is contained in:
gmueller
2011-01-18 21:02:48 +01:00
parent 21985a4ea4
commit bf00db6c68
251 changed files with 59131 additions and 3 deletions

View File

@ -0,0 +1,236 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef AABB_UTIL2
#define AABB_UTIL2
#include "btTransform.h"
#include "btVector3.h"
#include "btMinMax.h"
SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin,
btVector3& aabbMax,
const btVector3& expansionMin,
const btVector3& expansionMax)
{
aabbMin = aabbMin + expansionMin;
aabbMax = aabbMax + expansionMax;
}
/// conservative test for overlap between two aabbs
SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1,
const btVector3 &point)
{
bool overlap = true;
overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap;
overlap = (aabbMin1.getZ() > point.getZ() || aabbMax1.getZ() < point.getZ()) ? false : overlap;
overlap = (aabbMin1.getY() > point.getY() || aabbMax1.getY() < point.getY()) ? false : overlap;
return overlap;
}
/// conservative test for overlap between two aabbs
SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1,
const btVector3 &aabbMin2, const btVector3 &aabbMax2)
{
bool overlap = true;
overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap;
overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap;
return overlap;
}
/// conservative test for overlap between triangle and aabb
SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3 *vertices,
const btVector3 &aabbMin, const btVector3 &aabbMax)
{
const btVector3 &p1 = vertices[0];
const btVector3 &p2 = vertices[1];
const btVector3 &p3 = vertices[2];
if (btMin(btMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
if (btMax(btMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
if (btMin(btMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
if (btMax(btMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
if (btMin(btMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
if (btMax(btMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
return true;
}
SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent)
{
return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
(p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
(p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
(p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
(p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
(p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
}
SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
const btVector3& rayInvDirection,
const unsigned int raySign[3],
const btVector3 bounds[2],
btScalar& tmin,
btScalar lambda_min,
btScalar lambda_max)
{
btScalar tmax, tymin, tymax, tzmin, tzmax;
tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
if ( (tmin > tymax) || (tymin > tmax) )
return false;
if (tymin > tmin)
tmin = tymin;
if (tymax < tmax)
tmax = tymax;
tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
if ( (tmin > tzmax) || (tzmin > tmax) )
return false;
if (tzmin > tmin)
tmin = tzmin;
if (tzmax < tmax)
tmax = tzmax;
return ( (tmin < lambda_max) && (tmax > lambda_min) );
}
SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
const btVector3& rayTo,
const btVector3& aabbMin,
const btVector3& aabbMax,
btScalar& param, btVector3& normal)
{
btVector3 aabbHalfExtent = (aabbMax-aabbMin)* btScalar(0.5);
btVector3 aabbCenter = (aabbMax+aabbMin)* btScalar(0.5);
btVector3 source = rayFrom - aabbCenter;
btVector3 target = rayTo - aabbCenter;
int sourceOutcode = btOutcode(source,aabbHalfExtent);
int targetOutcode = btOutcode(target,aabbHalfExtent);
if ((sourceOutcode & targetOutcode) == 0x0)
{
btScalar lambda_enter = btScalar(0.0);
btScalar lambda_exit = param;
btVector3 r = target - source;
int i;
btScalar normSign = 1;
btVector3 hitNormal(0,0,0);
int bit=1;
for (int j=0;j<2;j++)
{
for (i = 0; i != 3; ++i)
{
if (sourceOutcode & bit)
{
btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
if (lambda_enter <= lambda)
{
lambda_enter = lambda;
hitNormal.setValue(0,0,0);
hitNormal[i] = normSign;
}
}
else if (targetOutcode & bit)
{
btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
btSetMin(lambda_exit, lambda);
}
bit<<=1;
}
normSign = btScalar(-1.);
}
if (lambda_enter <= lambda_exit)
{
param = lambda_enter;
normal = hitNormal;
return true;
}
}
return false;
}
SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin,const btTransform& t,btVector3& aabbMinOut,btVector3& aabbMaxOut)
{
btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin);
btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
btVector3 extent = btVector3(abs_b[0].dot(halfExtentsWithMargin),
abs_b[1].dot(halfExtentsWithMargin),
abs_b[2].dot(halfExtentsWithMargin));
aabbMinOut = center - extent;
aabbMaxOut = center + extent;
}
SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVector3& localAabbMax, btScalar margin,const btTransform& trans,btVector3& aabbMinOut,btVector3& aabbMaxOut)
{
btAssert(localAabbMin.getX() <= localAabbMax.getX());
btAssert(localAabbMin.getY() <= localAabbMax.getY());
btAssert(localAabbMin.getZ() <= localAabbMax.getZ());
btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
localHalfExtents+=btVector3(margin,margin,margin);
btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
btMatrix3x3 abs_b = trans.getBasis().absolute();
btVector3 center = trans(localCenter);
btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
abs_b[1].dot(localHalfExtents),
abs_b[2].dot(localHalfExtents));
aabbMinOut = center-extent;
aabbMaxOut = center+extent;
}
#define USE_BANCHLESS 1
#ifdef USE_BANCHLESS
//This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
{
return static_cast<unsigned int>(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
& (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
& (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
1, 0));
}
#else
SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
{
bool overlap = true;
overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
return overlap;
}
#endif //USE_BANCHLESS
#endif

View File

@ -0,0 +1,182 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btAlignedAllocator.h"
int gNumAlignedAllocs = 0;
int gNumAlignedFree = 0;
int gTotalBytesAlignedAllocs = 0;//detect memory leaks
static void *btAllocDefault(size_t size)
{
return malloc(size);
}
static void btFreeDefault(void *ptr)
{
free(ptr);
}
static btAllocFunc *sAllocFunc = btAllocDefault;
static btFreeFunc *sFreeFunc = btFreeDefault;
#if defined (BT_HAS_ALIGNED_ALLOCATOR)
#include <malloc.h>
static void *btAlignedAllocDefault(size_t size, int alignment)
{
return _aligned_malloc(size, (size_t)alignment);
}
static void btAlignedFreeDefault(void *ptr)
{
_aligned_free(ptr);
}
#elif defined(__CELLOS_LV2__)
#include <stdlib.h>
static inline void *btAlignedAllocDefault(size_t size, int alignment)
{
return memalign(alignment, size);
}
static inline void btAlignedFreeDefault(void *ptr)
{
free(ptr);
}
#else
static inline void *btAlignedAllocDefault(size_t size, int alignment)
{
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);
}
static inline void btAlignedFreeDefault(void *ptr)
{
void* real;
if (ptr) {
real = *((void **)(ptr)-1);
sFreeFunc(real);
}
}
#endif
static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault;
static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault;
void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc)
{
sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
}
void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc)
{
sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
}
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
//this generic allocator provides the total allocated number of bytes
#include <stdio.h>
void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename)
{
void *ret;
char *real;
unsigned long offset;
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);//??
}
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);
}
void btAlignedFreeInternal (void* ptr,int line,char* filename)
{
void* real;
gNumAlignedFree++;
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);
sFreeFunc(real);
} else
{
printf("NULL ptr\n");
}
}
#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;
}
void btAlignedFreeInternal (void* ptr)
{
if (!ptr)
{
return;
}
gNumAlignedFree++;
// printf("btAlignedFreeInternal %x\n",ptr);
sAlignedFreeFunc(ptr);
}
#endif //BT_DEBUG_MEMORY_ALLOCATIONS

View File

@ -0,0 +1,107 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_ALIGNED_ALLOCATOR
#define BT_ALIGNED_ALLOCATOR
///we probably replace this with our own aligned memory allocator
///so we replace _aligned_malloc and _aligned_free with our own
///that is better portable and more predictable
#include "btScalar.h"
//#define BT_DEBUG_MEMORY_ALLOCATIONS 1
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
#define btAlignedAlloc(a,b) \
btAlignedAllocInternal(a,b,__LINE__,__FILE__)
#define btAlignedFree(ptr) \
btAlignedFreeInternal(ptr,__LINE__,__FILE__)
void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename);
void btAlignedFreeInternal (void* ptr,int line,char* filename);
#else
void* btAlignedAllocInternal (size_t size, int alignment);
void btAlignedFreeInternal (void* ptr);
#define btAlignedAlloc(size,alignment) btAlignedAllocInternal(size,alignment)
#define btAlignedFree(ptr) btAlignedFreeInternal(ptr)
#endif
typedef int size_type;
typedef void *(btAlignedAllocFunc)(size_t size, int alignment);
typedef void (btAlignedFreeFunc)(void *memblock);
typedef void *(btAllocFunc)(size_t size);
typedef void (btFreeFunc)(void *memblock);
///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom
void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc);
///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc);
///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;
public:
//just going down a list:
btAlignedAllocator() {}
/*
btAlignedAllocator( const self_type & ) {}
*/
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;
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; }
friend bool operator==( const self_type & , const self_type & ) { return true; }
};
#endif //BT_ALIGNED_ALLOCATOR

View File

@ -0,0 +1,471 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_OBJECT_ARRAY__
#define BT_OBJECT_ARRAY__
#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
#include "btAlignedAllocator.h"
///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
///You can enable BT_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator=
///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and
///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240
#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...
#ifdef BT_USE_MEMCPY
#include <memory.h>
#include <string.h>
#endif //BT_USE_MEMCPY
#ifdef 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;
int m_size;
int m_capacity;
T* m_data;
//PCK: added this line
bool m_ownsMemory;
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)
#ifdef BT_USE_PLACEMENT_NEW
new (&dest[i]) T(m_data[i]);
#else
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* 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;
}
}
public:
btAlignedObjectArray()
{
init();
}
~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();
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;
}
SIMD_FORCE_INLINE const T& at(int n) const
{
return m_data[n];
}
SIMD_FORCE_INLINE T& at(int n)
{
return m_data[n];
}
SIMD_FORCE_INLINE const T& operator[](int n) const
{
return m_data[n];
}
SIMD_FORCE_INLINE T& operator[](int n)
{
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());
deallocate();
init();
}
SIMD_FORCE_INLINE void pop_back()
{
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();
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
}
m_size = newsize;
}
SIMD_FORCE_INLINE T& expandNonInitializing( )
{
int sz = size();
if( sz == capacity() )
{
reserve( allocSize(size()) );
}
m_size++;
return m_data[sz];
}
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)
#endif
return m_data[sz];
}
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);
#else
m_data[size()] = _Val;
#endif //BT_USE_PLACEMENT_NEW
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;
}
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);
destroy(0,size());
deallocate();
//PCK: added this line
m_ownsMemory = true;
m_data = s;
m_capacity = _Count;
}
}
class less
{
public:
bool operator() ( const T& a, const T& b )
{
return ( a < b );
}
};
template <typename L>
void quickSortInternal(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);
// recursion
if (lo<j)
quickSortInternal( CompareFunc, lo, j);
if (i<hi)
quickSortInternal( CompareFunc, i, hi);
}
template <typename L>
void quickSort(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,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;
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)
{
#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));
#else
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(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] */
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();
//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;
for (i=0;i<size();i++)
{
if (m_data[i] == key)
{
index = i;
break;
}
}
return index;
}
void remove(const T& key)
{
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;
}
void copyFromArray(const btAlignedObjectArray& otherArray)
{
int otherSize = otherArray.size();
resize (otherSize);
otherArray.copy(0, otherSize, m_data);
}
};
#endif //BT_OBJECT_ARRAY__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,241 @@
/*
Stan Melax Convex Hull Computation
Copyright (c) 2008 Stan Melax http://www.melax.com/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///includes modifications/improvements by John Ratcliff, see BringOutYourDead below.
#ifndef CD_HULL_H
#define CD_HULL_H
#include "btVector3.h"
#include "btAlignedObjectArray.h"
typedef btAlignedObjectArray<unsigned int> TUIntArray;
class HullResult
{
public:
HullResult(void)
{
mPolygons = true;
mNumOutputVertices = 0;
mNumFaces = 0;
mNumIndices = 0;
}
bool mPolygons; // true if indices represents polygons, false indices are triangles
unsigned int mNumOutputVertices; // number of vertices in the output hull
btAlignedObjectArray<btVector3> m_OutputVertices; // array of vertices
unsigned int mNumFaces; // the number of faces produced
unsigned int mNumIndices; // the total number of indices
btAlignedObjectArray<unsigned int> m_Indices; // pointer to indices.
// If triangles, then indices are array indexes into the vertex list.
// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
};
enum HullFlag
{
QF_TRIANGLES = (1<<0), // report results as triangles, not polygons.
QF_REVERSE_ORDER = (1<<1), // reverse order of the triangle indices.
QF_DEFAULT = QF_TRIANGLES
};
class HullDesc
{
public:
HullDesc(void)
{
mFlags = QF_DEFAULT;
mVcount = 0;
mVertices = 0;
mVertexStride = sizeof(btVector3);
mNormalEpsilon = 0.001f;
mMaxVertices = 4096; // maximum number of points to be considered for a convex hull.
mMaxFaces = 4096;
};
HullDesc(HullFlag flag,
unsigned int vcount,
const btVector3 *vertices,
unsigned int stride = sizeof(btVector3))
{
mFlags = flag;
mVcount = vcount;
mVertices = vertices;
mVertexStride = stride;
mNormalEpsilon = btScalar(0.001);
mMaxVertices = 4096;
}
bool HasHullFlag(HullFlag flag) const
{
if ( mFlags & flag ) return true;
return false;
}
void SetHullFlag(HullFlag flag)
{
mFlags|=flag;
}
void ClearHullFlag(HullFlag flag)
{
mFlags&=~flag;
}
unsigned int mFlags; // flags to use when generating the convex hull.
unsigned int mVcount; // number of vertices in the input point cloud
const btVector3 *mVertices; // the array of vertices.
unsigned int mVertexStride; // the stride of each vertex, in bytes.
btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull!
unsigned int mMaxFaces;
};
enum HullError
{
QE_OK, // success!
QE_FAIL // failed.
};
class btPlane
{
public:
btVector3 normal;
btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
btPlane(const btVector3 &n,btScalar d):normal(n),dist(d){}
btPlane():normal(),dist(0){}
};
class ConvexH
{
public:
class HalfEdge
{
public:
short ea; // the other half of the edge (index into edges list)
unsigned char v; // the vertex at the start of this edge (index into vertices list)
unsigned char p; // the facet on which this edge lies (index into facets list)
HalfEdge(){}
HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){}
};
ConvexH()
{
}
~ConvexH()
{
}
btAlignedObjectArray<btVector3> vertices;
btAlignedObjectArray<HalfEdge> edges;
btAlignedObjectArray<btPlane> facets;
ConvexH(int vertices_size,int edges_size,int facets_size);
};
class int4
{
public:
int x,y,z,w;
int4(){};
int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;}
const int& operator[](int i) const {return (&x)[i];}
int& operator[](int i) {return (&x)[i];}
};
class PHullResult
{
public:
PHullResult(void)
{
mVcount = 0;
mIndexCount = 0;
mFaceCount = 0;
mVertices = 0;
}
unsigned int mVcount;
unsigned int mIndexCount;
unsigned int mFaceCount;
btVector3* mVertices;
TUIntArray m_Indices;
};
///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method.
///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape.
class HullLibrary
{
btAlignedObjectArray<class btHullTriangle*> m_tris;
public:
btAlignedObjectArray<int> m_vertexIndexMapping;
HullError CreateConvexHull(const HullDesc& desc, // describes the input request
HullResult& result); // contains the resulst
HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it.
private:
bool ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit);
class btHullTriangle* allocateTriangle(int a,int b,int c);
void deAllocateTriangle(btHullTriangle*);
void b2bfix(btHullTriangle* s,btHullTriangle*t);
void removeb2b(btHullTriangle* s,btHullTriangle*t);
void checkit(btHullTriangle *t);
btHullTriangle* extrudable(btScalar epsilon);
int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit);
int calchullgen(btVector3 *verts,int verts_count, int vlimit);
int4 FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray<int> &allow);
class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice);
void extrude(class btHullTriangle* t0,int v);
ConvexH* test_cube();
//BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'.
//After the hull is generated it give you back a set of polygon faces which index the *original* point cloud.
//The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull.
//The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation.
void BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int* indices,unsigned indexcount);
bool CleanupVertices(unsigned int svcount,
const btVector3* svertices,
unsigned int stride,
unsigned int &vcount, // output number of vertices
btVector3* vertices, // location to store the results.
btScalar normalepsilon,
btVector3& scale);
};
#endif

View File

@ -0,0 +1,40 @@
#ifndef DEFAULT_MOTION_STATE_H
#define DEFAULT_MOTION_STATE_H
#include "btMotionState.h"
///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets.
struct btDefaultMotionState : public btMotionState
{
btTransform m_graphicsWorldTrans;
btTransform m_centerOfMassOffset;
btTransform m_startWorldTrans;
void* m_userPointer;
btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(),const btTransform& centerOfMassOffset = btTransform::getIdentity())
: m_graphicsWorldTrans(startTrans),
m_centerOfMassOffset(centerOfMassOffset),
m_startWorldTrans(startTrans),
m_userPointer(0)
{
}
///synchronizes world transform from user to physics
virtual void getWorldTransform(btTransform& centerOfMassWorldTrans ) const
{
centerOfMassWorldTrans = m_centerOfMassOffset.inverse() * m_graphicsWorldTrans ;
}
///synchronizes world transform from physics to user
///Bullet only calls the update of worldtransform for active objects
virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans)
{
m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset ;
}
};
#endif //DEFAULT_MOTION_STATE_H

View File

@ -0,0 +1,185 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btGeometryUtil.h"
/*
Make sure this dummy function never changes so that it
can be used by probes that are checking whether the
library is actually installed.
*/
extern "C"
{
void btBulletMathProbe ();
void btBulletMathProbe () {}
}
bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin)
{
int numbrushes = planeEquations.size();
for (int i=0;i<numbrushes;i++)
{
const btVector3& N1 = planeEquations[i];
btScalar dist = btScalar(N1.dot(point))+btScalar(N1[3])-margin;
if (dist>btScalar(0.))
{
return false;
}
}
return true;
}
bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin)
{
int numvertices = vertices.size();
for (int i=0;i<numvertices;i++)
{
const btVector3& N1 = vertices[i];
btScalar dist = btScalar(planeNormal.dot(N1))+btScalar(planeNormal[3])-margin;
if (dist>btScalar(0.))
{
return false;
}
}
return true;
}
bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations);
bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations)
{
int numbrushes = planeEquations.size();
for (int i=0;i<numbrushes;i++)
{
const btVector3& N1 = planeEquations[i];
if (planeEquation.dot(N1) > btScalar(0.999))
{
return false;
}
}
return true;
}
void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut )
{
const int numvertices = vertices.size();
// brute force:
for (int i=0;i<numvertices;i++)
{
const btVector3& N1 = vertices[i];
for (int j=i+1;j<numvertices;j++)
{
const btVector3& N2 = vertices[j];
for (int k=j+1;k<numvertices;k++)
{
const btVector3& N3 = vertices[k];
btVector3 planeEquation,edge0,edge1;
edge0 = N2-N1;
edge1 = N3-N1;
btScalar normalSign = btScalar(1.);
for (int ww=0;ww<2;ww++)
{
planeEquation = normalSign * edge0.cross(edge1);
if (planeEquation.length2() > btScalar(0.0001))
{
planeEquation.normalize();
if (notExist(planeEquation,planeEquationsOut))
{
planeEquation[3] = -planeEquation.dot(N1);
//check if inside, and replace supportingVertexOut if needed
if (areVerticesBehindPlane(planeEquation,vertices,btScalar(0.01)))
{
planeEquationsOut.push_back(planeEquation);
}
}
}
normalSign = btScalar(-1.);
}
}
}
}
}
void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations , btAlignedObjectArray<btVector3>& verticesOut )
{
const int numbrushes = planeEquations.size();
// brute force:
for (int i=0;i<numbrushes;i++)
{
const btVector3& N1 = planeEquations[i];
for (int j=i+1;j<numbrushes;j++)
{
const btVector3& N2 = planeEquations[j];
for (int k=j+1;k<numbrushes;k++)
{
const btVector3& N3 = planeEquations[k];
btVector3 n2n3; n2n3 = N2.cross(N3);
btVector3 n3n1; n3n1 = N3.cross(N1);
btVector3 n1n2; n1n2 = N1.cross(N2);
if ( ( n2n3.length2() > btScalar(0.0001) ) &&
( n3n1.length2() > btScalar(0.0001) ) &&
( n1n2.length2() > btScalar(0.0001) ) )
{
//point P out of 3 plane equations:
// d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
//P = -------------------------------------------------------------------------
// N1 . ( N2 * N3 )
btScalar quotient = (N1.dot(n2n3));
if (btFabs(quotient) > btScalar(0.000001))
{
quotient = btScalar(-1.) / quotient;
n2n3 *= N1[3];
n3n1 *= N2[3];
n1n2 *= N3[3];
btVector3 potentialVertex = n2n3;
potentialVertex += n3n1;
potentialVertex += n1n2;
potentialVertex *= quotient;
//check if inside, and replace supportingVertexOut if needed
if (isPointInsidePlanes(planeEquations,potentialVertex,btScalar(0.01)))
{
verticesOut.push_back(potentialVertex);
}
}
}
}
}
}
}

View File

@ -0,0 +1,42 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_GEOMETRY_UTIL_H
#define BT_GEOMETRY_UTIL_H
#include "btVector3.h"
#include "btAlignedObjectArray.h"
///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices.
class btGeometryUtil
{
public:
static void getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut );
static void getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations , btAlignedObjectArray<btVector3>& verticesOut );
static bool isInside(const btAlignedObjectArray<btVector3>& vertices, const btVector3& planeNormal, btScalar margin);
static bool isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin);
static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin);
};
#endif //BT_GEOMETRY_UTIL_H

View File

@ -0,0 +1,434 @@
#ifndef BT_HASH_MAP_H
#define BT_HASH_MAP_H
#include "btAlignedObjectArray.h"
///very basic hashable string implementation, compatible with btHashMap
struct btHashString
{
const char* m_string;
unsigned int m_hash;
SIMD_FORCE_INLINE unsigned int getHash()const
{
return m_hash;
}
btHashString(const char* name)
:m_string(name)
{
/* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
static const unsigned int InitialFNV = 2166136261u;
static const unsigned int FNVMultiple = 16777619u;
/* Fowler / Noll / Vo (FNV) Hash */
unsigned int hash = InitialFNV;
for(int i = 0; m_string[i]; i++)
{
hash = hash ^ (m_string[i]); /* xor the low 8 bits */
hash = hash * FNVMultiple; /* multiply by the magic number */
}
m_hash = hash;
}
int portableStringCompare(const char* src, const char* dst) const
{
int ret = 0 ;
while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
++src, ++dst;
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
}
bool equals(const btHashString& other) const
{
return (m_string == other.m_string) ||
(0==portableStringCompare(m_string,other.m_string));
}
};
const int BT_HASH_NULL=0xffffffff;
class btHashInt
{
int m_uid;
public:
btHashInt(int uid) :m_uid(uid)
{
}
int getUid1() const
{
return m_uid;
}
void setUid1(int uid)
{
m_uid = uid;
}
bool equals(const btHashInt& other) const
{
return getUid1() == other.getUid1();
}
//to our success
SIMD_FORCE_INLINE unsigned int getHash()const
{
int key = m_uid;
// Thomas Wang's hash
key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
return key;
}
};
class btHashPtr
{
union
{
const void* m_pointer;
int m_hashValues[2];
};
public:
btHashPtr(const void* ptr)
:m_pointer(ptr)
{
}
const void* getPointer() const
{
return m_pointer;
}
bool equals(const btHashPtr& other) const
{
return getPointer() == other.getPointer();
}
//to our success
SIMD_FORCE_INLINE unsigned int getHash()const
{
const bool VOID_IS_8 = ((sizeof(void*)==8));
int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0];
// Thomas Wang's hash
key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
return key;
}
};
template <class Value>
class btHashKeyPtr
{
int m_uid;
public:
btHashKeyPtr(int uid) :m_uid(uid)
{
}
int getUid1() const
{
return m_uid;
}
bool equals(const btHashKeyPtr<Value>& other) const
{
return getUid1() == other.getUid1();
}
//to our success
SIMD_FORCE_INLINE unsigned int getHash()const
{
int key = m_uid;
// Thomas Wang's hash
key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
return key;
}
};
template <class Value>
class btHashKey
{
int m_uid;
public:
btHashKey(int uid) :m_uid(uid)
{
}
int getUid1() const
{
return m_uid;
}
bool equals(const btHashKey<Value>& other) const
{
return getUid1() == other.getUid1();
}
//to our success
SIMD_FORCE_INLINE unsigned int getHash()const
{
int key = m_uid;
// Thomas Wang's hash
key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
return key;
}
};
///The btHashMap template class implements a generic and lightweight hashmap.
///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
template <class Key, class Value>
class btHashMap
{
protected:
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
btAlignedObjectArray<Value> m_valueArray;
btAlignedObjectArray<Key> m_keyArray;
void growTables(const Key& /*key*/)
{
int newCapacity = m_valueArray.capacity();
if (m_hashTable.size() < newCapacity)
{
//grow hashtable and next table
int curHashtableSize = m_hashTable.size();
m_hashTable.resize(newCapacity);
m_next.resize(newCapacity);
int i;
for (i= 0; i < newCapacity; ++i)
{
m_hashTable[i] = BT_HASH_NULL;
}
for (i = 0; i < newCapacity; ++i)
{
m_next[i] = BT_HASH_NULL;
}
for(i=0;i<curHashtableSize;i++)
{
//const Value& value = m_valueArray[i];
//const Key& key = m_keyArray[i];
int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1); // New hash value with new mask
m_next[i] = m_hashTable[hashValue];
m_hashTable[hashValue] = i;
}
}
}
public:
void insert(const Key& key, const Value& value) {
int hash = key.getHash() & (m_valueArray.capacity()-1);
//replace value if the key is already there
int index = findIndex(key);
if (index != BT_HASH_NULL)
{
m_valueArray[index]=value;
return;
}
int count = m_valueArray.size();
int oldCapacity = m_valueArray.capacity();
m_valueArray.push_back(value);
m_keyArray.push_back(key);
int newCapacity = m_valueArray.capacity();
if (oldCapacity < newCapacity)
{
growTables(key);
//hash with new capacity
hash = key.getHash() & (m_valueArray.capacity()-1);
}
m_next[count] = m_hashTable[hash];
m_hashTable[hash] = count;
}
void remove(const Key& key) {
int hash = key.getHash() & (m_valueArray.capacity()-1);
int pairIndex = findIndex(key);
if (pairIndex ==BT_HASH_NULL)
{
return;
}
// Remove the pair from the hash table.
int index = m_hashTable[hash];
btAssert(index != BT_HASH_NULL);
int previous = BT_HASH_NULL;
while (index != pairIndex)
{
previous = index;
index = m_next[index];
}
if (previous != BT_HASH_NULL)
{
btAssert(m_next[previous] == pairIndex);
m_next[previous] = m_next[pairIndex];
}
else
{
m_hashTable[hash] = m_next[pairIndex];
}
// We now move the last pair into spot of the
// pair being removed. We need to fix the hash
// table indices to support the move.
int lastPairIndex = m_valueArray.size() - 1;
// If the removed pair is the last pair, we are done.
if (lastPairIndex == pairIndex)
{
m_valueArray.pop_back();
m_keyArray.pop_back();
return;
}
// Remove the last pair from the hash table.
int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
index = m_hashTable[lastHash];
btAssert(index != BT_HASH_NULL);
previous = BT_HASH_NULL;
while (index != lastPairIndex)
{
previous = index;
index = m_next[index];
}
if (previous != BT_HASH_NULL)
{
btAssert(m_next[previous] == lastPairIndex);
m_next[previous] = m_next[lastPairIndex];
}
else
{
m_hashTable[lastHash] = m_next[lastPairIndex];
}
// Copy the last pair into the remove pair's spot.
m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
// Insert the last pair into the hash table
m_next[pairIndex] = m_hashTable[lastHash];
m_hashTable[lastHash] = pairIndex;
m_valueArray.pop_back();
m_keyArray.pop_back();
}
int size() const
{
return m_valueArray.size();
}
const Value* getAtIndex(int index) const
{
btAssert(index < m_valueArray.size());
return &m_valueArray[index];
}
Value* getAtIndex(int index)
{
btAssert(index < m_valueArray.size());
return &m_valueArray[index];
}
Value* operator[](const Key& key) {
return find(key);
}
const Value* find(const Key& key) const
{
int index = findIndex(key);
if (index == BT_HASH_NULL)
{
return NULL;
}
return &m_valueArray[index];
}
Value* find(const Key& key)
{
int index = findIndex(key);
if (index == BT_HASH_NULL)
{
return NULL;
}
return &m_valueArray[index];
}
int findIndex(const Key& key) const
{
unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
if (hash >= (unsigned int)m_hashTable.size())
{
return BT_HASH_NULL;
}
int index = m_hashTable[hash];
while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
{
index = m_next[index];
}
return index;
}
void clear()
{
m_hashTable.clear();
m_next.clear();
m_valueArray.clear();
m_keyArray.clear();
}
};
#endif //BT_HASH_MAP_H

View File

@ -0,0 +1,316 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef IDEBUG_DRAW__H
#define IDEBUG_DRAW__H
#include "btVector3.h"
#include "btTransform.h"
///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld.
///A class that implements the btIDebugDraw interface has to implement the drawLine method at a minimum.
///For color arguments the X,Y,Z components refer to Red, Green and Blue each in the range [0..1]
class btIDebugDraw
{
public:
enum DebugDrawModes
{
DBG_NoDebug=0,
DBG_DrawWireframe = 1,
DBG_DrawAabb=2,
DBG_DrawFeaturesText=4,
DBG_DrawContactPoints=8,
DBG_NoDeactivation=16,
DBG_NoHelpText = 32,
DBG_DrawText=64,
DBG_ProfileTimings = 128,
DBG_EnableSatComparison = 256,
DBG_DisableBulletLCP = 512,
DBG_EnableCCD = 1024,
DBG_DrawConstraints = (1 << 11),
DBG_DrawConstraintLimits = (1 << 12),
DBG_FastWireframe = (1<<13),
DBG_MAX_DEBUG_DRAW_MODE
};
virtual ~btIDebugDraw() {};
virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0;
virtual void drawLine(const btVector3& from,const btVector3& to, const btVector3& fromColor, const btVector3& toColor)
{
(void) toColor;
drawLine (from, to, fromColor);
}
virtual void drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
{
btVector3 start = transform.getOrigin();
const btVector3 xoffs = transform.getBasis() * btVector3(radius,0,0);
const btVector3 yoffs = transform.getBasis() * btVector3(0,radius,0);
const btVector3 zoffs = transform.getBasis() * btVector3(0,0,radius);
// XY
drawLine(start-xoffs, start+yoffs, color);
drawLine(start+yoffs, start+xoffs, color);
drawLine(start+xoffs, start-yoffs, color);
drawLine(start-yoffs, start-xoffs, color);
// XZ
drawLine(start-xoffs, start+zoffs, color);
drawLine(start+zoffs, start+xoffs, color);
drawLine(start+xoffs, start-zoffs, color);
drawLine(start-zoffs, start-xoffs, color);
// YZ
drawLine(start-yoffs, start+zoffs, color);
drawLine(start+zoffs, start+yoffs, color);
drawLine(start+yoffs, start-zoffs, color);
drawLine(start-zoffs, start-yoffs, color);
}
virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color)
{
btTransform tr;
tr.setIdentity();
tr.setOrigin(p);
drawSphere(radius,tr,color);
}
virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& /*n0*/,const btVector3& /*n1*/,const btVector3& /*n2*/,const btVector3& color, btScalar alpha)
{
drawTriangle(v0,v1,v2,color,alpha);
}
virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& color, btScalar /*alpha*/)
{
drawLine(v0,v1,color);
drawLine(v1,v2,color);
drawLine(v2,v0,color);
}
virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0;
virtual void reportErrorWarning(const char* warningString) = 0;
virtual void draw3dText(const btVector3& location,const char* textString) = 0;
virtual void setDebugMode(int debugMode) =0;
virtual int getDebugMode() const = 0;
virtual void drawAabb(const btVector3& from,const btVector3& to,const btVector3& color)
{
btVector3 halfExtents = (to-from)* 0.5f;
btVector3 center = (to+from) *0.5f;
int i,j;
btVector3 edgecoord(1.f,1.f,1.f),pa,pb;
for (i=0;i<4;i++)
{
for (j=0;j<3;j++)
{
pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
edgecoord[2]*halfExtents[2]);
pa+=center;
int othercoord = j%3;
edgecoord[othercoord]*=-1.f;
pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
edgecoord[2]*halfExtents[2]);
pb+=center;
drawLine(pa,pb,color);
}
edgecoord = btVector3(-1.f,-1.f,-1.f);
if (i<3)
edgecoord[i]*=-1.f;
}
}
virtual void drawTransform(const btTransform& transform, btScalar orthoLen)
{
btVector3 start = transform.getOrigin();
drawLine(start, start+transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(0.7f,0,0));
drawLine(start, start+transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(0,0.7f,0));
drawLine(start, start+transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(0,0,0.7f));
}
virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle,
const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f))
{
const btVector3& vx = axis;
btVector3 vy = normal.cross(axis);
btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
int nSteps = (int)((maxAngle - minAngle) / step);
if(!nSteps) nSteps = 1;
btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle);
if(drawSect)
{
drawLine(center, prev, color);
}
for(int i = 1; i <= nSteps; i++)
{
btScalar angle = minAngle + (maxAngle - minAngle) * btScalar(i) / btScalar(nSteps);
btVector3 next = center + radiusA * vx * btCos(angle) + radiusB * vy * btSin(angle);
drawLine(prev, next, color);
prev = next;
}
if(drawSect)
{
drawLine(center, prev, color);
}
}
virtual void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius,
btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f))
{
btVector3 vA[74];
btVector3 vB[74];
btVector3 *pvA = vA, *pvB = vB, *pT;
btVector3 npole = center + up * radius;
btVector3 spole = center - up * radius;
btVector3 arcStart;
btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
const btVector3& kv = up;
const btVector3& iv = axis;
btVector3 jv = kv.cross(iv);
bool drawN = false;
bool drawS = false;
if(minTh <= -SIMD_HALF_PI)
{
minTh = -SIMD_HALF_PI + step;
drawN = true;
}
if(maxTh >= SIMD_HALF_PI)
{
maxTh = SIMD_HALF_PI - step;
drawS = true;
}
if(minTh > maxTh)
{
minTh = -SIMD_HALF_PI + step;
maxTh = SIMD_HALF_PI - step;
drawN = drawS = true;
}
int n_hor = (int)((maxTh - minTh) / step) + 1;
if(n_hor < 2) n_hor = 2;
btScalar step_h = (maxTh - minTh) / btScalar(n_hor - 1);
bool isClosed = false;
if(minPs > maxPs)
{
minPs = -SIMD_PI + step;
maxPs = SIMD_PI;
isClosed = true;
}
else if((maxPs - minPs) >= SIMD_PI * btScalar(2.f))
{
isClosed = true;
}
else
{
isClosed = false;
}
int n_vert = (int)((maxPs - minPs) / step) + 1;
if(n_vert < 2) n_vert = 2;
btScalar step_v = (maxPs - minPs) / btScalar(n_vert - 1);
for(int i = 0; i < n_hor; i++)
{
btScalar th = minTh + btScalar(i) * step_h;
btScalar sth = radius * btSin(th);
btScalar cth = radius * btCos(th);
for(int j = 0; j < n_vert; j++)
{
btScalar psi = minPs + btScalar(j) * step_v;
btScalar sps = btSin(psi);
btScalar cps = btCos(psi);
pvB[j] = center + cth * cps * iv + cth * sps * jv + sth * kv;
if(i)
{
drawLine(pvA[j], pvB[j], color);
}
else if(drawS)
{
drawLine(spole, pvB[j], color);
}
if(j)
{
drawLine(pvB[j-1], pvB[j], color);
}
else
{
arcStart = pvB[j];
}
if((i == (n_hor - 1)) && drawN)
{
drawLine(npole, pvB[j], color);
}
if(isClosed)
{
if(j == (n_vert-1))
{
drawLine(arcStart, pvB[j], color);
}
}
else
{
if(((!i) || (i == (n_hor-1))) && ((!j) || (j == (n_vert-1))))
{
drawLine(center, pvB[j], color);
}
}
}
pT = pvA; pvA = pvB; pvB = pT;
}
}
virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color)
{
drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMin[2]), color);
drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMin[2]), color);
drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMin[2]), color);
drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
drawLine(btVector3(bbMin[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
drawLine(btVector3(bbMax[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
drawLine(btVector3(bbMax[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
drawLine(btVector3(bbMin[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
}
virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btTransform& trans, const btVector3& color)
{
drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), color);
drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), color);
drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), color);
drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
}
};
#endif //IDEBUG_DRAW__H

View File

@ -0,0 +1,73 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef GEN_LIST_H
#define GEN_LIST_H
class btGEN_Link {
public:
btGEN_Link() : m_next(0), m_prev(0) {}
btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {}
btGEN_Link *getNext() const { return m_next; }
btGEN_Link *getPrev() const { return m_prev; }
bool isHead() const { return m_prev == 0; }
bool isTail() const { return m_next == 0; }
void insertBefore(btGEN_Link *link) {
m_next = link;
m_prev = link->m_prev;
m_next->m_prev = this;
m_prev->m_next = this;
}
void insertAfter(btGEN_Link *link) {
m_next = link->m_next;
m_prev = link;
m_next->m_prev = this;
m_prev->m_next = this;
}
void remove() {
m_next->m_prev = m_prev;
m_prev->m_next = m_next;
}
private:
btGEN_Link *m_next;
btGEN_Link *m_prev;
};
class btGEN_List {
public:
btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
btGEN_Link *getHead() const { return m_head.getNext(); }
btGEN_Link *getTail() const { return m_tail.getPrev(); }
void addHead(btGEN_Link *link) { link->insertAfter(&m_head); }
void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); }
private:
btGEN_Link m_head;
btGEN_Link m_tail;
};
#endif

View File

@ -0,0 +1,688 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_MATRIX3x3_H
#define BT_MATRIX3x3_H
#include "btVector3.h"
#include "btQuaternion.h"
#ifdef BT_USE_DOUBLE_PRECISION
#define btMatrix3x3Data btMatrix3x3DoubleData
#else
#define btMatrix3x3Data btMatrix3x3FloatData
#endif //BT_USE_DOUBLE_PRECISION
/**@brief The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3.
* Make sure to only include a pure orthogonal matrix without scaling. */
class btMatrix3x3 {
///Data storage for the matrix, each vector is a row of the matrix
btVector3 m_el[3];
public:
/** @brief No initializaion constructor */
btMatrix3x3 () {}
// explicit btMatrix3x3(const btScalar *m) { setFromOpenGLSubMatrix(m); }
/**@brief Constructor from Quaternion */
explicit btMatrix3x3(const btQuaternion& q) { setRotation(q); }
/*
template <typename btScalar>
Matrix3x3(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
{
setEulerYPR(yaw, pitch, roll);
}
*/
/** @brief Constructor with row major formatting */
btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz,
const btScalar& yx, const btScalar& yy, const btScalar& yz,
const btScalar& zx, const btScalar& zy, const btScalar& zz)
{
setValue(xx, xy, xz,
yx, yy, yz,
zx, zy, zz);
}
/** @brief Copy constructor */
SIMD_FORCE_INLINE btMatrix3x3 (const btMatrix3x3& other)
{
m_el[0] = other.m_el[0];
m_el[1] = other.m_el[1];
m_el[2] = other.m_el[2];
}
/** @brief Assignment Operator */
SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other)
{
m_el[0] = other.m_el[0];
m_el[1] = other.m_el[1];
m_el[2] = other.m_el[2];
return *this;
}
/** @brief Get a column of the matrix as a vector
* @param i Column number 0 indexed */
SIMD_FORCE_INLINE btVector3 getColumn(int i) const
{
return btVector3(m_el[0][i],m_el[1][i],m_el[2][i]);
}
/** @brief Get a row of the matrix as a vector
* @param i Row number 0 indexed */
SIMD_FORCE_INLINE const btVector3& getRow(int i) const
{
btFullAssert(0 <= i && i < 3);
return m_el[i];
}
/** @brief Get a mutable reference to a row of the matrix as a vector
* @param i Row number 0 indexed */
SIMD_FORCE_INLINE btVector3& operator[](int i)
{
btFullAssert(0 <= i && i < 3);
return m_el[i];
}
/** @brief Get a const reference to a row of the matrix as a vector
* @param i Row number 0 indexed */
SIMD_FORCE_INLINE const btVector3& operator[](int i) const
{
btFullAssert(0 <= i && i < 3);
return m_el[i];
}
/** @brief Multiply by the target matrix on the right
* @param m Rotation matrix to be applied
* Equivilant to this = this * m */
btMatrix3x3& operator*=(const btMatrix3x3& m);
/** @brief Set from a carray of btScalars
* @param m A pointer to the beginning of an array of 9 btScalars */
void setFromOpenGLSubMatrix(const btScalar *m)
{
m_el[0].setValue(m[0],m[4],m[8]);
m_el[1].setValue(m[1],m[5],m[9]);
m_el[2].setValue(m[2],m[6],m[10]);
}
/** @brief Set the values of the matrix explicitly (row major)
* @param xx Top left
* @param xy Top Middle
* @param xz Top Right
* @param yx Middle Left
* @param yy Middle Middle
* @param yz Middle Right
* @param zx Bottom Left
* @param zy Bottom Middle
* @param zz Bottom Right*/
void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz,
const btScalar& yx, const btScalar& yy, const btScalar& yz,
const btScalar& zx, const btScalar& zy, const btScalar& zz)
{
m_el[0].setValue(xx,xy,xz);
m_el[1].setValue(yx,yy,yz);
m_el[2].setValue(zx,zy,zz);
}
/** @brief Set the matrix from a quaternion
* @param q The Quaternion to match */
void setRotation(const btQuaternion& q)
{
btScalar d = q.length2();
btFullAssert(d != btScalar(0.0));
btScalar s = btScalar(2.0) / d;
btScalar xs = q.x() * s, ys = q.y() * s, zs = q.z() * s;
btScalar wx = q.w() * xs, wy = q.w() * ys, wz = q.w() * zs;
btScalar xx = q.x() * xs, xy = q.x() * ys, xz = q.x() * zs;
btScalar yy = q.y() * ys, yz = q.y() * zs, zz = q.z() * zs;
setValue(btScalar(1.0) - (yy + zz), xy - wz, xz + wy,
xy + wz, btScalar(1.0) - (xx + zz), yz - wx,
xz - wy, yz + wx, btScalar(1.0) - (xx + yy));
}
/** @brief Set the matrix from euler angles using YPR around YXZ respectively
* @param yaw Yaw about Y axis
* @param pitch Pitch about X axis
* @param roll Roll about Z axis
*/
void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
{
setEulerZYX(roll, pitch, yaw);
}
/** @brief Set the matrix from euler angles YPR around ZYX axes
* @param eulerX Roll about X axis
* @param eulerY Pitch around Y axis
* @param eulerZ Yaw aboud Z axis
*
* These angles are used to produce a rotation matrix. The euler
* angles are applied in ZYX order. I.e a vector is first rotated
* about X then Y and then Z
**/
void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ) {
///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code
btScalar ci ( btCos(eulerX));
btScalar cj ( btCos(eulerY));
btScalar ch ( btCos(eulerZ));
btScalar si ( btSin(eulerX));
btScalar sj ( btSin(eulerY));
btScalar sh ( btSin(eulerZ));
btScalar cc = ci * ch;
btScalar cs = ci * sh;
btScalar sc = si * ch;
btScalar ss = si * sh;
setValue(cj * ch, sj * sc - cs, sj * cc + ss,
cj * sh, sj * ss + cc, sj * cs - sc,
-sj, cj * si, cj * ci);
}
/**@brief Set the matrix to the identity */
void setIdentity()
{
setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0),
btScalar(0.0), btScalar(1.0), btScalar(0.0),
btScalar(0.0), btScalar(0.0), btScalar(1.0));
}
static const btMatrix3x3& getIdentity()
{
static const btMatrix3x3 identityMatrix(btScalar(1.0), btScalar(0.0), btScalar(0.0),
btScalar(0.0), btScalar(1.0), btScalar(0.0),
btScalar(0.0), btScalar(0.0), btScalar(1.0));
return identityMatrix;
}
/**@brief Fill the values of the matrix into a 9 element array
* @param m The array to be filled */
void getOpenGLSubMatrix(btScalar *m) const
{
m[0] = btScalar(m_el[0].x());
m[1] = btScalar(m_el[1].x());
m[2] = btScalar(m_el[2].x());
m[3] = btScalar(0.0);
m[4] = btScalar(m_el[0].y());
m[5] = btScalar(m_el[1].y());
m[6] = btScalar(m_el[2].y());
m[7] = btScalar(0.0);
m[8] = btScalar(m_el[0].z());
m[9] = btScalar(m_el[1].z());
m[10] = btScalar(m_el[2].z());
m[11] = btScalar(0.0);
}
/**@brief Get the matrix represented as a quaternion
* @param q The quaternion which will be set */
void getRotation(btQuaternion& q) const
{
btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
btScalar temp[4];
if (trace > btScalar(0.0))
{
btScalar s = btSqrt(trace + btScalar(1.0));
temp[3]=(s * btScalar(0.5));
s = btScalar(0.5) / s;
temp[0]=((m_el[2].y() - m_el[1].z()) * s);
temp[1]=((m_el[0].z() - m_el[2].x()) * s);
temp[2]=((m_el[1].x() - m_el[0].y()) * s);
}
else
{
int i = m_el[0].x() < m_el[1].y() ?
(m_el[1].y() < m_el[2].z() ? 2 : 1) :
(m_el[0].x() < m_el[2].z() ? 2 : 0);
int j = (i + 1) % 3;
int k = (i + 2) % 3;
btScalar s = btSqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0));
temp[i] = s * btScalar(0.5);
s = btScalar(0.5) / s;
temp[3] = (m_el[k][j] - m_el[j][k]) * s;
temp[j] = (m_el[j][i] + m_el[i][j]) * s;
temp[k] = (m_el[k][i] + m_el[i][k]) * s;
}
q.setValue(temp[0],temp[1],temp[2],temp[3]);
}
/**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR
* @param yaw Yaw around Y axis
* @param pitch Pitch around X axis
* @param roll around Z axis */
void getEulerYPR(btScalar& yaw, btScalar& pitch, btScalar& roll) const
{
// first use the normal calculus
yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x()));
pitch = btScalar(btAsin(-m_el[2].x()));
roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z()));
// on pitch = +/-HalfPI
if (btFabs(pitch)==SIMD_HALF_PI)
{
if (yaw>0)
yaw-=SIMD_PI;
else
yaw+=SIMD_PI;
if (roll>0)
roll-=SIMD_PI;
else
roll+=SIMD_PI;
}
};
/**@brief Get the matrix represented as euler angles around ZYX
* @param yaw Yaw around X axis
* @param pitch Pitch around Y axis
* @param roll around X axis
* @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/
void getEulerZYX(btScalar& yaw, btScalar& pitch, btScalar& roll, unsigned int solution_number = 1) const
{
struct Euler
{
btScalar yaw;
btScalar pitch;
btScalar roll;
};
Euler euler_out;
Euler euler_out2; //second solution
//get the pointer to the raw data
// Check that pitch is not at a singularity
if (btFabs(m_el[2].x()) >= 1)
{
euler_out.yaw = 0;
euler_out2.yaw = 0;
// From difference of angles formula
btScalar delta = btAtan2(m_el[0].x(),m_el[0].z());
if (m_el[2].x() > 0) //gimbal locked up
{
euler_out.pitch = SIMD_PI / btScalar(2.0);
euler_out2.pitch = SIMD_PI / btScalar(2.0);
euler_out.roll = euler_out.pitch + delta;
euler_out2.roll = euler_out.pitch + delta;
}
else // gimbal locked down
{
euler_out.pitch = -SIMD_PI / btScalar(2.0);
euler_out2.pitch = -SIMD_PI / btScalar(2.0);
euler_out.roll = -euler_out.pitch + delta;
euler_out2.roll = -euler_out.pitch + delta;
}
}
else
{
euler_out.pitch = - btAsin(m_el[2].x());
euler_out2.pitch = SIMD_PI - euler_out.pitch;
euler_out.roll = btAtan2(m_el[2].y()/btCos(euler_out.pitch),
m_el[2].z()/btCos(euler_out.pitch));
euler_out2.roll = btAtan2(m_el[2].y()/btCos(euler_out2.pitch),
m_el[2].z()/btCos(euler_out2.pitch));
euler_out.yaw = btAtan2(m_el[1].x()/btCos(euler_out.pitch),
m_el[0].x()/btCos(euler_out.pitch));
euler_out2.yaw = btAtan2(m_el[1].x()/btCos(euler_out2.pitch),
m_el[0].x()/btCos(euler_out2.pitch));
}
if (solution_number == 1)
{
yaw = euler_out.yaw;
pitch = euler_out.pitch;
roll = euler_out.roll;
}
else
{
yaw = euler_out2.yaw;
pitch = euler_out2.pitch;
roll = euler_out2.roll;
}
}
/**@brief Create a scaled copy of the matrix
* @param s Scaling vector The elements of the vector will scale each column */
btMatrix3x3 scaled(const btVector3& s) const
{
return btMatrix3x3(m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(),
m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(),
m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z());
}
/**@brief Return the determinant of the matrix */
btScalar determinant() const;
/**@brief Return the adjoint of the matrix */
btMatrix3x3 adjoint() const;
/**@brief Return the matrix with all values non negative */
btMatrix3x3 absolute() const;
/**@brief Return the transpose of the matrix */
btMatrix3x3 transpose() const;
/**@brief Return the inverse of the matrix */
btMatrix3x3 inverse() const;
btMatrix3x3 transposeTimes(const btMatrix3x3& m) const;
btMatrix3x3 timesTranspose(const btMatrix3x3& m) const;
SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const
{
return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z();
}
SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const
{
return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z();
}
SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const
{
return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z();
}
/**@brief diagonalizes this matrix by the Jacobi method.
* @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original
* coordinate system, i.e., old_this = rot * new_this * rot^T.
* @param threshold See iteration
* @param iteration The iteration stops when all off-diagonal elements are less than the threshold multiplied
* by the sum of the absolute values of the diagonal, or when maxSteps have been executed.
*
* Note that this matrix is assumed to be symmetric.
*/
void diagonalize(btMatrix3x3& rot, btScalar threshold, int maxSteps)
{
rot.setIdentity();
for (int step = maxSteps; step > 0; step--)
{
// find off-diagonal element [p][q] with largest magnitude
int p = 0;
int q = 1;
int r = 2;
btScalar max = btFabs(m_el[0][1]);
btScalar v = btFabs(m_el[0][2]);
if (v > max)
{
q = 2;
r = 1;
max = v;
}
v = btFabs(m_el[1][2]);
if (v > max)
{
p = 1;
q = 2;
r = 0;
max = v;
}
btScalar t = threshold * (btFabs(m_el[0][0]) + btFabs(m_el[1][1]) + btFabs(m_el[2][2]));
if (max <= t)
{
if (max <= SIMD_EPSILON * t)
{
return;
}
step = 1;
}
// compute Jacobi rotation J which leads to a zero for element [p][q]
btScalar mpq = m_el[p][q];
btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq);
btScalar theta2 = theta * theta;
btScalar cos;
btScalar sin;
if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON))
{
t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2))
: 1 / (theta - btSqrt(1 + theta2));
cos = 1 / btSqrt(1 + t * t);
sin = cos * t;
}
else
{
// approximation for large theta-value, i.e., a nearly diagonal matrix
t = 1 / (theta * (2 + btScalar(0.5) / theta2));
cos = 1 - btScalar(0.5) * t * t;
sin = cos * t;
}
// apply rotation to matrix (this = J^T * this * J)
m_el[p][q] = m_el[q][p] = 0;
m_el[p][p] -= t * mpq;
m_el[q][q] += t * mpq;
btScalar mrp = m_el[r][p];
btScalar mrq = m_el[r][q];
m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq;
m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp;
// apply rotation to rot (rot = rot * J)
for (int i = 0; i < 3; i++)
{
btVector3& row = rot[i];
mrp = row[p];
mrq = row[q];
row[p] = cos * mrp - sin * mrq;
row[q] = cos * mrq + sin * mrp;
}
}
}
/**@brief Calculate the matrix cofactor
* @param r1 The first row to use for calculating the cofactor
* @param c1 The first column to use for calculating the cofactor
* @param r1 The second row to use for calculating the cofactor
* @param c1 The second column to use for calculating the cofactor
* See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details
*/
btScalar cofac(int r1, int c1, int r2, int c2) const
{
return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
}
void serialize(struct btMatrix3x3Data& dataOut) const;
void serializeFloat(struct btMatrix3x3FloatData& dataOut) const;
void deSerialize(const struct btMatrix3x3Data& dataIn);
void deSerializeFloat(const struct btMatrix3x3FloatData& dataIn);
void deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn);
};
SIMD_FORCE_INLINE btMatrix3x3&
btMatrix3x3::operator*=(const btMatrix3x3& m)
{
setValue(m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
return *this;
}
SIMD_FORCE_INLINE btScalar
btMatrix3x3::determinant() const
{
return btTriple((*this)[0], (*this)[1], (*this)[2]);
}
SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::absolute() const
{
return btMatrix3x3(
btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()),
btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()),
btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z()));
}
SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::transpose() const
{
return btMatrix3x3(m_el[0].x(), m_el[1].x(), m_el[2].x(),
m_el[0].y(), m_el[1].y(), m_el[2].y(),
m_el[0].z(), m_el[1].z(), m_el[2].z());
}
SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::adjoint() const
{
return btMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
}
SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::inverse() const
{
btVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
btScalar det = (*this)[0].dot(co);
btFullAssert(det != btScalar(0.0));
btScalar s = btScalar(1.0) / det;
return btMatrix3x3(co.x() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
}
SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::transposeTimes(const btMatrix3x3& m) const
{
return btMatrix3x3(
m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(),
m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(),
m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(),
m_el[0].y() * m[0].x() + m_el[1].y() * m[1].x() + m_el[2].y() * m[2].x(),
m_el[0].y() * m[0].y() + m_el[1].y() * m[1].y() + m_el[2].y() * m[2].y(),
m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(),
m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(),
m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(),
m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z());
}
SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::timesTranspose(const btMatrix3x3& m) const
{
return btMatrix3x3(
m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
}
SIMD_FORCE_INLINE btVector3
operator*(const btMatrix3x3& m, const btVector3& v)
{
return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
}
SIMD_FORCE_INLINE btVector3
operator*(const btVector3& v, const btMatrix3x3& m)
{
return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
}
SIMD_FORCE_INLINE btMatrix3x3
operator*(const btMatrix3x3& m1, const btMatrix3x3& m2)
{
return btMatrix3x3(
m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]),
m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]),
m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2]));
}
/*
SIMD_FORCE_INLINE btMatrix3x3 btMultTransposeLeft(const btMatrix3x3& m1, const btMatrix3x3& m2) {
return btMatrix3x3(
m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0],
m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1],
m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2],
m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0],
m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1],
m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2],
m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0],
m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1],
m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
}
*/
/**@brief Equality operator between two matrices
* It will test all elements are equal. */
SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2)
{
return ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] );
}
///for serialization
struct btMatrix3x3FloatData
{
btVector3FloatData m_el[3];
};
///for serialization
struct btMatrix3x3DoubleData
{
btVector3DoubleData m_el[3];
};
SIMD_FORCE_INLINE void btMatrix3x3::serialize(struct btMatrix3x3Data& dataOut) const
{
for (int i=0;i<3;i++)
m_el[i].serialize(dataOut.m_el[i]);
}
SIMD_FORCE_INLINE void btMatrix3x3::serializeFloat(struct btMatrix3x3FloatData& dataOut) const
{
for (int i=0;i<3;i++)
m_el[i].serializeFloat(dataOut.m_el[i]);
}
SIMD_FORCE_INLINE void btMatrix3x3::deSerialize(const struct btMatrix3x3Data& dataIn)
{
for (int i=0;i<3;i++)
m_el[i].deSerialize(dataIn.m_el[i]);
}
SIMD_FORCE_INLINE void btMatrix3x3::deSerializeFloat(const struct btMatrix3x3FloatData& dataIn)
{
for (int i=0;i<3;i++)
m_el[i].deSerializeFloat(dataIn.m_el[i]);
}
SIMD_FORCE_INLINE void btMatrix3x3::deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn)
{
for (int i=0;i<3;i++)
m_el[i].deSerializeDouble(dataIn.m_el[i]);
}
#endif //BT_MATRIX3x3_H

View File

@ -0,0 +1,71 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef GEN_MINMAX_H
#define GEN_MINMAX_H
#include "LinearMath/btScalar.h"
template <class T>
SIMD_FORCE_INLINE const T& btMin(const T& a, const T& 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;
}
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);
}
template <class T>
SIMD_FORCE_INLINE void btSetMin(T& a, const T& b)
{
if (b < a)
{
a = b;
}
}
template <class T>
SIMD_FORCE_INLINE void btSetMax(T& a, const T& 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;
}
}
#endif

View File

@ -0,0 +1,40 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_MOTIONSTATE_H
#define BT_MOTIONSTATE_H
#include "btTransform.h"
///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics
///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation)
class btMotionState
{
public:
virtual ~btMotionState()
{
}
virtual void getWorldTransform(btTransform& worldTrans ) const =0;
//Bullet only calls the update of worldtransform for active objects
virtual void setWorldTransform(const btTransform& worldTrans)=0;
};
#endif //BT_MOTIONSTATE_H

View File

@ -0,0 +1,116 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef _BT_POOL_ALLOCATOR_H
#define _BT_POOL_ALLOCATOR_H
#include "btScalar.h"
#include "btAlignedAllocator.h"
///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
class btPoolAllocator
{
int m_elemSize;
int m_maxElements;
int m_freeCount;
void* m_firstFree;
unsigned char* m_pool;
public:
btPoolAllocator(int elemSize, int maxElements)
:m_elemSize(elemSize),
m_maxElements(maxElements)
{
m_pool = (unsigned char*) btAlignedAlloc( static_cast<unsigned int>(m_elemSize*m_maxElements),16);
unsigned char* p = m_pool;
m_firstFree = p;
m_freeCount = m_maxElements;
int count = m_maxElements;
while (--count) {
*(void**)p = (p + m_elemSize);
p += m_elemSize;
}
*(void**)p = 0;
}
~btPoolAllocator()
{
btAlignedFree( m_pool);
}
int getFreeCount() const
{
return m_freeCount;
}
int getUsedCount() const
{
return m_maxElements - m_freeCount;
}
void* allocate(int size)
{
// release mode fix
(void)size;
btAssert(!size || size<=m_elemSize);
btAssert(m_freeCount>0);
void* result = m_firstFree;
m_firstFree = *(void**)m_firstFree;
--m_freeCount;
return result;
}
bool validPtr(void* ptr)
{
if (ptr) {
if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
{
return true;
}
}
return false;
}
void freeMemory(void* ptr)
{
if (ptr) {
btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
*(void**)ptr = m_firstFree;
m_firstFree = ptr;
++m_freeCount;
}
}
int getElementSize() const
{
return m_elemSize;
}
unsigned char* getPoolAddress()
{
return m_pool;
}
const unsigned char* getPoolAddress() const
{
return m_pool;
}
};
#endif //_BT_POOL_ALLOCATOR_H

View File

@ -0,0 +1,180 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SIMD_QUADWORD_H
#define SIMD_QUADWORD_H
#include "btScalar.h"
#include "btMinMax.h"
#if defined (__CELLOS_LV2) && defined (__SPU__)
#include <altivec.h>
#endif
/**@brief The btQuadWord class is base class for btVector3 and btQuaternion.
* Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword.
*/
#ifndef USE_LIBSPE2
ATTRIBUTE_ALIGNED16(class) btQuadWord
#else
class btQuadWord
#endif
{
protected:
#if defined (__SPU__) && defined (__CELLOS_LV2__)
union {
vec_float4 mVec128;
btScalar m_floats[4];
};
public:
vec_float4 get128() const
{
return mVec128;
}
protected:
#else //__CELLOS_LV2__ __SPU__
btScalar m_floats[4];
#endif //__CELLOS_LV2__ __SPU__
public:
/**@brief Return the x value */
SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
/**@brief Return the y value */
SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
/**@brief Return the z value */
SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
/**@brief Set the x value */
SIMD_FORCE_INLINE void setX(btScalar x) { m_floats[0] = x;};
/**@brief Set the y value */
SIMD_FORCE_INLINE void setY(btScalar y) { m_floats[1] = y;};
/**@brief Set the z value */
SIMD_FORCE_INLINE void setZ(btScalar z) { m_floats[2] = z;};
/**@brief Set the w value */
SIMD_FORCE_INLINE void setW(btScalar w) { m_floats[3] = w;};
/**@brief Return the x value */
SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
/**@brief Return the y value */
SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
/**@brief Return the z value */
SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
/**@brief Return the w value */
SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
//SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
//SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; }
SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; }
SIMD_FORCE_INLINE bool operator==(const btQuadWord& other) const
{
return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0]));
}
SIMD_FORCE_INLINE bool operator!=(const btQuadWord& other) const
{
return !(*this == other);
}
/**@brief Set x,y,z and zero w
* @param x Value of x
* @param y Value of y
* @param z Value of z
*/
SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z)
{
m_floats[0]=x;
m_floats[1]=y;
m_floats[2]=z;
m_floats[3] = 0.f;
}
/* void getValue(btScalar *m) const
{
m[0] = m_floats[0];
m[1] = m_floats[1];
m[2] = m_floats[2];
}
*/
/**@brief Set the values
* @param x Value of x
* @param y Value of y
* @param z Value of z
* @param w Value of w
*/
SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
{
m_floats[0]=x;
m_floats[1]=y;
m_floats[2]=z;
m_floats[3]=w;
}
/**@brief No initialization constructor */
SIMD_FORCE_INLINE btQuadWord()
// :m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.))
{
}
/**@brief Three argument constructor (zeros w)
* @param x Value of x
* @param y Value of y
* @param z Value of z
*/
SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z)
{
m_floats[0] = x, m_floats[1] = y, m_floats[2] = z, m_floats[3] = 0.0f;
}
/**@brief Initializing constructor
* @param x Value of x
* @param y Value of y
* @param z Value of z
* @param w Value of w
*/
SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
{
m_floats[0] = x, m_floats[1] = y, m_floats[2] = z, m_floats[3] = w;
}
/**@brief Set each element to the max of the current values and the values of another btQuadWord
* @param other The other btQuadWord to compare with
*/
SIMD_FORCE_INLINE void setMax(const btQuadWord& other)
{
btSetMax(m_floats[0], other.m_floats[0]);
btSetMax(m_floats[1], other.m_floats[1]);
btSetMax(m_floats[2], other.m_floats[2]);
btSetMax(m_floats[3], other.m_floats[3]);
}
/**@brief Set each element to the min of the current values and the values of another btQuadWord
* @param other The other btQuadWord to compare with
*/
SIMD_FORCE_INLINE void setMin(const btQuadWord& other)
{
btSetMin(m_floats[0], other.m_floats[0]);
btSetMin(m_floats[1], other.m_floats[1]);
btSetMin(m_floats[2], other.m_floats[2]);
btSetMin(m_floats[3], other.m_floats[3]);
}
};
#endif //SIMD_QUADWORD_H

View File

@ -0,0 +1,433 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SIMD__QUATERNION_H_
#define SIMD__QUATERNION_H_
#include "btVector3.h"
#include "btQuadWord.h"
/**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */
class btQuaternion : public btQuadWord {
public:
/**@brief No initialization constructor */
btQuaternion() {}
// template <typename btScalar>
// explicit Quaternion(const btScalar *v) : Tuple4<btScalar>(v) {}
/**@brief Constructor from scalars */
btQuaternion(const btScalar& x, const btScalar& y, const btScalar& z, const btScalar& w)
: btQuadWord(x, y, z, w)
{}
/**@brief Axis angle Constructor
* @param axis The axis which the rotation is around
* @param angle The magnitude of the rotation around the angle (Radians) */
btQuaternion(const btVector3& axis, const btScalar& angle)
{
setRotation(axis, angle);
}
/**@brief Constructor from Euler angles
* @param yaw Angle around Y unless BT_EULER_DEFAULT_ZYX defined then Z
* @param pitch Angle around X unless BT_EULER_DEFAULT_ZYX defined then Y
* @param roll Angle around Z unless BT_EULER_DEFAULT_ZYX defined then X */
btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
{
#ifndef BT_EULER_DEFAULT_ZYX
setEuler(yaw, pitch, roll);
#else
setEulerZYX(yaw, pitch, roll);
#endif
}
/**@brief Set the rotation using axis angle notation
* @param axis The axis around which to rotate
* @param angle The magnitude of the rotation in Radians */
void setRotation(const btVector3& axis, const btScalar& angle)
{
btScalar d = axis.length();
btAssert(d != btScalar(0.0));
btScalar s = btSin(angle * btScalar(0.5)) / d;
setValue(axis.x() * s, axis.y() * s, axis.z() * s,
btCos(angle * btScalar(0.5)));
}
/**@brief Set the quaternion using Euler angles
* @param yaw Angle around Y
* @param pitch Angle around X
* @param roll Angle around Z */
void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
{
btScalar halfYaw = btScalar(yaw) * btScalar(0.5);
btScalar halfPitch = btScalar(pitch) * btScalar(0.5);
btScalar halfRoll = btScalar(roll) * btScalar(0.5);
btScalar cosYaw = btCos(halfYaw);
btScalar sinYaw = btSin(halfYaw);
btScalar cosPitch = btCos(halfPitch);
btScalar sinPitch = btSin(halfPitch);
btScalar cosRoll = btCos(halfRoll);
btScalar sinRoll = btSin(halfRoll);
setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
}
/**@brief Set the quaternion using euler angles
* @param yaw Angle around Z
* @param pitch Angle around Y
* @param roll Angle around X */
void setEulerZYX(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
{
btScalar halfYaw = btScalar(yaw) * btScalar(0.5);
btScalar halfPitch = btScalar(pitch) * btScalar(0.5);
btScalar halfRoll = btScalar(roll) * btScalar(0.5);
btScalar cosYaw = btCos(halfYaw);
btScalar sinYaw = btSin(halfYaw);
btScalar cosPitch = btCos(halfPitch);
btScalar sinPitch = btSin(halfPitch);
btScalar cosRoll = btCos(halfRoll);
btScalar sinRoll = btSin(halfRoll);
setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
}
/**@brief Add two quaternions
* @param q The quaternion to add to this one */
SIMD_FORCE_INLINE btQuaternion& operator+=(const btQuaternion& q)
{
m_floats[0] += q.x(); m_floats[1] += q.y(); m_floats[2] += q.z(); m_floats[3] += q.m_floats[3];
return *this;
}
/**@brief Subtract out a quaternion
* @param q The quaternion to subtract from this one */
btQuaternion& operator-=(const btQuaternion& q)
{
m_floats[0] -= q.x(); m_floats[1] -= q.y(); m_floats[2] -= q.z(); m_floats[3] -= q.m_floats[3];
return *this;
}
/**@brief Scale this quaternion
* @param s The scalar to scale by */
btQuaternion& operator*=(const btScalar& s)
{
m_floats[0] *= s; m_floats[1] *= s; m_floats[2] *= s; m_floats[3] *= s;
return *this;
}
/**@brief Multiply this quaternion by q on the right
* @param q The other quaternion
* Equivilant to this = this * q */
btQuaternion& operator*=(const btQuaternion& q)
{
setValue(m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(),
m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(),
m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(),
m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z());
return *this;
}
/**@brief Return the dot product between this quaternion and another
* @param q The other quaternion */
btScalar dot(const btQuaternion& q) const
{
return m_floats[0] * q.x() + m_floats[1] * q.y() + m_floats[2] * q.z() + m_floats[3] * q.m_floats[3];
}
/**@brief Return the length squared of the quaternion */
btScalar length2() const
{
return dot(*this);
}
/**@brief Return the length of the quaternion */
btScalar length() const
{
return btSqrt(length2());
}
/**@brief Normalize the quaternion
* Such that x^2 + y^2 + z^2 +w^2 = 1 */
btQuaternion& normalize()
{
return *this /= length();
}
/**@brief Return a scaled version of this quaternion
* @param s The scale factor */
SIMD_FORCE_INLINE btQuaternion
operator*(const btScalar& s) const
{
return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s);
}
/**@brief Return an inversely scaled versionof this quaternion
* @param s The inverse scale factor */
btQuaternion operator/(const btScalar& s) const
{
btAssert(s != btScalar(0.0));
return *this * (btScalar(1.0) / s);
}
/**@brief Inversely scale this quaternion
* @param s The scale factor */
btQuaternion& operator/=(const btScalar& s)
{
btAssert(s != btScalar(0.0));
return *this *= btScalar(1.0) / s;
}
/**@brief Return a normalized version of this quaternion */
btQuaternion normalized() const
{
return *this / length();
}
/**@brief Return the angle between this quaternion and the other
* @param q The other quaternion */
btScalar angle(const btQuaternion& q) const
{
btScalar s = btSqrt(length2() * q.length2());
btAssert(s != btScalar(0.0));
return btAcos(dot(q) / s);
}
/**@brief Return the angle of rotation represented by this quaternion */
btScalar getAngle() const
{
btScalar s = btScalar(2.) * btAcos(m_floats[3]);
return s;
}
/**@brief Return the axis of the rotation represented by this quaternion */
btVector3 getAxis() const
{
btScalar s_squared = btScalar(1.) - btPow(m_floats[3], btScalar(2.));
if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero
return btVector3(1.0, 0.0, 0.0); // Arbitrary
btScalar s = btSqrt(s_squared);
return btVector3(m_floats[0] / s, m_floats[1] / s, m_floats[2] / s);
}
/**@brief Return the inverse of this quaternion */
btQuaternion inverse() const
{
return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
}
/**@brief Return the sum of this quaternion and the other
* @param q2 The other quaternion */
SIMD_FORCE_INLINE btQuaternion
operator+(const btQuaternion& q2) const
{
const btQuaternion& q1 = *this;
return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]);
}
/**@brief Return the difference between this quaternion and the other
* @param q2 The other quaternion */
SIMD_FORCE_INLINE btQuaternion
operator-(const btQuaternion& q2) const
{
const btQuaternion& q1 = *this;
return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]);
}
/**@brief Return the negative of this quaternion
* This simply negates each element */
SIMD_FORCE_INLINE btQuaternion operator-() const
{
const btQuaternion& q2 = *this;
return btQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2.m_floats[3]);
}
/**@todo document this and it's use */
SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const
{
btQuaternion diff,sum;
diff = *this - qd;
sum = *this + qd;
if( diff.dot(diff) > sum.dot(sum) )
return qd;
return (-qd);
}
/**@todo document this and it's use */
SIMD_FORCE_INLINE btQuaternion nearest( const btQuaternion& qd) const
{
btQuaternion diff,sum;
diff = *this - qd;
sum = *this + qd;
if( diff.dot(diff) < sum.dot(sum) )
return qd;
return (-qd);
}
/**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
* @param q The other quaternion to interpolate with
* @param t The ratio between this and q to interpolate. If t = 0 the result is this, if t=1 the result is q.
* Slerp interpolates assuming constant velocity. */
btQuaternion slerp(const btQuaternion& q, const btScalar& t) const
{
btScalar theta = angle(q);
if (theta != btScalar(0.0))
{
btScalar d = btScalar(1.0) / btSin(theta);
btScalar s0 = btSin((btScalar(1.0) - t) * theta);
btScalar s1 = btSin(t * theta);
if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
return btQuaternion((m_floats[0] * s0 + -q.x() * s1) * d,
(m_floats[1] * s0 + -q.y() * s1) * d,
(m_floats[2] * s0 + -q.z() * s1) * d,
(m_floats[3] * s0 + -q.m_floats[3] * s1) * d);
else
return btQuaternion((m_floats[0] * s0 + q.x() * s1) * d,
(m_floats[1] * s0 + q.y() * s1) * d,
(m_floats[2] * s0 + q.z() * s1) * d,
(m_floats[3] * s0 + q.m_floats[3] * s1) * d);
}
else
{
return *this;
}
}
static const btQuaternion& getIdentity()
{
static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.));
return identityQuat;
}
SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; }
};
/**@brief Return the negative of a quaternion */
SIMD_FORCE_INLINE btQuaternion
operator-(const btQuaternion& q)
{
return btQuaternion(-q.x(), -q.y(), -q.z(), -q.w());
}
/**@brief Return the product of two quaternions */
SIMD_FORCE_INLINE btQuaternion
operator*(const btQuaternion& q1, const btQuaternion& q2) {
return btQuaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(),
q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(),
q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z());
}
SIMD_FORCE_INLINE btQuaternion
operator*(const btQuaternion& q, const btVector3& w)
{
return btQuaternion( q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
-q.x() * w.x() - q.y() * w.y() - q.z() * w.z());
}
SIMD_FORCE_INLINE btQuaternion
operator*(const btVector3& w, const btQuaternion& q)
{
return btQuaternion( w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
-w.x() * q.x() - w.y() * q.y() - w.z() * q.z());
}
/**@brief Calculate the dot product between two quaternions */
SIMD_FORCE_INLINE btScalar
dot(const btQuaternion& q1, const btQuaternion& q2)
{
return q1.dot(q2);
}
/**@brief Return the length of a quaternion */
SIMD_FORCE_INLINE btScalar
length(const btQuaternion& q)
{
return q.length();
}
/**@brief Return the angle between two quaternions*/
SIMD_FORCE_INLINE btScalar
angle(const btQuaternion& q1, const btQuaternion& q2)
{
return q1.angle(q2);
}
/**@brief Return the inverse of a quaternion*/
SIMD_FORCE_INLINE btQuaternion
inverse(const btQuaternion& q)
{
return q.inverse();
}
/**@brief Return the result of spherical linear interpolation betwen two quaternions
* @param q1 The first quaternion
* @param q2 The second quaternion
* @param t The ration between q1 and q2. t = 0 return q1, t=1 returns q2
* Slerp assumes constant velocity between positions. */
SIMD_FORCE_INLINE btQuaternion
slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t)
{
return q1.slerp(q2, t);
}
SIMD_FORCE_INLINE btVector3
quatRotate(const btQuaternion& rotation, const btVector3& v)
{
btQuaternion q = rotation * v;
q *= rotation.inverse();
return btVector3(q.getX(),q.getY(),q.getZ());
}
SIMD_FORCE_INLINE btQuaternion
shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
{
btVector3 c = v0.cross(v1);
btScalar d = v0.dot(v1);
if (d < -1.0 + SIMD_EPSILON)
{
btVector3 n,unused;
btPlaneSpace1(v0,n,unused);
return btQuaternion(n.x(),n.y(),n.z(),0.0f); // just pick any vector that is orthogonal to v0
}
btScalar s = btSqrt((1.0f + d) * 2.0f);
btScalar rs = 1.0f / s;
return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f);
}
SIMD_FORCE_INLINE btQuaternion
shortestArcQuatNormalize2(btVector3& v0,btVector3& v1)
{
v0.normalize();
v1.normalize();
return shortestArcQuat(v0,v1);
}
#endif

View File

@ -0,0 +1,565 @@
/*
***************************************************************************************************
**
** profile.cpp
**
** Real-Time Hierarchical Profiling for Game Programming Gems 3
**
** by Greg Hjelstrom & Byon Garrabrant
**
***************************************************************************************************/
// Credits: The Clock class was inspired by the Timer classes in
// Ogre (www.ogre3d.org).
#include "btQuickprof.h"
#ifndef BT_NO_PROFILE
static btClock gProfileClock;
#ifdef __CELLOS_LV2__
#include <sys/sys_time.h>
#include <sys/time_util.h>
#include <stdio.h>
#endif
#if defined (SUNOS) || defined (__SUNOS__)
#include <stdio.h>
#endif
#if defined(WIN32) || defined(_WIN32)
#define BT_USE_WINDOWS_TIMERS
#define WIN32_LEAN_AND_MEAN
#define NOWINRES
#define NOMCX
#define NOIME
#ifdef _XBOX
#include <Xtl.h>
#else //_XBOX
#include <windows.h>
#endif //_XBOX
#include <time.h>
#else //_WIN32
#include <sys/time.h>
#endif //_WIN32
#define mymin(a,b) (a > b ? a : b)
struct btClockData
{
#ifdef BT_USE_WINDOWS_TIMERS
LARGE_INTEGER mClockFrequency;
DWORD mStartTick;
LONGLONG mPrevElapsedTime;
LARGE_INTEGER mStartTime;
#else
#ifdef __CELLOS_LV2__
uint64_t mStartTime;
#else
struct timeval mStartTime;
#endif
#endif //__CELLOS_LV2__
};
///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
btClock::btClock()
{
m_data = new btClockData;
#ifdef BT_USE_WINDOWS_TIMERS
QueryPerformanceFrequency(&m_data->mClockFrequency);
#endif
reset();
}
btClock::~btClock()
{
delete m_data;
}
btClock::btClock(const btClock& other)
{
m_data = new btClockData;
*m_data = *other.m_data;
}
btClock& btClock::operator=(const btClock& other)
{
*m_data = *other.m_data;
return *this;
}
/// Resets the initial reference time.
void btClock::reset()
{
#ifdef BT_USE_WINDOWS_TIMERS
QueryPerformanceCounter(&m_data->mStartTime);
m_data->mStartTick = GetTickCount();
m_data->mPrevElapsedTime = 0;
#else
#ifdef __CELLOS_LV2__
typedef uint64_t ClockSize;
ClockSize newTime;
//__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
SYS_TIMEBASE_GET( newTime );
m_data->mStartTime = newTime;
#else
gettimeofday(&m_data->mStartTime, 0);
#endif
#endif
}
/// Returns the time in ms since the last call to reset or since
/// the btClock was created.
unsigned long int btClock::getTimeMilliseconds()
{
#ifdef BT_USE_WINDOWS_TIMERS
LARGE_INTEGER currentTime;
QueryPerformanceCounter(&currentTime);
LONGLONG elapsedTime = currentTime.QuadPart -
m_data->mStartTime.QuadPart;
// Compute the number of millisecond ticks elapsed.
unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
m_data->mClockFrequency.QuadPart);
// Check for unexpected leaps in the Win32 performance counter.
// (This is caused by unexpected data across the PCI to ISA
// bridge, aka south bridge. See Microsoft KB274323.)
unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick;
signed long msecOff = (signed long)(msecTicks - elapsedTicks);
if (msecOff < -100 || msecOff > 100)
{
// Adjust the starting time forwards.
LONGLONG msecAdjustment = mymin(msecOff *
m_data->mClockFrequency.QuadPart / 1000, elapsedTime -
m_data->mPrevElapsedTime);
m_data->mStartTime.QuadPart += msecAdjustment;
elapsedTime -= msecAdjustment;
// Recompute the number of millisecond ticks elapsed.
msecTicks = (unsigned long)(1000 * elapsedTime /
m_data->mClockFrequency.QuadPart);
}
// Store the current elapsed time for adjustments next time.
m_data->mPrevElapsedTime = elapsedTime;
return msecTicks;
#else
#ifdef __CELLOS_LV2__
uint64_t freq=sys_time_get_timebase_frequency();
double dFreq=((double) freq) / 1000.0;
typedef uint64_t ClockSize;
ClockSize newTime;
SYS_TIMEBASE_GET( newTime );
//__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
#else
struct timeval currentTime;
gettimeofday(&currentTime, 0);
return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 +
(currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000;
#endif //__CELLOS_LV2__
#endif
}
/// Returns the time in us since the last call to reset or since
/// the Clock was created.
unsigned long int btClock::getTimeMicroseconds()
{
#ifdef BT_USE_WINDOWS_TIMERS
LARGE_INTEGER currentTime;
QueryPerformanceCounter(&currentTime);
LONGLONG elapsedTime = currentTime.QuadPart -
m_data->mStartTime.QuadPart;
// Compute the number of millisecond ticks elapsed.
unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
m_data->mClockFrequency.QuadPart);
// Check for unexpected leaps in the Win32 performance counter.
// (This is caused by unexpected data across the PCI to ISA
// bridge, aka south bridge. See Microsoft KB274323.)
unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick;
signed long msecOff = (signed long)(msecTicks - elapsedTicks);
if (msecOff < -100 || msecOff > 100)
{
// Adjust the starting time forwards.
LONGLONG msecAdjustment = mymin(msecOff *
m_data->mClockFrequency.QuadPart / 1000, elapsedTime -
m_data->mPrevElapsedTime);
m_data->mStartTime.QuadPart += msecAdjustment;
elapsedTime -= msecAdjustment;
}
// Store the current elapsed time for adjustments next time.
m_data->mPrevElapsedTime = elapsedTime;
// Convert to microseconds.
unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime /
m_data->mClockFrequency.QuadPart);
return usecTicks;
#else
#ifdef __CELLOS_LV2__
uint64_t freq=sys_time_get_timebase_frequency();
double dFreq=((double) freq)/ 1000000.0;
typedef uint64_t ClockSize;
ClockSize newTime;
//__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
SYS_TIMEBASE_GET( newTime );
return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
#else
struct timeval currentTime;
gettimeofday(&currentTime, 0);
return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 +
(currentTime.tv_usec - m_data->mStartTime.tv_usec);
#endif//__CELLOS_LV2__
#endif
}
inline void Profile_Get_Ticks(unsigned long int * ticks)
{
*ticks = gProfileClock.getTimeMicroseconds();
}
inline float Profile_Get_Tick_Rate(void)
{
// return 1000000.f;
return 1000.f;
}
/***************************************************************************************************
**
** CProfileNode
**
***************************************************************************************************/
/***********************************************************************************************
* INPUT: *
* name - pointer to a static string which is the name of this profile node *
* parent - parent pointer *
* *
* WARNINGS: *
* The name is assumed to be a static pointer, only the pointer is stored and compared for *
* efficiency reasons. *
*=============================================================================================*/
CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) :
Name( name ),
TotalCalls( 0 ),
TotalTime( 0 ),
StartTime( 0 ),
RecursionCounter( 0 ),
Parent( parent ),
Child( NULL ),
Sibling( NULL )
{
Reset();
}
void CProfileNode::CleanupMemory()
{
delete ( Child);
Child = NULL;
delete ( Sibling);
Sibling = NULL;
}
CProfileNode::~CProfileNode( void )
{
delete ( Child);
delete ( Sibling);
}
/***********************************************************************************************
* INPUT: *
* name - static string pointer to the name of the node we are searching for *
* *
* WARNINGS: *
* All profile names are assumed to be static strings so this function uses pointer compares *
* to find the named node. *
*=============================================================================================*/
CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
{
// Try to find this sub node
CProfileNode * child = Child;
while ( child ) {
if ( child->Name == name ) {
return child;
}
child = child->Sibling;
}
// We didn't find it, so add it
CProfileNode * node = new CProfileNode( name, this );
node->Sibling = Child;
Child = node;
return node;
}
void CProfileNode::Reset( void )
{
TotalCalls = 0;
TotalTime = 0.0f;
if ( Child ) {
Child->Reset();
}
if ( Sibling ) {
Sibling->Reset();
}
}
void CProfileNode::Call( void )
{
TotalCalls++;
if (RecursionCounter++ == 0) {
Profile_Get_Ticks(&StartTime);
}
}
bool CProfileNode::Return( void )
{
if ( --RecursionCounter == 0 && TotalCalls != 0 ) {
unsigned long int time;
Profile_Get_Ticks(&time);
time-=StartTime;
TotalTime += (float)time / Profile_Get_Tick_Rate();
}
return ( RecursionCounter == 0 );
}
/***************************************************************************************************
**
** CProfileIterator
**
***************************************************************************************************/
CProfileIterator::CProfileIterator( CProfileNode * start )
{
CurrentParent = start;
CurrentChild = CurrentParent->Get_Child();
}
void CProfileIterator::First(void)
{
CurrentChild = CurrentParent->Get_Child();
}
void CProfileIterator::Next(void)
{
CurrentChild = CurrentChild->Get_Sibling();
}
bool CProfileIterator::Is_Done(void)
{
return CurrentChild == NULL;
}
void CProfileIterator::Enter_Child( int index )
{
CurrentChild = CurrentParent->Get_Child();
while ( (CurrentChild != NULL) && (index != 0) ) {
index--;
CurrentChild = CurrentChild->Get_Sibling();
}
if ( CurrentChild != NULL ) {
CurrentParent = CurrentChild;
CurrentChild = CurrentParent->Get_Child();
}
}
void CProfileIterator::Enter_Parent( void )
{
if ( CurrentParent->Get_Parent() != NULL ) {
CurrentParent = CurrentParent->Get_Parent();
}
CurrentChild = CurrentParent->Get_Child();
}
/***************************************************************************************************
**
** CProfileManager
**
***************************************************************************************************/
CProfileNode CProfileManager::Root( "Root", NULL );
CProfileNode * CProfileManager::CurrentNode = &CProfileManager::Root;
int CProfileManager::FrameCounter = 0;
unsigned long int CProfileManager::ResetTime = 0;
/***********************************************************************************************
* CProfileManager::Start_Profile -- Begin a named profile *
* *
* Steps one level deeper into the tree, if a child already exists with the specified name *
* then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
* *
* INPUT: *
* name - name of this profiling record *
* *
* WARNINGS: *
* The string used is assumed to be a static string; pointer compares are used throughout *
* the profiling code for efficiency. *
*=============================================================================================*/
void CProfileManager::Start_Profile( const char * name )
{
if (name != CurrentNode->Get_Name()) {
CurrentNode = CurrentNode->Get_Sub_Node( name );
}
CurrentNode->Call();
}
/***********************************************************************************************
* CProfileManager::Stop_Profile -- Stop timing and record the results. *
*=============================================================================================*/
void CProfileManager::Stop_Profile( void )
{
// Return will indicate whether we should back up to our parent (we may
// be profiling a recursive function)
if (CurrentNode->Return()) {
CurrentNode = CurrentNode->Get_Parent();
}
}
/***********************************************************************************************
* CProfileManager::Reset -- Reset the contents of the profiling system *
* *
* This resets everything except for the tree structure. All of the timing data is reset. *
*=============================================================================================*/
void CProfileManager::Reset( void )
{
gProfileClock.reset();
Root.Reset();
Root.Call();
FrameCounter = 0;
Profile_Get_Ticks(&ResetTime);
}
/***********************************************************************************************
* CProfileManager::Increment_Frame_Counter -- Increment the frame counter *
*=============================================================================================*/
void CProfileManager::Increment_Frame_Counter( void )
{
FrameCounter++;
}
/***********************************************************************************************
* CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
*=============================================================================================*/
float CProfileManager::Get_Time_Since_Reset( void )
{
unsigned long int time;
Profile_Get_Ticks(&time);
time -= ResetTime;
return (float)time / Profile_Get_Tick_Rate();
}
#include <stdio.h>
void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing)
{
profileIterator->First();
if (profileIterator->Is_Done())
return;
float accumulated_time=0,parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
int i;
int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
for (i=0;i<spacing;i++) printf(".");
printf("----------------------------------\n");
for (i=0;i<spacing;i++) printf(".");
printf("Profiling: %s (total running time: %.3f ms) ---\n", profileIterator->Get_Current_Parent_Name(), parent_time );
float totalTime = 0.f;
int numChildren = 0;
for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next())
{
numChildren++;
float current_total_time = profileIterator->Get_Current_Total_Time();
accumulated_time += current_total_time;
float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
{
int i; for (i=0;i<spacing;i++) printf(".");
}
printf("%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n",i, profileIterator->Get_Current_Name(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls());
totalTime += current_total_time;
//recurse into children
}
if (parent_time < accumulated_time)
{
printf("what's wrong\n");
}
for (i=0;i<spacing;i++) printf(".");
printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:",parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
for (i=0;i<numChildren;i++)
{
profileIterator->Enter_Child(i);
dumpRecursive(profileIterator,spacing+3);
profileIterator->Enter_Parent();
}
}
void CProfileManager::dumpAll()
{
CProfileIterator* profileIterator = 0;
profileIterator = CProfileManager::Get_Iterator();
dumpRecursive(profileIterator,0);
CProfileManager::Release_Iterator(profileIterator);
}
#endif //BT_NO_PROFILE

View File

@ -0,0 +1,196 @@
/***************************************************************************************************
**
** Real-Time Hierarchical Profiling for Game Programming Gems 3
**
** by Greg Hjelstrom & Byon Garrabrant
**
***************************************************************************************************/
// Credits: The Clock class was inspired by the Timer classes in
// Ogre (www.ogre3d.org).
#ifndef QUICK_PROF_H
#define QUICK_PROF_H
//To disable built-in profiling, please comment out next line
//#define BT_NO_PROFILE 1
#ifndef BT_NO_PROFILE
#include <stdio.h>//@todo remove this, backwards compatibility
#include "btScalar.h"
#include "btAlignedAllocator.h"
#include <new>
#define USE_BT_CLOCK 1
#ifdef USE_BT_CLOCK
///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
class btClock
{
public:
btClock();
btClock(const btClock& other);
btClock& operator=(const btClock& other);
~btClock();
/// Resets the initial reference time.
void reset();
/// Returns the time in ms since the last call to reset or since
/// the btClock was created.
unsigned long int getTimeMilliseconds();
/// Returns the time in us since the last call to reset or since
/// the Clock was created.
unsigned long int getTimeMicroseconds();
private:
struct btClockData* m_data;
};
#endif //USE_BT_CLOCK
///A node in the Profile Hierarchy Tree
class CProfileNode {
public:
CProfileNode( const char * name, CProfileNode * parent );
~CProfileNode( void );
CProfileNode * Get_Sub_Node( const char * name );
CProfileNode * Get_Parent( void ) { return Parent; }
CProfileNode * Get_Sibling( void ) { return Sibling; }
CProfileNode * Get_Child( void ) { return Child; }
void CleanupMemory();
void Reset( void );
void Call( void );
bool Return( void );
const char * Get_Name( void ) { return Name; }
int Get_Total_Calls( void ) { return TotalCalls; }
float Get_Total_Time( void ) { return TotalTime; }
protected:
const char * Name;
int TotalCalls;
float TotalTime;
unsigned long int StartTime;
int RecursionCounter;
CProfileNode * Parent;
CProfileNode * Child;
CProfileNode * Sibling;
};
///An iterator to navigate through the tree
class CProfileIterator
{
public:
// Access all the children of the current parent
void First(void);
void Next(void);
bool Is_Done(void);
bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
void Enter_Child( int index ); // Make the given child the new parent
void Enter_Largest_Child( void ); // Make the largest child the new parent
void Enter_Parent( void ); // Make the current parent's parent the new parent
// Access the current child
const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); }
int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); }
float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); }
// Access the current parent
const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); }
int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); }
float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); }
protected:
CProfileNode * CurrentParent;
CProfileNode * CurrentChild;
CProfileIterator( CProfileNode * start );
friend class CProfileManager;
};
///The Manager for the Profile system
class CProfileManager {
public:
static void Start_Profile( const char * name );
static void Stop_Profile( void );
static void CleanupMemory(void)
{
Root.CleanupMemory();
}
static void Reset( void );
static void Increment_Frame_Counter( void );
static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; }
static float Get_Time_Since_Reset( void );
static CProfileIterator * Get_Iterator( void )
{
return new CProfileIterator( &Root );
}
static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); }
static void dumpRecursive(CProfileIterator* profileIterator, int spacing);
static void dumpAll();
private:
static CProfileNode Root;
static CProfileNode * CurrentNode;
static int FrameCounter;
static unsigned long int ResetTime;
};
///ProfileSampleClass is a simple way to profile a function's scope
///Use the BT_PROFILE macro at the start of scope to time
class CProfileSample {
public:
CProfileSample( const char * name )
{
CProfileManager::Start_Profile( name );
}
~CProfileSample( void )
{
CProfileManager::Stop_Profile();
}
};
#define BT_PROFILE( name ) CProfileSample __profile( name )
#else
#define BT_PROFILE( name )
#endif //#ifndef BT_NO_PROFILE
#endif //QUICK_PROF_H

View File

@ -0,0 +1,42 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef GEN_RANDOM_H
#define GEN_RANDOM_H
#ifdef MT19937
#include <limits.h>
#include <mt19937.h>
#define GEN_RAND_MAX UINT_MAX
SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); }
SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); }
#else
#include <stdlib.h>
#define GEN_RAND_MAX RAND_MAX
SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); }
SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); }
#endif
#endif

View File

@ -0,0 +1,524 @@
/*
Copyright (c) 2003-2009 Erwin Coumans http://bullet.googlecode.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SIMD___SCALAR_H
#define SIMD___SCALAR_H
#ifdef BT_MANAGED_CODE
//Aligned data types not supported in managed code
#pragma unmanaged
#endif
#include <math.h>
#include <stdlib.h>//size_t for MSVC 6.0
#include <cstdlib>
#include <cfloat>
#include <float.h>
/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
#define BT_BULLET_VERSION 277
inline int btGetVersion()
{
return BT_BULLET_VERSION;
}
#if defined(DEBUG) || defined (_DEBUG)
#define BT_DEBUG
#endif
#ifdef _WIN32
#if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
#define SIMD_FORCE_INLINE inline
#define ATTRIBUTE_ALIGNED16(a) a
#define ATTRIBUTE_ALIGNED64(a) a
#define ATTRIBUTE_ALIGNED128(a) a
#else
//#define BT_HAS_ALIGNED_ALLOCATOR
#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
#define SIMD_FORCE_INLINE __forceinline
#define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
#define ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
#define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a
#ifdef _XBOX
#define BT_USE_VMX128
#include <ppcintrinsics.h>
#define BT_HAVE_NATIVE_FSEL
#define btFsel(a,b,c) __fsel((a),(b),(c))
#else
#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))
#define BT_USE_SSE
#include <emmintrin.h>
#endif
#endif//_XBOX
#endif //__MINGW32__
#include <assert.h>
#ifdef BT_DEBUG
#define btAssert assert
#else
#define btAssert(x)
#endif
//btFullAssert is optional, slows down a lot
#define btFullAssert(x)
#define btLikely(_c) _c
#define btUnlikely(_c) _c
#else
#if defined (__CELLOS_LV2__)
#define SIMD_FORCE_INLINE inline __attribute__((always_inline))
#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
#ifndef assert
#include <assert.h>
#endif
#ifdef BT_DEBUG
#ifdef __SPU__
#include <spu_printf.h>
#define printf spu_printf
#define btAssert(x) {if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}}
#else
#define btAssert assert
#endif
#else
#define btAssert(x)
#endif
//btFullAssert is optional, slows down a lot
#define btFullAssert(x)
#define btLikely(_c) _c
#define btUnlikely(_c) _c
#else
#ifdef USE_LIBSPE2
#define SIMD_FORCE_INLINE __inline
#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
#ifndef assert
#include <assert.h>
#endif
#ifdef BT_DEBUG
#define btAssert assert
#else
#define btAssert(x)
#endif
//btFullAssert is optional, slows down a lot
#define btFullAssert(x)
#define btLikely(_c) __builtin_expect((_c), 1)
#define btUnlikely(_c) __builtin_expect((_c), 0)
#else
//non-windows systems
#if (defined (__APPLE__) && defined (__i386__) && (!defined (BT_USE_DOUBLE_PRECISION)))
#define BT_USE_SSE
#include <emmintrin.h>
#define SIMD_FORCE_INLINE inline
///@todo: check out alignment methods for other platforms/compilers
#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
#ifndef assert
#include <assert.h>
#endif
#if defined(DEBUG) || defined (_DEBUG)
#define btAssert assert
#else
#define btAssert(x)
#endif
//btFullAssert is optional, slows down a lot
#define btFullAssert(x)
#define btLikely(_c) _c
#define btUnlikely(_c) _c
#else
#define SIMD_FORCE_INLINE inline
///@todo: check out alignment methods for other platforms/compilers
///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
///#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
#define ATTRIBUTE_ALIGNED16(a) a
#define ATTRIBUTE_ALIGNED64(a) a
#define ATTRIBUTE_ALIGNED128(a) a
#ifndef assert
#include <assert.h>
#endif
#if defined(DEBUG) || defined (_DEBUG)
#define btAssert assert
#else
#define btAssert(x)
#endif
//btFullAssert is optional, slows down a lot
#define btFullAssert(x)
#define btLikely(_c) _c
#define btUnlikely(_c) _c
#endif //__APPLE__
#endif // LIBSPE2
#endif //__CELLOS_LV2__
#endif
///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
#if defined(BT_USE_DOUBLE_PRECISION)
typedef double btScalar;
//this number could be bigger in double precision
#define BT_LARGE_FLOAT 1e30
#else
typedef float btScalar;
//keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX
#define BT_LARGE_FLOAT 1e18f
#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*) { } \
#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS)
SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); }
SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); }
SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); }
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); }
SIMD_FORCE_INLINE btScalar btAsin(btScalar 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); }
SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); }
SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); }
SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); }
SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmod(x,y); }
#else
SIMD_FORCE_INLINE btScalar btSqrt(btScalar y)
{
#ifdef USE_APPROXIMATION
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;
#else
return sqrtf(y);
#endif
}
SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); }
SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); }
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);
}
SIMD_FORCE_INLINE btScalar btAsin(btScalar 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); }
SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); }
SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); }
SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); }
SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmodf(x,y); }
#endif
#define SIMD_2_PI btScalar(6.283185307179586232)
#define SIMD_PI (SIMD_2_PI * btScalar(0.5))
#define SIMD_HALF_PI (SIMD_2_PI * btScalar(0.25))
#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0))
#define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI)
#define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490)
#define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x)))) /* reciprocal square root */
#ifdef BT_USE_DOUBLE_PRECISION
#define SIMD_EPSILON DBL_EPSILON
#define SIMD_INFINITY DBL_MAX
#else
#define SIMD_EPSILON FLT_EPSILON
#define SIMD_INFINITY FLT_MAX
#endif
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;
}
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));
}
SIMD_FORCE_INLINE bool btGreaterEqual (btScalar a, btScalar eps) {
return (!((a) <= eps));
}
SIMD_FORCE_INLINE int btIsNegative(btScalar x) {
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
#ifndef btFsel
SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar 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;
}
///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));
}
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));
}
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);
#else
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;
}
//PCK: endian swapping functions
SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val)
{
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));
}
SIMD_FORCE_INLINE unsigned btSwapEndian(int val)
{
return btSwapEndian((unsigned)val);
}
SIMD_FORCE_INLINE unsigned short btSwapEndian(short val)
{
return btSwapEndian((unsigned short) val);
}
///btSwapFloat uses using char pointers to swap the endianness
////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values
///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754.
///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception.
///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you.
///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;
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;
dst[0] = src[3];
dst[1] = src[2];
dst[2] = src[1];
dst[3] = src[0];
return d;
}
// swap using char pointers
SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst)
{
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];
}
// unswap using char pointers
SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src)
{
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];
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;
}
}
///rudimentary class to provide type info
struct btTypedObject
{
btTypedObject(int objectType)
:m_objectType(objectType)
{
}
int m_objectType;
inline int getObjectType() const
{
return m_objectType;
}
};
#endif //SIMD___SCALAR_H

View File

@ -0,0 +1,577 @@
unsigned char sBulletDNAstr64[]= {
83,68,78,65,78,65,77,69,-79,0,0,0,109,95,115,105,122,101,0,109,
95,99,97,112,97,99,105,116,121,0,42,109,95,100,97,116,97,0,109,95,
99,111,108,108,105,115,105,111,110,83,104,97,112,101,115,0,109,95,99,111,
108,108,105,115,105,111,110,79,98,106,101,99,116,115,0,109,95,99,111,110,
115,116,114,97,105,110,116,115,0,42,102,105,114,115,116,0,42,108,97,115,
116,0,109,95,102,108,111,97,116,115,91,52,93,0,109,95,101,108,91,51,
93,0,109,95,98,97,115,105,115,0,109,95,111,114,105,103,105,110,0,109,
95,114,111,111,116,78,111,100,101,73,110,100,101,120,0,109,95,115,117,98,
116,114,101,101,83,105,122,101,0,109,95,113,117,97,110,116,105,122,101,100,
65,97,98,98,77,105,110,91,51,93,0,109,95,113,117,97,110,116,105,122,
101,100,65,97,98,98,77,97,120,91,51,93,0,109,95,97,97,98,98,77,
105,110,79,114,103,0,109,95,97,97,98,98,77,97,120,79,114,103,0,109,
95,101,115,99,97,112,101,73,110,100,101,120,0,109,95,115,117,98,80,97,
114,116,0,109,95,116,114,105,97,110,103,108,101,73,110,100,101,120,0,109,
95,112,97,100,91,52,93,0,109,95,101,115,99,97,112,101,73,110,100,101,
120,79,114,84,114,105,97,110,103,108,101,73,110,100,101,120,0,109,95,98,
118,104,65,97,98,98,77,105,110,0,109,95,98,118,104,65,97,98,98,77,
97,120,0,109,95,98,118,104,81,117,97,110,116,105,122,97,116,105,111,110,
0,109,95,99,117,114,78,111,100,101,73,110,100,101,120,0,109,95,117,115,
101,81,117,97,110,116,105,122,97,116,105,111,110,0,109,95,110,117,109,67,
111,110,116,105,103,117,111,117,115,76,101,97,102,78,111,100,101,115,0,109,
95,110,117,109,81,117,97,110,116,105,122,101,100,67,111,110,116,105,103,117,
111,117,115,78,111,100,101,115,0,42,109,95,99,111,110,116,105,103,117,111,
117,115,78,111,100,101,115,80,116,114,0,42,109,95,113,117,97,110,116,105,
122,101,100,67,111,110,116,105,103,117,111,117,115,78,111,100,101,115,80,116,
114,0,42,109,95,115,117,98,84,114,101,101,73,110,102,111,80,116,114,0,
109,95,116,114,97,118,101,114,115,97,108,77,111,100,101,0,109,95,110,117,
109,83,117,98,116,114,101,101,72,101,97,100,101,114,115,0,42,109,95,110,
97,109,101,0,109,95,115,104,97,112,101,84,121,112,101,0,109,95,112,97,
100,100,105,110,103,91,52,93,0,109,95,99,111,108,108,105,115,105,111,110,
83,104,97,112,101,68,97,116,97,0,109,95,108,111,99,97,108,83,99,97,
108,105,110,103,0,109,95,112,108,97,110,101,78,111,114,109,97,108,0,109,
95,112,108,97,110,101,67,111,110,115,116,97,110,116,0,109,95,105,109,112,
108,105,99,105,116,83,104,97,112,101,68,105,109,101,110,115,105,111,110,115,
0,109,95,99,111,108,108,105,115,105,111,110,77,97,114,103,105,110,0,109,
95,112,97,100,100,105,110,103,0,109,95,112,111,115,0,109,95,114,97,100,
105,117,115,0,109,95,99,111,110,118,101,120,73,110,116,101,114,110,97,108,
83,104,97,112,101,68,97,116,97,0,42,109,95,108,111,99,97,108,80,111,
115,105,116,105,111,110,65,114,114,97,121,80,116,114,0,109,95,108,111,99,
97,108,80,111,115,105,116,105,111,110,65,114,114,97,121,83,105,122,101,0,
109,95,118,97,108,117,101,0,109,95,112,97,100,91,50,93,0,109,95,118,
97,108,117,101,115,91,51,93,0,42,109,95,118,101,114,116,105,99,101,115,
51,102,0,42,109,95,118,101,114,116,105,99,101,115,51,100,0,42,109,95,
105,110,100,105,99,101,115,51,50,0,42,109,95,51,105,110,100,105,99,101,
115,49,54,0,42,109,95,105,110,100,105,99,101,115,49,54,0,109,95,110,
117,109,84,114,105,97,110,103,108,101,115,0,109,95,110,117,109,86,101,114,
116,105,99,101,115,0,42,109,95,109,101,115,104,80,97,114,116,115,80,116,
114,0,109,95,115,99,97,108,105,110,103,0,109,95,110,117,109,77,101,115,
104,80,97,114,116,115,0,109,95,109,101,115,104,73,110,116,101,114,102,97,
99,101,0,42,109,95,113,117,97,110,116,105,122,101,100,70,108,111,97,116,
66,118,104,0,42,109,95,113,117,97,110,116,105,122,101,100,68,111,117,98,
108,101,66,118,104,0,42,109,95,116,114,105,97,110,103,108,101,73,110,102,
111,77,97,112,0,109,95,112,97,100,51,91,52,93,0,109,95,116,114,97,
110,115,102,111,114,109,0,42,109,95,99,104,105,108,100,83,104,97,112,101,
0,109,95,99,104,105,108,100,83,104,97,112,101,84,121,112,101,0,109,95,
99,104,105,108,100,77,97,114,103,105,110,0,42,109,95,99,104,105,108,100,
83,104,97,112,101,80,116,114,0,109,95,110,117,109,67,104,105,108,100,83,
104,97,112,101,115,0,109,95,117,112,65,120,105,115,0,109,95,102,108,97,
103,115,0,109,95,101,100,103,101,86,48,86,49,65,110,103,108,101,0,109,
95,101,100,103,101,86,49,86,50,65,110,103,108,101,0,109,95,101,100,103,
101,86,50,86,48,65,110,103,108,101,0,42,109,95,104,97,115,104,84,97,
98,108,101,80,116,114,0,42,109,95,110,101,120,116,80,116,114,0,42,109,
95,118,97,108,117,101,65,114,114,97,121,80,116,114,0,42,109,95,107,101,
121,65,114,114,97,121,80,116,114,0,109,95,99,111,110,118,101,120,69,112,
115,105,108,111,110,0,109,95,112,108,97,110,97,114,69,112,115,105,108,111,
110,0,109,95,101,113,117,97,108,86,101,114,116,101,120,84,104,114,101,115,
104,111,108,100,0,109,95,101,100,103,101,68,105,115,116,97,110,99,101,84,
104,114,101,115,104,111,108,100,0,109,95,122,101,114,111,65,114,101,97,84,
104,114,101,115,104,111,108,100,0,109,95,110,101,120,116,83,105,122,101,0,
109,95,104,97,115,104,84,97,98,108,101,83,105,122,101,0,109,95,110,117,
109,86,97,108,117,101,115,0,109,95,110,117,109,75,101,121,115,0,109,95,
103,105,109,112,97,99,116,83,117,98,84,121,112,101,0,42,109,95,117,110,
115,99,97,108,101,100,80,111,105,110,116,115,70,108,111,97,116,80,116,114,
0,42,109,95,117,110,115,99,97,108,101,100,80,111,105,110,116,115,68,111,
117,98,108,101,80,116,114,0,109,95,110,117,109,85,110,115,99,97,108,101,
100,80,111,105,110,116,115,0,109,95,112,97,100,100,105,110,103,51,91,52,
93,0,42,109,95,98,114,111,97,100,112,104,97,115,101,72,97,110,100,108,
101,0,42,109,95,99,111,108,108,105,115,105,111,110,83,104,97,112,101,0,
42,109,95,114,111,111,116,67,111,108,108,105,115,105,111,110,83,104,97,112,
101,0,109,95,119,111,114,108,100,84,114,97,110,115,102,111,114,109,0,109,
95,105,110,116,101,114,112,111,108,97,116,105,111,110,87,111,114,108,100,84,
114,97,110,115,102,111,114,109,0,109,95,105,110,116,101,114,112,111,108,97,
116,105,111,110,76,105,110,101,97,114,86,101,108,111,99,105,116,121,0,109,
95,105,110,116,101,114,112,111,108,97,116,105,111,110,65,110,103,117,108,97,
114,86,101,108,111,99,105,116,121,0,109,95,97,110,105,115,111,116,114,111,
112,105,99,70,114,105,99,116,105,111,110,0,109,95,99,111,110,116,97,99,
116,80,114,111,99,101,115,115,105,110,103,84,104,114,101,115,104,111,108,100,
0,109,95,100,101,97,99,116,105,118,97,116,105,111,110,84,105,109,101,0,
109,95,102,114,105,99,116,105,111,110,0,109,95,114,101,115,116,105,116,117,
116,105,111,110,0,109,95,104,105,116,70,114,97,99,116,105,111,110,0,109,
95,99,99,100,83,119,101,112,116,83,112,104,101,114,101,82,97,100,105,117,
115,0,109,95,99,99,100,77,111,116,105,111,110,84,104,114,101,115,104,111,
108,100,0,109,95,104,97,115,65,110,105,115,111,116,114,111,112,105,99,70,
114,105,99,116,105,111,110,0,109,95,99,111,108,108,105,115,105,111,110,70,
108,97,103,115,0,109,95,105,115,108,97,110,100,84,97,103,49,0,109,95,
99,111,109,112,97,110,105,111,110,73,100,0,109,95,97,99,116,105,118,97,
116,105,111,110,83,116,97,116,101,49,0,109,95,105,110,116,101,114,110,97,
108,84,121,112,101,0,109,95,99,104,101,99,107,67,111,108,108,105,100,101,
87,105,116,104,0,109,95,99,111,108,108,105,115,105,111,110,79,98,106,101,
99,116,68,97,116,97,0,109,95,105,110,118,73,110,101,114,116,105,97,84,
101,110,115,111,114,87,111,114,108,100,0,109,95,108,105,110,101,97,114,86,
101,108,111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,86,101,108,
111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,70,97,99,116,111,
114,0,109,95,108,105,110,101,97,114,70,97,99,116,111,114,0,109,95,103,
114,97,118,105,116,121,0,109,95,103,114,97,118,105,116,121,95,97,99,99,
101,108,101,114,97,116,105,111,110,0,109,95,105,110,118,73,110,101,114,116,
105,97,76,111,99,97,108,0,109,95,116,111,116,97,108,70,111,114,99,101,
0,109,95,116,111,116,97,108,84,111,114,113,117,101,0,109,95,105,110,118,
101,114,115,101,77,97,115,115,0,109,95,108,105,110,101,97,114,68,97,109,
112,105,110,103,0,109,95,97,110,103,117,108,97,114,68,97,109,112,105,110,
103,0,109,95,97,100,100,105,116,105,111,110,97,108,68,97,109,112,105,110,
103,70,97,99,116,111,114,0,109,95,97,100,100,105,116,105,111,110,97,108,
76,105,110,101,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,
108,100,83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,
103,117,108,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,
100,83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,
117,108,97,114,68,97,109,112,105,110,103,70,97,99,116,111,114,0,109,95,
108,105,110,101,97,114,83,108,101,101,112,105,110,103,84,104,114,101,115,104,
111,108,100,0,109,95,97,110,103,117,108,97,114,83,108,101,101,112,105,110,
103,84,104,114,101,115,104,111,108,100,0,109,95,97,100,100,105,116,105,111,
110,97,108,68,97,109,112,105,110,103,0,109,95,110,117,109,67,111,110,115,
116,114,97,105,110,116,82,111,119,115,0,110,117,98,0,42,109,95,114,98,
65,0,42,109,95,114,98,66,0,109,95,111,98,106,101,99,116,84,121,112,
101,0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,84,121,
112,101,0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,73,
100,0,109,95,110,101,101,100,115,70,101,101,100,98,97,99,107,0,109,95,
97,112,112,108,105,101,100,73,109,112,117,108,115,101,0,109,95,100,98,103,
68,114,97,119,83,105,122,101,0,109,95,100,105,115,97,98,108,101,67,111,
108,108,105,115,105,111,110,115,66,101,116,119,101,101,110,76,105,110,107,101,
100,66,111,100,105,101,115,0,109,95,112,97,100,52,91,52,93,0,109,95,
116,121,112,101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,
95,112,105,118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,
0,109,95,114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,
109,101,0,109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,
109,101,65,0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,
101,110,97,98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,
95,109,111,116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,
0,109,95,109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,
95,108,111,119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,
105,109,105,116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,
0,109,95,98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,
120,97,116,105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,
83,112,97,110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,
95,116,119,105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,
0,109,95,108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,
109,95,108,105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,
95,97,110,103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,
95,97,110,103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,
95,117,115,101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,
114,97,109,101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,
67,111,110,115,116,114,97,105,110,116,70,114,97,109,101,0,84,89,80,69,
58,0,0,0,99,104,97,114,0,117,99,104,97,114,0,115,104,111,114,116,
0,117,115,104,111,114,116,0,105,110,116,0,108,111,110,103,0,117,108,111,
110,103,0,102,108,111,97,116,0,100,111,117,98,108,101,0,118,111,105,100,
0,80,111,105,110,116,101,114,65,114,114,97,121,0,98,116,80,104,121,115,
105,99,115,83,121,115,116,101,109,0,76,105,115,116,66,97,115,101,0,98,
116,86,101,99,116,111,114,51,70,108,111,97,116,68,97,116,97,0,98,116,
86,101,99,116,111,114,51,68,111,117,98,108,101,68,97,116,97,0,98,116,
77,97,116,114,105,120,51,120,51,70,108,111,97,116,68,97,116,97,0,98,
116,77,97,116,114,105,120,51,120,51,68,111,117,98,108,101,68,97,116,97,
0,98,116,84,114,97,110,115,102,111,114,109,70,108,111,97,116,68,97,116,
97,0,98,116,84,114,97,110,115,102,111,114,109,68,111,117,98,108,101,68,
97,116,97,0,98,116,66,118,104,83,117,98,116,114,101,101,73,110,102,111,
68,97,116,97,0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78,
111,100,101,70,108,111,97,116,68,97,116,97,0,98,116,79,112,116,105,109,
105,122,101,100,66,118,104,78,111,100,101,68,111,117,98,108,101,68,97,116,
97,0,98,116,81,117,97,110,116,105,122,101,100,66,118,104,78,111,100,101,
68,97,116,97,0,98,116,81,117,97,110,116,105,122,101,100,66,118,104,70,
108,111,97,116,68,97,116,97,0,98,116,81,117,97,110,116,105,122,101,100,
66,118,104,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108,108,
105,115,105,111,110,83,104,97,112,101,68,97,116,97,0,98,116,83,116,97,
116,105,99,80,108,97,110,101,83,104,97,112,101,68,97,116,97,0,98,116,
67,111,110,118,101,120,73,110,116,101,114,110,97,108,83,104,97,112,101,68,
97,116,97,0,98,116,80,111,115,105,116,105,111,110,65,110,100,82,97,100,
105,117,115,0,98,116,77,117,108,116,105,83,112,104,101,114,101,83,104,97,
112,101,68,97,116,97,0,98,116,73,110,116,73,110,100,101,120,68,97,116,
97,0,98,116,83,104,111,114,116,73,110,116,73,110,100,101,120,68,97,116,
97,0,98,116,83,104,111,114,116,73,110,116,73,110,100,101,120,84,114,105,
112,108,101,116,68,97,116,97,0,98,116,77,101,115,104,80,97,114,116,68,
97,116,97,0,98,116,83,116,114,105,100,105,110,103,77,101,115,104,73,110,
116,101,114,102,97,99,101,68,97,116,97,0,98,116,84,114,105,97,110,103,
108,101,77,101,115,104,83,104,97,112,101,68,97,116,97,0,98,116,84,114,
105,97,110,103,108,101,73,110,102,111,77,97,112,68,97,116,97,0,98,116,
67,111,109,112,111,117,110,100,83,104,97,112,101,67,104,105,108,100,68,97,
116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,68,97,
116,97,0,98,116,67,121,108,105,110,100,101,114,83,104,97,112,101,68,97,
116,97,0,98,116,67,97,112,115,117,108,101,83,104,97,112,101,68,97,116,
97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,111,68,97,116,97,
0,98,116,71,73,109,112,97,99,116,77,101,115,104,83,104,97,112,101,68,
97,116,97,0,98,116,67,111,110,118,101,120,72,117,108,108,83,104,97,112,
101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,79,98,106,
101,99,116,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108,108,
105,115,105,111,110,79,98,106,101,99,116,70,108,111,97,116,68,97,116,97,
0,98,116,82,105,103,105,100,66,111,100,121,70,108,111,97,116,68,97,116,
97,0,98,116,82,105,103,105,100,66,111,100,121,68,111,117,98,108,101,68,
97,116,97,0,98,116,67,111,110,115,116,114,97,105,110,116,73,110,102,111,
49,0,98,116,84,121,112,101,100,67,111,110,115,116,114,97,105,110,116,68,
97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,97,116,97,0,
98,116,80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114,97,
105,110,116,70,108,111,97,116,68,97,116,97,0,98,116,80,111,105,110,116,
50,80,111,105,110,116,67,111,110,115,116,114,97,105,110,116,68,111,117,98,
108,101,68,97,116,97,0,98,116,72,105,110,103,101,67,111,110,115,116,114,
97,105,110,116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105,110,
103,101,67,111,110,115,116,114,97,105,110,116,70,108,111,97,116,68,97,116,
97,0,98,116,67,111,110,101,84,119,105,115,116,67,111,110,115,116,114,97,
105,110,116,68,97,116,97,0,98,116,71,101,110,101,114,105,99,54,68,111,
102,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,
105,100,101,114,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,0,
84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0,4,0,4,0,
8,0,0,0,16,0,48,0,16,0,16,0,32,0,48,0,96,0,64,0,
-128,0,20,0,48,0,80,0,16,0,96,0,-112,0,16,0,56,0,56,0,
20,0,72,0,4,0,4,0,8,0,48,0,32,0,80,0,72,0,80,0,
32,0,64,0,64,0,16,0,72,0,80,0,-40,1,8,1,-16,1,-88,3,
8,0,56,0,0,0,88,0,120,0,96,1,-32,0,-40,0,0,1,-48,0,
83,84,82,67,47,0,0,0,10,0,3,0,4,0,0,0,4,0,1,0,
9,0,2,0,11,0,3,0,10,0,3,0,10,0,4,0,10,0,5,0,
12,0,2,0,9,0,6,0,9,0,7,0,13,0,1,0,7,0,8,0,
14,0,1,0,8,0,8,0,15,0,1,0,13,0,9,0,16,0,1,0,
14,0,9,0,17,0,2,0,15,0,10,0,13,0,11,0,18,0,2,0,
16,0,10,0,14,0,11,0,19,0,4,0,4,0,12,0,4,0,13,0,
2,0,14,0,2,0,15,0,20,0,6,0,13,0,16,0,13,0,17,0,
4,0,18,0,4,0,19,0,4,0,20,0,0,0,21,0,21,0,6,0,
14,0,16,0,14,0,17,0,4,0,18,0,4,0,19,0,4,0,20,0,
0,0,21,0,22,0,3,0,2,0,14,0,2,0,15,0,4,0,22,0,
23,0,12,0,13,0,23,0,13,0,24,0,13,0,25,0,4,0,26,0,
4,0,27,0,4,0,28,0,4,0,29,0,20,0,30,0,22,0,31,0,
19,0,32,0,4,0,33,0,4,0,34,0,24,0,12,0,14,0,23,0,
14,0,24,0,14,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0,
4,0,29,0,21,0,30,0,22,0,31,0,4,0,33,0,4,0,34,0,
19,0,32,0,25,0,3,0,0,0,35,0,4,0,36,0,0,0,37,0,
26,0,5,0,25,0,38,0,13,0,39,0,13,0,40,0,7,0,41,0,
0,0,21,0,27,0,5,0,25,0,38,0,13,0,39,0,13,0,42,0,
7,0,43,0,4,0,44,0,28,0,2,0,13,0,45,0,7,0,46,0,
29,0,4,0,27,0,47,0,28,0,48,0,4,0,49,0,0,0,37,0,
30,0,1,0,4,0,50,0,31,0,2,0,2,0,50,0,0,0,51,0,
32,0,2,0,2,0,52,0,0,0,51,0,33,0,7,0,13,0,53,0,
14,0,54,0,30,0,55,0,32,0,56,0,31,0,57,0,4,0,58,0,
4,0,59,0,34,0,4,0,33,0,60,0,13,0,61,0,4,0,62,0,
0,0,37,0,35,0,7,0,25,0,38,0,34,0,63,0,23,0,64,0,
24,0,65,0,36,0,66,0,7,0,43,0,0,0,67,0,37,0,4,0,
17,0,68,0,25,0,69,0,4,0,70,0,7,0,71,0,38,0,4,0,
25,0,38,0,37,0,72,0,4,0,73,0,7,0,43,0,39,0,3,0,
27,0,47,0,4,0,74,0,0,0,37,0,40,0,3,0,27,0,47,0,
4,0,74,0,0,0,37,0,41,0,4,0,4,0,75,0,7,0,76,0,
7,0,77,0,7,0,78,0,36,0,14,0,4,0,79,0,4,0,80,0,
41,0,81,0,4,0,82,0,7,0,83,0,7,0,84,0,7,0,85,0,
7,0,86,0,7,0,87,0,4,0,88,0,4,0,89,0,4,0,90,0,
4,0,91,0,0,0,37,0,42,0,5,0,25,0,38,0,34,0,63,0,
13,0,39,0,7,0,43,0,4,0,92,0,43,0,5,0,27,0,47,0,
13,0,93,0,14,0,94,0,4,0,95,0,0,0,96,0,44,0,24,0,
9,0,97,0,9,0,98,0,25,0,99,0,0,0,35,0,18,0,100,0,
18,0,101,0,14,0,102,0,14,0,103,0,14,0,104,0,8,0,105,0,
8,0,106,0,8,0,107,0,8,0,108,0,8,0,109,0,8,0,110,0,
8,0,111,0,4,0,112,0,4,0,113,0,4,0,114,0,4,0,115,0,
4,0,116,0,4,0,117,0,4,0,118,0,0,0,37,0,45,0,23,0,
9,0,97,0,9,0,98,0,25,0,99,0,0,0,35,0,17,0,100,0,
17,0,101,0,13,0,102,0,13,0,103,0,13,0,104,0,7,0,105,0,
7,0,106,0,7,0,107,0,7,0,108,0,7,0,109,0,7,0,110,0,
7,0,111,0,4,0,112,0,4,0,113,0,4,0,114,0,4,0,115,0,
4,0,116,0,4,0,117,0,4,0,118,0,46,0,21,0,45,0,119,0,
15,0,120,0,13,0,121,0,13,0,122,0,13,0,123,0,13,0,124,0,
13,0,125,0,13,0,126,0,13,0,127,0,13,0,-128,0,13,0,-127,0,
7,0,-126,0,7,0,-125,0,7,0,-124,0,7,0,-123,0,7,0,-122,0,
7,0,-121,0,7,0,-120,0,7,0,-119,0,7,0,-118,0,4,0,-117,0,
47,0,22,0,44,0,119,0,16,0,120,0,14,0,121,0,14,0,122,0,
14,0,123,0,14,0,124,0,14,0,125,0,14,0,126,0,14,0,127,0,
14,0,-128,0,14,0,-127,0,8,0,-126,0,8,0,-125,0,8,0,-124,0,
8,0,-123,0,8,0,-122,0,8,0,-121,0,8,0,-120,0,8,0,-119,0,
8,0,-118,0,4,0,-117,0,0,0,37,0,48,0,2,0,4,0,-116,0,
4,0,-115,0,49,0,11,0,50,0,-114,0,50,0,-113,0,0,0,35,0,
4,0,-112,0,4,0,-111,0,4,0,-110,0,4,0,-109,0,7,0,-108,0,
7,0,-107,0,4,0,-106,0,0,0,-105,0,51,0,3,0,49,0,-104,0,
13,0,-103,0,13,0,-102,0,52,0,3,0,49,0,-104,0,14,0,-103,0,
14,0,-102,0,53,0,13,0,49,0,-104,0,18,0,-101,0,18,0,-100,0,
4,0,-99,0,4,0,-98,0,4,0,-97,0,7,0,-96,0,7,0,-95,0,
7,0,-94,0,7,0,-93,0,7,0,-92,0,7,0,-91,0,7,0,-90,0,
54,0,13,0,49,0,-104,0,17,0,-101,0,17,0,-100,0,4,0,-99,0,
4,0,-98,0,4,0,-97,0,7,0,-96,0,7,0,-95,0,7,0,-94,0,
7,0,-93,0,7,0,-92,0,7,0,-91,0,7,0,-90,0,55,0,11,0,
49,0,-104,0,17,0,-101,0,17,0,-100,0,7,0,-89,0,7,0,-88,0,
7,0,-87,0,7,0,-92,0,7,0,-91,0,7,0,-90,0,7,0,-86,0,
0,0,21,0,56,0,9,0,49,0,-104,0,17,0,-101,0,17,0,-100,0,
13,0,-85,0,13,0,-84,0,13,0,-83,0,13,0,-82,0,4,0,-81,0,
4,0,-80,0,57,0,9,0,49,0,-104,0,17,0,-101,0,17,0,-100,0,
7,0,-85,0,7,0,-84,0,7,0,-83,0,7,0,-82,0,4,0,-81,0,
4,0,-80,0,};
int sBulletDNAlen64= sizeof(sBulletDNAstr64);
unsigned char sBulletDNAstr[]= {
83,68,78,65,78,65,77,69,-79,0,0,0,109,95,115,105,122,101,0,109,
95,99,97,112,97,99,105,116,121,0,42,109,95,100,97,116,97,0,109,95,
99,111,108,108,105,115,105,111,110,83,104,97,112,101,115,0,109,95,99,111,
108,108,105,115,105,111,110,79,98,106,101,99,116,115,0,109,95,99,111,110,
115,116,114,97,105,110,116,115,0,42,102,105,114,115,116,0,42,108,97,115,
116,0,109,95,102,108,111,97,116,115,91,52,93,0,109,95,101,108,91,51,
93,0,109,95,98,97,115,105,115,0,109,95,111,114,105,103,105,110,0,109,
95,114,111,111,116,78,111,100,101,73,110,100,101,120,0,109,95,115,117,98,
116,114,101,101,83,105,122,101,0,109,95,113,117,97,110,116,105,122,101,100,
65,97,98,98,77,105,110,91,51,93,0,109,95,113,117,97,110,116,105,122,
101,100,65,97,98,98,77,97,120,91,51,93,0,109,95,97,97,98,98,77,
105,110,79,114,103,0,109,95,97,97,98,98,77,97,120,79,114,103,0,109,
95,101,115,99,97,112,101,73,110,100,101,120,0,109,95,115,117,98,80,97,
114,116,0,109,95,116,114,105,97,110,103,108,101,73,110,100,101,120,0,109,
95,112,97,100,91,52,93,0,109,95,101,115,99,97,112,101,73,110,100,101,
120,79,114,84,114,105,97,110,103,108,101,73,110,100,101,120,0,109,95,98,
118,104,65,97,98,98,77,105,110,0,109,95,98,118,104,65,97,98,98,77,
97,120,0,109,95,98,118,104,81,117,97,110,116,105,122,97,116,105,111,110,
0,109,95,99,117,114,78,111,100,101,73,110,100,101,120,0,109,95,117,115,
101,81,117,97,110,116,105,122,97,116,105,111,110,0,109,95,110,117,109,67,
111,110,116,105,103,117,111,117,115,76,101,97,102,78,111,100,101,115,0,109,
95,110,117,109,81,117,97,110,116,105,122,101,100,67,111,110,116,105,103,117,
111,117,115,78,111,100,101,115,0,42,109,95,99,111,110,116,105,103,117,111,
117,115,78,111,100,101,115,80,116,114,0,42,109,95,113,117,97,110,116,105,
122,101,100,67,111,110,116,105,103,117,111,117,115,78,111,100,101,115,80,116,
114,0,42,109,95,115,117,98,84,114,101,101,73,110,102,111,80,116,114,0,
109,95,116,114,97,118,101,114,115,97,108,77,111,100,101,0,109,95,110,117,
109,83,117,98,116,114,101,101,72,101,97,100,101,114,115,0,42,109,95,110,
97,109,101,0,109,95,115,104,97,112,101,84,121,112,101,0,109,95,112,97,
100,100,105,110,103,91,52,93,0,109,95,99,111,108,108,105,115,105,111,110,
83,104,97,112,101,68,97,116,97,0,109,95,108,111,99,97,108,83,99,97,
108,105,110,103,0,109,95,112,108,97,110,101,78,111,114,109,97,108,0,109,
95,112,108,97,110,101,67,111,110,115,116,97,110,116,0,109,95,105,109,112,
108,105,99,105,116,83,104,97,112,101,68,105,109,101,110,115,105,111,110,115,
0,109,95,99,111,108,108,105,115,105,111,110,77,97,114,103,105,110,0,109,
95,112,97,100,100,105,110,103,0,109,95,112,111,115,0,109,95,114,97,100,
105,117,115,0,109,95,99,111,110,118,101,120,73,110,116,101,114,110,97,108,
83,104,97,112,101,68,97,116,97,0,42,109,95,108,111,99,97,108,80,111,
115,105,116,105,111,110,65,114,114,97,121,80,116,114,0,109,95,108,111,99,
97,108,80,111,115,105,116,105,111,110,65,114,114,97,121,83,105,122,101,0,
109,95,118,97,108,117,101,0,109,95,112,97,100,91,50,93,0,109,95,118,
97,108,117,101,115,91,51,93,0,42,109,95,118,101,114,116,105,99,101,115,
51,102,0,42,109,95,118,101,114,116,105,99,101,115,51,100,0,42,109,95,
105,110,100,105,99,101,115,51,50,0,42,109,95,51,105,110,100,105,99,101,
115,49,54,0,42,109,95,105,110,100,105,99,101,115,49,54,0,109,95,110,
117,109,84,114,105,97,110,103,108,101,115,0,109,95,110,117,109,86,101,114,
116,105,99,101,115,0,42,109,95,109,101,115,104,80,97,114,116,115,80,116,
114,0,109,95,115,99,97,108,105,110,103,0,109,95,110,117,109,77,101,115,
104,80,97,114,116,115,0,109,95,109,101,115,104,73,110,116,101,114,102,97,
99,101,0,42,109,95,113,117,97,110,116,105,122,101,100,70,108,111,97,116,
66,118,104,0,42,109,95,113,117,97,110,116,105,122,101,100,68,111,117,98,
108,101,66,118,104,0,42,109,95,116,114,105,97,110,103,108,101,73,110,102,
111,77,97,112,0,109,95,112,97,100,51,91,52,93,0,109,95,116,114,97,
110,115,102,111,114,109,0,42,109,95,99,104,105,108,100,83,104,97,112,101,
0,109,95,99,104,105,108,100,83,104,97,112,101,84,121,112,101,0,109,95,
99,104,105,108,100,77,97,114,103,105,110,0,42,109,95,99,104,105,108,100,
83,104,97,112,101,80,116,114,0,109,95,110,117,109,67,104,105,108,100,83,
104,97,112,101,115,0,109,95,117,112,65,120,105,115,0,109,95,102,108,97,
103,115,0,109,95,101,100,103,101,86,48,86,49,65,110,103,108,101,0,109,
95,101,100,103,101,86,49,86,50,65,110,103,108,101,0,109,95,101,100,103,
101,86,50,86,48,65,110,103,108,101,0,42,109,95,104,97,115,104,84,97,
98,108,101,80,116,114,0,42,109,95,110,101,120,116,80,116,114,0,42,109,
95,118,97,108,117,101,65,114,114,97,121,80,116,114,0,42,109,95,107,101,
121,65,114,114,97,121,80,116,114,0,109,95,99,111,110,118,101,120,69,112,
115,105,108,111,110,0,109,95,112,108,97,110,97,114,69,112,115,105,108,111,
110,0,109,95,101,113,117,97,108,86,101,114,116,101,120,84,104,114,101,115,
104,111,108,100,0,109,95,101,100,103,101,68,105,115,116,97,110,99,101,84,
104,114,101,115,104,111,108,100,0,109,95,122,101,114,111,65,114,101,97,84,
104,114,101,115,104,111,108,100,0,109,95,110,101,120,116,83,105,122,101,0,
109,95,104,97,115,104,84,97,98,108,101,83,105,122,101,0,109,95,110,117,
109,86,97,108,117,101,115,0,109,95,110,117,109,75,101,121,115,0,109,95,
103,105,109,112,97,99,116,83,117,98,84,121,112,101,0,42,109,95,117,110,
115,99,97,108,101,100,80,111,105,110,116,115,70,108,111,97,116,80,116,114,
0,42,109,95,117,110,115,99,97,108,101,100,80,111,105,110,116,115,68,111,
117,98,108,101,80,116,114,0,109,95,110,117,109,85,110,115,99,97,108,101,
100,80,111,105,110,116,115,0,109,95,112,97,100,100,105,110,103,51,91,52,
93,0,42,109,95,98,114,111,97,100,112,104,97,115,101,72,97,110,100,108,
101,0,42,109,95,99,111,108,108,105,115,105,111,110,83,104,97,112,101,0,
42,109,95,114,111,111,116,67,111,108,108,105,115,105,111,110,83,104,97,112,
101,0,109,95,119,111,114,108,100,84,114,97,110,115,102,111,114,109,0,109,
95,105,110,116,101,114,112,111,108,97,116,105,111,110,87,111,114,108,100,84,
114,97,110,115,102,111,114,109,0,109,95,105,110,116,101,114,112,111,108,97,
116,105,111,110,76,105,110,101,97,114,86,101,108,111,99,105,116,121,0,109,
95,105,110,116,101,114,112,111,108,97,116,105,111,110,65,110,103,117,108,97,
114,86,101,108,111,99,105,116,121,0,109,95,97,110,105,115,111,116,114,111,
112,105,99,70,114,105,99,116,105,111,110,0,109,95,99,111,110,116,97,99,
116,80,114,111,99,101,115,115,105,110,103,84,104,114,101,115,104,111,108,100,
0,109,95,100,101,97,99,116,105,118,97,116,105,111,110,84,105,109,101,0,
109,95,102,114,105,99,116,105,111,110,0,109,95,114,101,115,116,105,116,117,
116,105,111,110,0,109,95,104,105,116,70,114,97,99,116,105,111,110,0,109,
95,99,99,100,83,119,101,112,116,83,112,104,101,114,101,82,97,100,105,117,
115,0,109,95,99,99,100,77,111,116,105,111,110,84,104,114,101,115,104,111,
108,100,0,109,95,104,97,115,65,110,105,115,111,116,114,111,112,105,99,70,
114,105,99,116,105,111,110,0,109,95,99,111,108,108,105,115,105,111,110,70,
108,97,103,115,0,109,95,105,115,108,97,110,100,84,97,103,49,0,109,95,
99,111,109,112,97,110,105,111,110,73,100,0,109,95,97,99,116,105,118,97,
116,105,111,110,83,116,97,116,101,49,0,109,95,105,110,116,101,114,110,97,
108,84,121,112,101,0,109,95,99,104,101,99,107,67,111,108,108,105,100,101,
87,105,116,104,0,109,95,99,111,108,108,105,115,105,111,110,79,98,106,101,
99,116,68,97,116,97,0,109,95,105,110,118,73,110,101,114,116,105,97,84,
101,110,115,111,114,87,111,114,108,100,0,109,95,108,105,110,101,97,114,86,
101,108,111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,86,101,108,
111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,70,97,99,116,111,
114,0,109,95,108,105,110,101,97,114,70,97,99,116,111,114,0,109,95,103,
114,97,118,105,116,121,0,109,95,103,114,97,118,105,116,121,95,97,99,99,
101,108,101,114,97,116,105,111,110,0,109,95,105,110,118,73,110,101,114,116,
105,97,76,111,99,97,108,0,109,95,116,111,116,97,108,70,111,114,99,101,
0,109,95,116,111,116,97,108,84,111,114,113,117,101,0,109,95,105,110,118,
101,114,115,101,77,97,115,115,0,109,95,108,105,110,101,97,114,68,97,109,
112,105,110,103,0,109,95,97,110,103,117,108,97,114,68,97,109,112,105,110,
103,0,109,95,97,100,100,105,116,105,111,110,97,108,68,97,109,112,105,110,
103,70,97,99,116,111,114,0,109,95,97,100,100,105,116,105,111,110,97,108,
76,105,110,101,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,
108,100,83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,
103,117,108,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,
100,83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,
117,108,97,114,68,97,109,112,105,110,103,70,97,99,116,111,114,0,109,95,
108,105,110,101,97,114,83,108,101,101,112,105,110,103,84,104,114,101,115,104,
111,108,100,0,109,95,97,110,103,117,108,97,114,83,108,101,101,112,105,110,
103,84,104,114,101,115,104,111,108,100,0,109,95,97,100,100,105,116,105,111,
110,97,108,68,97,109,112,105,110,103,0,109,95,110,117,109,67,111,110,115,
116,114,97,105,110,116,82,111,119,115,0,110,117,98,0,42,109,95,114,98,
65,0,42,109,95,114,98,66,0,109,95,111,98,106,101,99,116,84,121,112,
101,0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,84,121,
112,101,0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,73,
100,0,109,95,110,101,101,100,115,70,101,101,100,98,97,99,107,0,109,95,
97,112,112,108,105,101,100,73,109,112,117,108,115,101,0,109,95,100,98,103,
68,114,97,119,83,105,122,101,0,109,95,100,105,115,97,98,108,101,67,111,
108,108,105,115,105,111,110,115,66,101,116,119,101,101,110,76,105,110,107,101,
100,66,111,100,105,101,115,0,109,95,112,97,100,52,91,52,93,0,109,95,
116,121,112,101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,
95,112,105,118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,
0,109,95,114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,
109,101,0,109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,
109,101,65,0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,
101,110,97,98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,
95,109,111,116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,
0,109,95,109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,
95,108,111,119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,
105,109,105,116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,
0,109,95,98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,
120,97,116,105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,
83,112,97,110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,
95,116,119,105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,
0,109,95,108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,
109,95,108,105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,
95,97,110,103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,
95,97,110,103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,
95,117,115,101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,
114,97,109,101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,
67,111,110,115,116,114,97,105,110,116,70,114,97,109,101,0,84,89,80,69,
58,0,0,0,99,104,97,114,0,117,99,104,97,114,0,115,104,111,114,116,
0,117,115,104,111,114,116,0,105,110,116,0,108,111,110,103,0,117,108,111,
110,103,0,102,108,111,97,116,0,100,111,117,98,108,101,0,118,111,105,100,
0,80,111,105,110,116,101,114,65,114,114,97,121,0,98,116,80,104,121,115,
105,99,115,83,121,115,116,101,109,0,76,105,115,116,66,97,115,101,0,98,
116,86,101,99,116,111,114,51,70,108,111,97,116,68,97,116,97,0,98,116,
86,101,99,116,111,114,51,68,111,117,98,108,101,68,97,116,97,0,98,116,
77,97,116,114,105,120,51,120,51,70,108,111,97,116,68,97,116,97,0,98,
116,77,97,116,114,105,120,51,120,51,68,111,117,98,108,101,68,97,116,97,
0,98,116,84,114,97,110,115,102,111,114,109,70,108,111,97,116,68,97,116,
97,0,98,116,84,114,97,110,115,102,111,114,109,68,111,117,98,108,101,68,
97,116,97,0,98,116,66,118,104,83,117,98,116,114,101,101,73,110,102,111,
68,97,116,97,0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78,
111,100,101,70,108,111,97,116,68,97,116,97,0,98,116,79,112,116,105,109,
105,122,101,100,66,118,104,78,111,100,101,68,111,117,98,108,101,68,97,116,
97,0,98,116,81,117,97,110,116,105,122,101,100,66,118,104,78,111,100,101,
68,97,116,97,0,98,116,81,117,97,110,116,105,122,101,100,66,118,104,70,
108,111,97,116,68,97,116,97,0,98,116,81,117,97,110,116,105,122,101,100,
66,118,104,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108,108,
105,115,105,111,110,83,104,97,112,101,68,97,116,97,0,98,116,83,116,97,
116,105,99,80,108,97,110,101,83,104,97,112,101,68,97,116,97,0,98,116,
67,111,110,118,101,120,73,110,116,101,114,110,97,108,83,104,97,112,101,68,
97,116,97,0,98,116,80,111,115,105,116,105,111,110,65,110,100,82,97,100,
105,117,115,0,98,116,77,117,108,116,105,83,112,104,101,114,101,83,104,97,
112,101,68,97,116,97,0,98,116,73,110,116,73,110,100,101,120,68,97,116,
97,0,98,116,83,104,111,114,116,73,110,116,73,110,100,101,120,68,97,116,
97,0,98,116,83,104,111,114,116,73,110,116,73,110,100,101,120,84,114,105,
112,108,101,116,68,97,116,97,0,98,116,77,101,115,104,80,97,114,116,68,
97,116,97,0,98,116,83,116,114,105,100,105,110,103,77,101,115,104,73,110,
116,101,114,102,97,99,101,68,97,116,97,0,98,116,84,114,105,97,110,103,
108,101,77,101,115,104,83,104,97,112,101,68,97,116,97,0,98,116,84,114,
105,97,110,103,108,101,73,110,102,111,77,97,112,68,97,116,97,0,98,116,
67,111,109,112,111,117,110,100,83,104,97,112,101,67,104,105,108,100,68,97,
116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,68,97,
116,97,0,98,116,67,121,108,105,110,100,101,114,83,104,97,112,101,68,97,
116,97,0,98,116,67,97,112,115,117,108,101,83,104,97,112,101,68,97,116,
97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,111,68,97,116,97,
0,98,116,71,73,109,112,97,99,116,77,101,115,104,83,104,97,112,101,68,
97,116,97,0,98,116,67,111,110,118,101,120,72,117,108,108,83,104,97,112,
101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,79,98,106,
101,99,116,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108,108,
105,115,105,111,110,79,98,106,101,99,116,70,108,111,97,116,68,97,116,97,
0,98,116,82,105,103,105,100,66,111,100,121,70,108,111,97,116,68,97,116,
97,0,98,116,82,105,103,105,100,66,111,100,121,68,111,117,98,108,101,68,
97,116,97,0,98,116,67,111,110,115,116,114,97,105,110,116,73,110,102,111,
49,0,98,116,84,121,112,101,100,67,111,110,115,116,114,97,105,110,116,68,
97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,97,116,97,0,
98,116,80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114,97,
105,110,116,70,108,111,97,116,68,97,116,97,0,98,116,80,111,105,110,116,
50,80,111,105,110,116,67,111,110,115,116,114,97,105,110,116,68,111,117,98,
108,101,68,97,116,97,0,98,116,72,105,110,103,101,67,111,110,115,116,114,
97,105,110,116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105,110,
103,101,67,111,110,115,116,114,97,105,110,116,70,108,111,97,116,68,97,116,
97,0,98,116,67,111,110,101,84,119,105,115,116,67,111,110,115,116,114,97,
105,110,116,68,97,116,97,0,98,116,71,101,110,101,114,105,99,54,68,111,
102,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,
105,100,101,114,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,0,
84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0,4,0,4,0,
8,0,0,0,12,0,36,0,8,0,16,0,32,0,48,0,96,0,64,0,
-128,0,20,0,48,0,80,0,16,0,84,0,-124,0,12,0,52,0,52,0,
20,0,64,0,4,0,4,0,8,0,28,0,28,0,60,0,56,0,76,0,
24,0,60,0,60,0,16,0,64,0,68,0,-56,1,-8,0,-32,1,-104,3,
8,0,44,0,0,0,76,0,108,0,84,1,-44,0,-52,0,-12,0,-60,0,
83,84,82,67,47,0,0,0,10,0,3,0,4,0,0,0,4,0,1,0,
9,0,2,0,11,0,3,0,10,0,3,0,10,0,4,0,10,0,5,0,
12,0,2,0,9,0,6,0,9,0,7,0,13,0,1,0,7,0,8,0,
14,0,1,0,8,0,8,0,15,0,1,0,13,0,9,0,16,0,1,0,
14,0,9,0,17,0,2,0,15,0,10,0,13,0,11,0,18,0,2,0,
16,0,10,0,14,0,11,0,19,0,4,0,4,0,12,0,4,0,13,0,
2,0,14,0,2,0,15,0,20,0,6,0,13,0,16,0,13,0,17,0,
4,0,18,0,4,0,19,0,4,0,20,0,0,0,21,0,21,0,6,0,
14,0,16,0,14,0,17,0,4,0,18,0,4,0,19,0,4,0,20,0,
0,0,21,0,22,0,3,0,2,0,14,0,2,0,15,0,4,0,22,0,
23,0,12,0,13,0,23,0,13,0,24,0,13,0,25,0,4,0,26,0,
4,0,27,0,4,0,28,0,4,0,29,0,20,0,30,0,22,0,31,0,
19,0,32,0,4,0,33,0,4,0,34,0,24,0,12,0,14,0,23,0,
14,0,24,0,14,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0,
4,0,29,0,21,0,30,0,22,0,31,0,4,0,33,0,4,0,34,0,
19,0,32,0,25,0,3,0,0,0,35,0,4,0,36,0,0,0,37,0,
26,0,5,0,25,0,38,0,13,0,39,0,13,0,40,0,7,0,41,0,
0,0,21,0,27,0,5,0,25,0,38,0,13,0,39,0,13,0,42,0,
7,0,43,0,4,0,44,0,28,0,2,0,13,0,45,0,7,0,46,0,
29,0,4,0,27,0,47,0,28,0,48,0,4,0,49,0,0,0,37,0,
30,0,1,0,4,0,50,0,31,0,2,0,2,0,50,0,0,0,51,0,
32,0,2,0,2,0,52,0,0,0,51,0,33,0,7,0,13,0,53,0,
14,0,54,0,30,0,55,0,32,0,56,0,31,0,57,0,4,0,58,0,
4,0,59,0,34,0,4,0,33,0,60,0,13,0,61,0,4,0,62,0,
0,0,37,0,35,0,7,0,25,0,38,0,34,0,63,0,23,0,64,0,
24,0,65,0,36,0,66,0,7,0,43,0,0,0,67,0,37,0,4,0,
17,0,68,0,25,0,69,0,4,0,70,0,7,0,71,0,38,0,4,0,
25,0,38,0,37,0,72,0,4,0,73,0,7,0,43,0,39,0,3,0,
27,0,47,0,4,0,74,0,0,0,37,0,40,0,3,0,27,0,47,0,
4,0,74,0,0,0,37,0,41,0,4,0,4,0,75,0,7,0,76,0,
7,0,77,0,7,0,78,0,36,0,14,0,4,0,79,0,4,0,80,0,
41,0,81,0,4,0,82,0,7,0,83,0,7,0,84,0,7,0,85,0,
7,0,86,0,7,0,87,0,4,0,88,0,4,0,89,0,4,0,90,0,
4,0,91,0,0,0,37,0,42,0,5,0,25,0,38,0,34,0,63,0,
13,0,39,0,7,0,43,0,4,0,92,0,43,0,5,0,27,0,47,0,
13,0,93,0,14,0,94,0,4,0,95,0,0,0,96,0,44,0,24,0,
9,0,97,0,9,0,98,0,25,0,99,0,0,0,35,0,18,0,100,0,
18,0,101,0,14,0,102,0,14,0,103,0,14,0,104,0,8,0,105,0,
8,0,106,0,8,0,107,0,8,0,108,0,8,0,109,0,8,0,110,0,
8,0,111,0,4,0,112,0,4,0,113,0,4,0,114,0,4,0,115,0,
4,0,116,0,4,0,117,0,4,0,118,0,0,0,37,0,45,0,23,0,
9,0,97,0,9,0,98,0,25,0,99,0,0,0,35,0,17,0,100,0,
17,0,101,0,13,0,102,0,13,0,103,0,13,0,104,0,7,0,105,0,
7,0,106,0,7,0,107,0,7,0,108,0,7,0,109,0,7,0,110,0,
7,0,111,0,4,0,112,0,4,0,113,0,4,0,114,0,4,0,115,0,
4,0,116,0,4,0,117,0,4,0,118,0,46,0,21,0,45,0,119,0,
15,0,120,0,13,0,121,0,13,0,122,0,13,0,123,0,13,0,124,0,
13,0,125,0,13,0,126,0,13,0,127,0,13,0,-128,0,13,0,-127,0,
7,0,-126,0,7,0,-125,0,7,0,-124,0,7,0,-123,0,7,0,-122,0,
7,0,-121,0,7,0,-120,0,7,0,-119,0,7,0,-118,0,4,0,-117,0,
47,0,22,0,44,0,119,0,16,0,120,0,14,0,121,0,14,0,122,0,
14,0,123,0,14,0,124,0,14,0,125,0,14,0,126,0,14,0,127,0,
14,0,-128,0,14,0,-127,0,8,0,-126,0,8,0,-125,0,8,0,-124,0,
8,0,-123,0,8,0,-122,0,8,0,-121,0,8,0,-120,0,8,0,-119,0,
8,0,-118,0,4,0,-117,0,0,0,37,0,48,0,2,0,4,0,-116,0,
4,0,-115,0,49,0,11,0,50,0,-114,0,50,0,-113,0,0,0,35,0,
4,0,-112,0,4,0,-111,0,4,0,-110,0,4,0,-109,0,7,0,-108,0,
7,0,-107,0,4,0,-106,0,0,0,-105,0,51,0,3,0,49,0,-104,0,
13,0,-103,0,13,0,-102,0,52,0,3,0,49,0,-104,0,14,0,-103,0,
14,0,-102,0,53,0,13,0,49,0,-104,0,18,0,-101,0,18,0,-100,0,
4,0,-99,0,4,0,-98,0,4,0,-97,0,7,0,-96,0,7,0,-95,0,
7,0,-94,0,7,0,-93,0,7,0,-92,0,7,0,-91,0,7,0,-90,0,
54,0,13,0,49,0,-104,0,17,0,-101,0,17,0,-100,0,4,0,-99,0,
4,0,-98,0,4,0,-97,0,7,0,-96,0,7,0,-95,0,7,0,-94,0,
7,0,-93,0,7,0,-92,0,7,0,-91,0,7,0,-90,0,55,0,11,0,
49,0,-104,0,17,0,-101,0,17,0,-100,0,7,0,-89,0,7,0,-88,0,
7,0,-87,0,7,0,-92,0,7,0,-91,0,7,0,-90,0,7,0,-86,0,
0,0,21,0,56,0,9,0,49,0,-104,0,17,0,-101,0,17,0,-100,0,
13,0,-85,0,13,0,-84,0,13,0,-83,0,13,0,-82,0,4,0,-81,0,
4,0,-80,0,57,0,9,0,49,0,-104,0,17,0,-101,0,17,0,-100,0,
7,0,-85,0,7,0,-84,0,7,0,-83,0,7,0,-82,0,4,0,-81,0,
4,0,-80,0,};
int sBulletDNAlen= sizeof(sBulletDNAstr);

View File

@ -0,0 +1,606 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_SERIALIZER_H
#define BT_SERIALIZER_H
#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
#include "btStackAlloc.h"
#include "btHashMap.h"
#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
#include <memory.h>
#endif
#include <string.h>
///only the 32bit versions for now
extern unsigned char sBulletDNAstr[];
extern int sBulletDNAlen;
extern unsigned char sBulletDNAstr64[];
extern int sBulletDNAlen64;
SIMD_FORCE_INLINE int btStrLen(const char* str)
{
if (!str)
return(0);
int len = 0;
while (*str != 0)
{
str++;
len++;
}
return len;
}
class btChunk
{
public:
int m_chunkCode;
int m_length;
void *m_oldPtr;
int m_dna_nr;
int m_number;
};
enum btSerializationFlags
{
BT_SERIALIZE_NO_BVH = 1,
BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4
};
class btSerializer
{
public:
virtual ~btSerializer() {}
virtual const unsigned char* getBufferPointer() const = 0;
virtual int getCurrentBufferSize() const = 0;
virtual btChunk* allocate(size_t size, int numElements) = 0;
virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
virtual void* findPointer(void* oldPtr) = 0;
virtual void* getUniquePointer(void*oldPtr) = 0;
virtual void startSerialization() = 0;
virtual void finishSerialization() = 0;
virtual const char* findNameForPointer(const void* ptr) const = 0;
virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
virtual void serializeName(const char* ptr) = 0;
virtual int getSerializationFlags() const = 0;
virtual void setSerializationFlags(int flags) = 0;
};
#define BT_HEADER_LENGTH 12
#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
# define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
#else
# define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
#endif
#define BT_COLLISIONOBJECT_CODE MAKE_ID('C','O','B','J')
#define BT_RIGIDBODY_CODE MAKE_ID('R','B','D','Y')
#define BT_CONSTRAINT_CODE MAKE_ID('C','O','N','S')
#define BT_BOXSHAPE_CODE MAKE_ID('B','O','X','S')
#define BT_QUANTIZED_BVH_CODE MAKE_ID('Q','B','V','H')
#define BT_TRIANLGE_INFO_MAP MAKE_ID('T','M','A','P')
#define BT_SHAPE_CODE MAKE_ID('S','H','A','P')
#define BT_ARRAY_CODE MAKE_ID('A','R','A','Y')
#define BT_DNA_CODE MAKE_ID('D','N','A','1')
struct btPointerUid
{
union
{
void* m_ptr;
int m_uniqueIds[2];
};
};
class btDefaultSerializer : public btSerializer
{
btAlignedObjectArray<char*> mTypes;
btAlignedObjectArray<short*> mStructs;
btAlignedObjectArray<short> mTlens;
btHashMap<btHashInt, int> mStructReverse;
btHashMap<btHashString,int> mTypeLookup;
btHashMap<btHashPtr,void*> m_chunkP;
btHashMap<btHashPtr,const char*> m_nameMap;
btHashMap<btHashPtr,btPointerUid> m_uniquePointers;
int m_uniqueIdGenerator;
int m_totalSize;
unsigned char* m_buffer;
int m_currentSize;
void* m_dna;
int m_dnaLength;
int m_serializationFlags;
btAlignedObjectArray<btChunk*> m_chunkPtrs;
protected:
virtual void* findPointer(void* oldPtr)
{
void** ptr = m_chunkP.find(oldPtr);
if (ptr && *ptr)
return *ptr;
return 0;
}
void writeDNA()
{
btChunk* dnaChunk = allocate(m_dnaLength,1);
memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna);
}
int getReverseType(const char *type) const
{
btHashString key(type);
const int* valuePtr = mTypeLookup.find(key);
if (valuePtr)
return *valuePtr;
return -1;
}
void initDNA(const char* bdnaOrg,int dnalen)
{
///was already initialized
if (m_dna)
return;
int littleEndian= 1;
littleEndian= ((char*)&littleEndian)[0];
m_dna = btAlignedAlloc(dnalen,16);
memcpy(m_dna,bdnaOrg,dnalen);
m_dnaLength = dnalen;
int *intPtr=0;
short *shtPtr=0;
char *cp = 0;int dataLen =0;long nr=0;
intPtr = (int*)m_dna;
/*
SDNA (4 bytes) (magic number)
NAME (4 bytes)
<nr> (4 bytes) amount of names (int)
<string>
<string>
*/
if (strncmp((const char*)m_dna, "SDNA", 4)==0)
{
// skip ++ NAME
intPtr++; intPtr++;
}
// Parse names
if (!littleEndian)
*intPtr = btSwapEndian(*intPtr);
dataLen = *intPtr;
intPtr++;
cp = (char*)intPtr;
int i;
for ( i=0; i<dataLen; i++)
{
while (*cp)cp++;
cp++;
}
{
nr= (long)cp;
// long mask=3;
nr= ((nr+3)&~3)-nr;
while (nr--)
{
cp++;
}
}
/*
TYPE (4 bytes)
<nr> amount of types (int)
<string>
<string>
*/
intPtr = (int*)cp;
assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
if (!littleEndian)
*intPtr = btSwapEndian(*intPtr);
dataLen = *intPtr;
intPtr++;
cp = (char*)intPtr;
for (i=0; i<dataLen; i++)
{
mTypes.push_back(cp);
while (*cp)cp++;
cp++;
}
{
nr= (long)cp;
// long mask=3;
nr= ((nr+3)&~3)-nr;
while (nr--)
{
cp++;
}
}
/*
TLEN (4 bytes)
<len> (short) the lengths of types
<len>
*/
// Parse type lens
intPtr = (int*)cp;
assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
dataLen = (int)mTypes.size();
shtPtr = (short*)intPtr;
for (i=0; i<dataLen; i++, shtPtr++)
{
if (!littleEndian)
shtPtr[0] = btSwapEndian(shtPtr[0]);
mTlens.push_back(shtPtr[0]);
}
if (dataLen & 1) shtPtr++;
/*
STRC (4 bytes)
<nr> amount of structs (int)
<typenr>
<nr_of_elems>
<typenr>
<namenr>
<typenr>
<namenr>
*/
intPtr = (int*)shtPtr;
cp = (char*)intPtr;
assert(strncmp(cp, "STRC", 4)==0); intPtr++;
if (!littleEndian)
*intPtr = btSwapEndian(*intPtr);
dataLen = *intPtr ;
intPtr++;
shtPtr = (short*)intPtr;
for (i=0; i<dataLen; i++)
{
mStructs.push_back (shtPtr);
if (!littleEndian)
{
shtPtr[0]= btSwapEndian(shtPtr[0]);
shtPtr[1]= btSwapEndian(shtPtr[1]);
int len = shtPtr[1];
shtPtr+= 2;
for (int a=0; a<len; a++, shtPtr+=2)
{
shtPtr[0]= btSwapEndian(shtPtr[0]);
shtPtr[1]= btSwapEndian(shtPtr[1]);
}
} else
{
shtPtr+= (2*shtPtr[1])+2;
}
}
// build reverse lookups
for (i=0; i<(int)mStructs.size(); i++)
{
short *strc = mStructs.at(i);
mStructReverse.insert(strc[0], i);
mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
}
}
public:
btDefaultSerializer(int totalSize)
:m_totalSize(totalSize),
m_currentSize(0),
m_dna(0),
m_dnaLength(0),
m_serializationFlags(0)
{
m_buffer = (unsigned char*)btAlignedAlloc(totalSize, 16);
const bool VOID_IS_8 = ((sizeof(void*)==8));
#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
if (VOID_IS_8)
{
#if _WIN64
initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
#else
btAssert(0);
#endif
} else
{
#ifndef _WIN64
initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
#else
btAssert(0);
#endif
}
#else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
if (VOID_IS_8)
{
initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
} else
{
initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
}
#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
}
virtual ~btDefaultSerializer()
{
if (m_buffer)
btAlignedFree(m_buffer);
if (m_dna)
btAlignedFree(m_dna);
}
virtual void startSerialization()
{
m_uniqueIdGenerator= 1;
m_currentSize = BT_HEADER_LENGTH;
#ifdef BT_USE_DOUBLE_PRECISION
memcpy(m_buffer, "BULLETd", 7);
#else
memcpy(m_buffer, "BULLETf", 7);
#endif //BT_USE_DOUBLE_PRECISION
int littleEndian= 1;
littleEndian= ((char*)&littleEndian)[0];
if (sizeof(void*)==8)
{
m_buffer[7] = '-';
} else
{
m_buffer[7] = '_';
}
if (littleEndian)
{
m_buffer[8]='v';
} else
{
m_buffer[8]='V';
}
m_buffer[9] = '2';
m_buffer[10] = '7';
m_buffer[11] = '7';
}
virtual void finishSerialization()
{
writeDNA();
mTypes.clear();
mStructs.clear();
mTlens.clear();
mStructReverse.clear();
mTypeLookup.clear();
m_chunkP.clear();
m_nameMap.clear();
m_uniquePointers.clear();
}
virtual void* getUniquePointer(void*oldPtr)
{
if (!oldPtr)
return 0;
btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
if (uptr)
{
return uptr->m_ptr;
}
m_uniqueIdGenerator++;
btPointerUid uid;
uid.m_uniqueIds[0] = m_uniqueIdGenerator;
uid.m_uniqueIds[1] = m_uniqueIdGenerator;
m_uniquePointers.insert(oldPtr,uid);
return uid.m_ptr;
}
virtual const unsigned char* getBufferPointer() const
{
return m_buffer;
}
virtual int getCurrentBufferSize() const
{
return m_currentSize;
}
virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
{
if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
{
btAssert(!findPointer(oldPtr));
}
chunk->m_dna_nr = getReverseType(structType);
chunk->m_chunkCode = chunkCode;
void* uniquePtr = getUniquePointer(oldPtr);
m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr);
chunk->m_oldPtr = uniquePtr;//oldPtr;
}
virtual btChunk* allocate(size_t size, int numElements)
{
unsigned char* ptr = m_buffer+m_currentSize;
m_currentSize += int(size)*numElements+sizeof(btChunk);
btAssert(m_currentSize<m_totalSize);
unsigned char* data = ptr + sizeof(btChunk);
btChunk* chunk = (btChunk*)ptr;
chunk->m_chunkCode = 0;
chunk->m_oldPtr = data;
chunk->m_length = int(size)*numElements;
chunk->m_number = numElements;
m_chunkPtrs.push_back(chunk);
return chunk;
}
virtual const char* findNameForPointer(const void* ptr) const
{
const char*const * namePtr = m_nameMap.find(ptr);
if (namePtr && *namePtr)
return *namePtr;
return 0;
}
virtual void registerNameForPointer(const void* ptr, const char* name)
{
m_nameMap.insert(ptr,name);
}
virtual void serializeName(const char* name)
{
if (name)
{
//don't serialize name twice
if (findPointer((void*)name))
return;
int len = btStrLen(name);
if (len)
{
int newLen = len+1;
int padding = ((newLen+3)&~3)-newLen;
newLen += padding;
//serialize name string now
btChunk* chunk = allocate(sizeof(char),newLen);
char* destinationName = (char*)chunk->m_oldPtr;
for (int i=0;i<len;i++)
{
destinationName[i] = name[i];
}
destinationName[len] = 0;
finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name);
}
}
}
virtual int getSerializationFlags() const
{
return m_serializationFlags;
}
virtual void setSerializationFlags(int flags)
{
m_serializationFlags = flags;
}
};
#endif //BT_SERIALIZER_H

View File

@ -0,0 +1,116 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson
Nov.2006
*/
#ifndef BT_STACK_ALLOC
#define BT_STACK_ALLOC
#include "btScalar.h" //for btAssert
#include "btAlignedAllocator.h"
///The btBlock class is an internal structure for the btStackAlloc memory allocator.
struct btBlock
{
btBlock* previous;
unsigned char* address;
};
///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
class btStackAlloc
{
public:
btStackAlloc(unsigned int size) { ctor();create(size); }
~btStackAlloc() { destroy(); }
inline void create(unsigned int size)
{
destroy();
data = (unsigned char*) btAlignedAlloc(size,16);
totalsize = size;
}
inline void destroy()
{
btAssert(usedsize==0);
//Raise(L"StackAlloc is still in use");
if(usedsize==0)
{
if(!ischild && data)
btAlignedFree(data);
data = 0;
usedsize = 0;
}
}
int getAvailableMemory() const
{
return static_cast<int>(totalsize - usedsize);
}
unsigned char* allocate(unsigned int size)
{
const unsigned int nus(usedsize+size);
if(nus<totalsize)
{
usedsize=nus;
return(data+(usedsize-size));
}
btAssert(0);
//&& (L"Not enough memory"));
return(0);
}
SIMD_FORCE_INLINE btBlock* beginBlock()
{
btBlock* pb = (btBlock*)allocate(sizeof(btBlock));
pb->previous = current;
pb->address = data+usedsize;
current = pb;
return(pb);
}
SIMD_FORCE_INLINE void endBlock(btBlock* block)
{
btAssert(block==current);
//Raise(L"Unmatched blocks");
if(block==current)
{
current = block->previous;
usedsize = (unsigned int)((block->address-data)-sizeof(btBlock));
}
}
private:
void ctor()
{
data = 0;
totalsize = 0;
usedsize = 0;
current = 0;
ischild = false;
}
unsigned char* data;
unsigned int totalsize;
unsigned int usedsize;
btBlock* current;
bool ischild;
};
#endif //BT_STACK_ALLOC

View File

@ -0,0 +1,307 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef btTransform_H
#define btTransform_H
#include "btMatrix3x3.h"
#ifdef BT_USE_DOUBLE_PRECISION
#define btTransformData btTransformDoubleData
#else
#define btTransformData btTransformFloatData
#endif
/**@brief The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear.
*It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. */
class btTransform {
///Storage for the rotation
btMatrix3x3 m_basis;
///Storage for the translation
btVector3 m_origin;
public:
/**@brief No initialization constructor */
btTransform() {}
/**@brief Constructor from btQuaternion (optional btVector3 )
* @param q Rotation from quaternion
* @param c Translation from Vector (default 0,0,0) */
explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q,
const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
: m_basis(q),
m_origin(c)
{}
/**@brief Constructor from btMatrix3x3 (optional btVector3)
* @param b Rotation from Matrix
* @param c Translation from Vector default (0,0,0)*/
explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b,
const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
: m_basis(b),
m_origin(c)
{}
/**@brief Copy constructor */
SIMD_FORCE_INLINE btTransform (const btTransform& other)
: m_basis(other.m_basis),
m_origin(other.m_origin)
{
}
/**@brief Assignment Operator */
SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other)
{
m_basis = other.m_basis;
m_origin = other.m_origin;
return *this;
}
/**@brief Set the current transform as the value of the product of two transforms
* @param t1 Transform 1
* @param t2 Transform 2
* This = Transform1 * Transform2 */
SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2) {
m_basis = t1.m_basis * t2.m_basis;
m_origin = t1(t2.m_origin);
}
/* void multInverseLeft(const btTransform& t1, const btTransform& t2) {
btVector3 v = t2.m_origin - t1.m_origin;
m_basis = btMultTransposeLeft(t1.m_basis, t2.m_basis);
m_origin = v * t1.m_basis;
}
*/
/**@brief Return the transform of the vector */
SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const
{
return btVector3(m_basis[0].dot(x) + m_origin.x(),
m_basis[1].dot(x) + m_origin.y(),
m_basis[2].dot(x) + m_origin.z());
}
/**@brief Return the transform of the vector */
SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const
{
return (*this)(x);
}
/**@brief Return the transform of the btQuaternion */
SIMD_FORCE_INLINE btQuaternion operator*(const btQuaternion& q) const
{
return getRotation() * q;
}
/**@brief Return the basis matrix for the rotation */
SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; }
/**@brief Return the basis matrix for the rotation */
SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; }
/**@brief Return the origin vector translation */
SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; }
/**@brief Return the origin vector translation */
SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; }
/**@brief Return a quaternion representing the rotation */
btQuaternion getRotation() const {
btQuaternion q;
m_basis.getRotation(q);
return q;
}
/**@brief Set from an array
* @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
void setFromOpenGLMatrix(const btScalar *m)
{
m_basis.setFromOpenGLSubMatrix(m);
m_origin.setValue(m[12],m[13],m[14]);
}
/**@brief Fill an array representation
* @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
void getOpenGLMatrix(btScalar *m) const
{
m_basis.getOpenGLSubMatrix(m);
m[12] = m_origin.x();
m[13] = m_origin.y();
m[14] = m_origin.z();
m[15] = btScalar(1.0);
}
/**@brief Set the translational element
* @param origin The vector to set the translation to */
SIMD_FORCE_INLINE void setOrigin(const btVector3& origin)
{
m_origin = origin;
}
SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const;
/**@brief Set the rotational element by btMatrix3x3 */
SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis)
{
m_basis = basis;
}
/**@brief Set the rotational element by btQuaternion */
SIMD_FORCE_INLINE void setRotation(const btQuaternion& q)
{
m_basis.setRotation(q);
}
/**@brief Set this transformation to the identity */
void setIdentity()
{
m_basis.setIdentity();
m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
}
/**@brief Multiply this Transform by another(this = this * another)
* @param t The other transform */
btTransform& operator*=(const btTransform& t)
{
m_origin += m_basis * t.m_origin;
m_basis *= t.m_basis;
return *this;
}
/**@brief Return the inverse of this transform */
btTransform inverse() const
{
btMatrix3x3 inv = m_basis.transpose();
return btTransform(inv, inv * -m_origin);
}
/**@brief Return the inverse of this transform times the other transform
* @param t The other transform
* return this.inverse() * the other */
btTransform inverseTimes(const btTransform& t) const;
/**@brief Return the product of this transform and the other */
btTransform operator*(const btTransform& t) const;
/**@brief Return an identity transform */
static const btTransform& getIdentity()
{
static const btTransform identityTransform(btMatrix3x3::getIdentity());
return identityTransform;
}
void serialize(struct btTransformData& dataOut) const;
void serializeFloat(struct btTransformFloatData& dataOut) const;
void deSerialize(const struct btTransformData& dataIn);
void deSerializeDouble(const struct btTransformDoubleData& dataIn);
void deSerializeFloat(const struct btTransformFloatData& dataIn);
};
SIMD_FORCE_INLINE btVector3
btTransform::invXform(const btVector3& inVec) const
{
btVector3 v = inVec - m_origin;
return (m_basis.transpose() * v);
}
SIMD_FORCE_INLINE btTransform
btTransform::inverseTimes(const btTransform& t) const
{
btVector3 v = t.getOrigin() - m_origin;
return btTransform(m_basis.transposeTimes(t.m_basis),
v * m_basis);
}
SIMD_FORCE_INLINE btTransform
btTransform::operator*(const btTransform& t) const
{
return btTransform(m_basis * t.m_basis,
(*this)(t.m_origin));
}
/**@brief Test if two transforms have all elements equal */
SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2)
{
return ( t1.getBasis() == t2.getBasis() &&
t1.getOrigin() == t2.getOrigin() );
}
///for serialization
struct btTransformFloatData
{
btMatrix3x3FloatData m_basis;
btVector3FloatData m_origin;
};
struct btTransformDoubleData
{
btMatrix3x3DoubleData m_basis;
btVector3DoubleData m_origin;
};
SIMD_FORCE_INLINE void btTransform::serialize(btTransformData& dataOut) const
{
m_basis.serialize(dataOut.m_basis);
m_origin.serialize(dataOut.m_origin);
}
SIMD_FORCE_INLINE void btTransform::serializeFloat(btTransformFloatData& dataOut) const
{
m_basis.serializeFloat(dataOut.m_basis);
m_origin.serializeFloat(dataOut.m_origin);
}
SIMD_FORCE_INLINE void btTransform::deSerialize(const btTransformData& dataIn)
{
m_basis.deSerialize(dataIn.m_basis);
m_origin.deSerialize(dataIn.m_origin);
}
SIMD_FORCE_INLINE void btTransform::deSerializeFloat(const btTransformFloatData& dataIn)
{
m_basis.deSerializeFloat(dataIn.m_basis);
m_origin.deSerializeFloat(dataIn.m_origin);
}
SIMD_FORCE_INLINE void btTransform::deSerializeDouble(const btTransformDoubleData& dataIn)
{
m_basis.deSerializeDouble(dataIn.m_basis);
m_origin.deSerializeDouble(dataIn.m_origin);
}
#endif

View File

@ -0,0 +1,228 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SIMD_TRANSFORM_UTIL_H
#define SIMD_TRANSFORM_UTIL_H
#include "btTransform.h"
#define ANGULAR_MOTION_THRESHOLD btScalar(0.5)*SIMD_HALF_PI
SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir)
{
return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
}
/// Utils related to temporal transforms
class btTransformUtil
{
public:
static void integrateTransform(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep,btTransform& predictedTransform)
{
predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
// #define QUATERNION_DERIVATIVE
#ifdef QUATERNION_DERIVATIVE
btQuaternion predictedOrn = curTrans.getRotation();
predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5));
predictedOrn.normalize();
#else
//Exponential map
//google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
btVector3 axis;
btScalar fAngle = angvel.length();
//limit the angular motion
if (fAngle*timeStep > ANGULAR_MOTION_THRESHOLD)
{
fAngle = ANGULAR_MOTION_THRESHOLD / timeStep;
}
if ( fAngle < btScalar(0.001) )
{
// use Taylor's expansions of sync function
axis = angvel*( btScalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(btScalar(0.020833333333))*fAngle*fAngle );
}
else
{
// sync(fAngle) = sin(c*fAngle)/t
axis = angvel*( btSin(btScalar(0.5)*fAngle*timeStep)/fAngle );
}
btQuaternion dorn (axis.x(),axis.y(),axis.z(),btCos( fAngle*timeStep*btScalar(0.5) ));
btQuaternion orn0 = curTrans.getRotation();
btQuaternion predictedOrn = dorn * orn0;
predictedOrn.normalize();
#endif
predictedTransform.setRotation(predictedOrn);
}
static void calculateVelocityQuaternion(const btVector3& pos0,const btVector3& pos1,const btQuaternion& orn0,const btQuaternion& orn1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
{
linVel = (pos1 - pos0) / timeStep;
btVector3 axis;
btScalar angle;
if (orn0 != orn1)
{
calculateDiffAxisAngleQuaternion(orn0,orn1,axis,angle);
angVel = axis * angle / timeStep;
} else
{
angVel.setValue(0,0,0);
}
}
static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0,const btQuaternion& orn1a,btVector3& axis,btScalar& angle)
{
btQuaternion orn1 = orn0.nearest(orn1a);
btQuaternion dorn = orn1 * orn0.inverse();
angle = dorn.getAngle();
axis = btVector3(dorn.x(),dorn.y(),dorn.z());
axis[3] = btScalar(0.);
//check for axis length
btScalar len = axis.length2();
if (len < SIMD_EPSILON*SIMD_EPSILON)
axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
else
axis /= btSqrt(len);
}
static void calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
{
linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
btVector3 axis;
btScalar angle;
calculateDiffAxisAngle(transform0,transform1,axis,angle);
angVel = axis * angle / timeStep;
}
static void calculateDiffAxisAngle(const btTransform& transform0,const btTransform& transform1,btVector3& axis,btScalar& angle)
{
btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
btQuaternion dorn;
dmat.getRotation(dorn);
///floating point inaccuracy can lead to w component > 1..., which breaks
dorn.normalize();
angle = dorn.getAngle();
axis = btVector3(dorn.x(),dorn.y(),dorn.z());
axis[3] = btScalar(0.);
//check for axis length
btScalar len = axis.length2();
if (len < SIMD_EPSILON*SIMD_EPSILON)
axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
else
axis /= btSqrt(len);
}
};
///The btConvexSeparatingDistanceUtil can help speed up convex collision detection
///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance
class btConvexSeparatingDistanceUtil
{
btQuaternion m_ornA;
btQuaternion m_ornB;
btVector3 m_posA;
btVector3 m_posB;
btVector3 m_separatingNormal;
btScalar m_boundingRadiusA;
btScalar m_boundingRadiusB;
btScalar m_separatingDistance;
public:
btConvexSeparatingDistanceUtil(btScalar boundingRadiusA,btScalar boundingRadiusB)
:m_boundingRadiusA(boundingRadiusA),
m_boundingRadiusB(boundingRadiusB),
m_separatingDistance(0.f)
{
}
btScalar getConservativeSeparatingDistance()
{
return m_separatingDistance;
}
void updateSeparatingDistance(const btTransform& transA,const btTransform& transB)
{
const btVector3& toPosA = transA.getOrigin();
const btVector3& toPosB = transB.getOrigin();
btQuaternion toOrnA = transA.getRotation();
btQuaternion toOrnB = transB.getRotation();
if (m_separatingDistance>0.f)
{
btVector3 linVelA,angVelA,linVelB,angVelB;
btTransformUtil::calculateVelocityQuaternion(m_posA,toPosA,m_ornA,toOrnA,btScalar(1.),linVelA,angVelA);
btTransformUtil::calculateVelocityQuaternion(m_posB,toPosB,m_ornB,toOrnB,btScalar(1.),linVelB,angVelB);
btScalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
btVector3 relLinVel = (linVelB-linVelA);
btScalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
if (relLinVelocLength<0.f)
{
relLinVelocLength = 0.f;
}
btScalar projectedMotion = maxAngularProjectedVelocity +relLinVelocLength;
m_separatingDistance -= projectedMotion;
}
m_posA = toPosA;
m_posB = toPosB;
m_ornA = toOrnA;
m_ornB = toOrnB;
}
void initSeparatingDistance(const btVector3& separatingVector,btScalar separatingDistance,const btTransform& transA,const btTransform& transB)
{
m_separatingDistance = separatingDistance;
if (m_separatingDistance>0.f)
{
m_separatingNormal = separatingVector;
const btVector3& toPosA = transA.getOrigin();
const btVector3& toPosB = transB.getOrigin();
btQuaternion toOrnA = transA.getRotation();
btQuaternion toOrnB = transB.getRotation();
m_posA = toPosA;
m_posB = toPosB;
m_ornA = toOrnA;
m_ornB = toOrnB;
}
}
};
#endif //SIMD_TRANSFORM_UTIL_H

View File

@ -0,0 +1,766 @@
/*
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SIMD__VECTOR3_H
#define SIMD__VECTOR3_H
#include "btScalar.h"
#include "btMinMax.h"
#ifdef BT_USE_DOUBLE_PRECISION
#define btVector3Data btVector3DoubleData
#define btVector3DataName "btVector3DoubleData"
#else
#define btVector3Data btVector3FloatData
#define btVector3DataName "btVector3FloatData"
#endif //BT_USE_DOUBLE_PRECISION
/**@brief btVector3 can be used to represent 3D points and vectors.
* It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
* Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
*/
ATTRIBUTE_ALIGNED16(class) btVector3
{
public:
#if defined (__SPU__) && defined (__CELLOS_LV2__)
btScalar m_floats[4];
public:
SIMD_FORCE_INLINE const vec_float4& get128() const
{
return *((const vec_float4*)&m_floats[0]);
}
public:
#else //__CELLOS_LV2__ __SPU__
#ifdef BT_USE_SSE // _WIN32
union {
__m128 mVec128;
btScalar m_floats[4];
};
SIMD_FORCE_INLINE __m128 get128() const
{
return mVec128;
}
SIMD_FORCE_INLINE void set128(__m128 v128)
{
mVec128 = v128;
}
#else
btScalar m_floats[4];
#endif
#endif //__CELLOS_LV2__ __SPU__
public:
/**@brief No initialization constructor */
SIMD_FORCE_INLINE btVector3() {}
/**@brief Constructor from scalars
* @param x X value
* @param y Y value
* @param z Z value
*/
SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z)
{
m_floats[0] = x;
m_floats[1] = y;
m_floats[2] = z;
m_floats[3] = btScalar(0.);
}
/**@brief Add a vector to this one
* @param The vector to add to this one */
SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v)
{
m_floats[0] += v.m_floats[0]; m_floats[1] += v.m_floats[1];m_floats[2] += v.m_floats[2];
return *this;
}
/**@brief Subtract a vector from this one
* @param The vector to subtract */
SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v)
{
m_floats[0] -= v.m_floats[0]; m_floats[1] -= v.m_floats[1];m_floats[2] -= v.m_floats[2];
return *this;
}
/**@brief Scale the vector
* @param s Scale factor */
SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s)
{
m_floats[0] *= s; m_floats[1] *= s;m_floats[2] *= s;
return *this;
}
/**@brief Inversely scale the vector
* @param s Scale factor to divide by */
SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s)
{
btFullAssert(s != btScalar(0.0));
return *this *= btScalar(1.0) / s;
}
/**@brief Return the dot product
* @param v The other vector in the dot product */
SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const
{
return m_floats[0] * v.m_floats[0] + m_floats[1] * v.m_floats[1] +m_floats[2] * v.m_floats[2];
}
/**@brief Return the length of the vector squared */
SIMD_FORCE_INLINE btScalar length2() const
{
return dot(*this);
}
/**@brief Return the length of the vector */
SIMD_FORCE_INLINE btScalar length() const
{
return btSqrt(length2());
}
/**@brief Return the distance squared between the ends of this and another vector
* This is symantically treating the vector like a point */
SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const;
/**@brief Return the distance between the ends of this and another vector
* This is symantically treating the vector like a point */
SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const;
SIMD_FORCE_INLINE btVector3& safeNormalize()
{
btVector3 absVec = this->absolute();
int maxIndex = absVec.maxAxis();
if (absVec[maxIndex]>0)
{
*this /= absVec[maxIndex];
return *this /= length();
}
setValue(1,0,0);
return *this;
}
/**@brief Normalize this vector
* x^2 + y^2 + z^2 = 1 */
SIMD_FORCE_INLINE btVector3& normalize()
{
return *this /= length();
}
/**@brief Return a normalized version of this vector */
SIMD_FORCE_INLINE btVector3 normalized() const;
/**@brief Return a rotated version of this vector
* @param wAxis The axis to rotate about
* @param angle The angle to rotate by */
SIMD_FORCE_INLINE btVector3 rotate( const btVector3& wAxis, const btScalar angle ) const;
/**@brief Return the angle between this and another vector
* @param v The other vector */
SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const
{
btScalar s = btSqrt(length2() * v.length2());
btFullAssert(s != btScalar(0.0));
return btAcos(dot(v) / s);
}
/**@brief Return a vector will the absolute values of each element */
SIMD_FORCE_INLINE btVector3 absolute() const
{
return btVector3(
btFabs(m_floats[0]),
btFabs(m_floats[1]),
btFabs(m_floats[2]));
}
/**@brief Return the cross product between this and another vector
* @param v The other vector */
SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const
{
return btVector3(
m_floats[1] * v.m_floats[2] -m_floats[2] * v.m_floats[1],
m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2],
m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]);
}
SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const
{
return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
}
/**@brief Return the axis with the smallest value
* Note return values are 0,1,2 for x, y, or z */
SIMD_FORCE_INLINE int minAxis() const
{
return m_floats[0] < m_floats[1] ? (m_floats[0] <m_floats[2] ? 0 : 2) : (m_floats[1] <m_floats[2] ? 1 : 2);
}
/**@brief Return the axis with the largest value
* Note return values are 0,1,2 for x, y, or z */
SIMD_FORCE_INLINE int maxAxis() const
{
return m_floats[0] < m_floats[1] ? (m_floats[1] <m_floats[2] ? 2 : 1) : (m_floats[0] <m_floats[2] ? 2 : 0);
}
SIMD_FORCE_INLINE int furthestAxis() const
{
return absolute().minAxis();
}
SIMD_FORCE_INLINE int closestAxis() const
{
return absolute().maxAxis();
}
SIMD_FORCE_INLINE void setInterpolate3(const btVector3& v0, const btVector3& v1, btScalar rt)
{
btScalar s = btScalar(1.0) - rt;
m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0];
m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1];
m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2];
//don't do the unused w component
// m_co[3] = s * v0[3] + rt * v1[3];
}
/**@brief Return the linear interpolation between this and another vector
* @param v The other vector
* @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const
{
return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
m_floats[2] + (v.m_floats[2] -m_floats[2]) * t);
}
/**@brief Elementwise multiply this vector by the other
* @param v The other vector */
SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v)
{
m_floats[0] *= v.m_floats[0]; m_floats[1] *= v.m_floats[1];m_floats[2] *= v.m_floats[2];
return *this;
}
/**@brief Return the x value */
SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
/**@brief Return the y value */
SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
/**@brief Return the z value */
SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
/**@brief Set the x value */
SIMD_FORCE_INLINE void setX(btScalar x) { m_floats[0] = x;};
/**@brief Set the y value */
SIMD_FORCE_INLINE void setY(btScalar y) { m_floats[1] = y;};
/**@brief Set the z value */
SIMD_FORCE_INLINE void setZ(btScalar z) {m_floats[2] = z;};
/**@brief Set the w value */
SIMD_FORCE_INLINE void setW(btScalar w) { m_floats[3] = w;};
/**@brief Return the x value */
SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
/**@brief Return the y value */
SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
/**@brief Return the z value */
SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
/**@brief Return the w value */
SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
//SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
//SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; }
SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; }
SIMD_FORCE_INLINE bool operator==(const btVector3& other) const
{
return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0]));
}
SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const
{
return !(*this == other);
}
/**@brief Set each element to the max of the current values and the values of another btVector3
* @param other The other btVector3 to compare with
*/
SIMD_FORCE_INLINE void setMax(const btVector3& other)
{
btSetMax(m_floats[0], other.m_floats[0]);
btSetMax(m_floats[1], other.m_floats[1]);
btSetMax(m_floats[2], other.m_floats[2]);
btSetMax(m_floats[3], other.w());
}
/**@brief Set each element to the min of the current values and the values of another btVector3
* @param other The other btVector3 to compare with
*/
SIMD_FORCE_INLINE void setMin(const btVector3& other)
{
btSetMin(m_floats[0], other.m_floats[0]);
btSetMin(m_floats[1], other.m_floats[1]);
btSetMin(m_floats[2], other.m_floats[2]);
btSetMin(m_floats[3], other.w());
}
SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z)
{
m_floats[0]=x;
m_floats[1]=y;
m_floats[2]=z;
m_floats[3] = btScalar(0.);
}
void getSkewSymmetricMatrix(btVector3* v0,btVector3* v1,btVector3* v2) const
{
v0->setValue(0. ,-z() ,y());
v1->setValue(z() ,0. ,-x());
v2->setValue(-y() ,x() ,0.);
}
void setZero()
{
setValue(btScalar(0.),btScalar(0.),btScalar(0.));
}
SIMD_FORCE_INLINE bool isZero() const
{
return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0);
}
SIMD_FORCE_INLINE bool fuzzyZero() const
{
return length2() < SIMD_EPSILON;
}
SIMD_FORCE_INLINE void serialize(struct btVector3Data& dataOut) const;
SIMD_FORCE_INLINE void deSerialize(const struct btVector3Data& dataIn);
SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData& dataOut) const;
SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn);
SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData& dataOut) const;
SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn);
};
/**@brief Return the sum of two vectors (Point symantics)*/
SIMD_FORCE_INLINE btVector3
operator+(const btVector3& v1, const btVector3& v2)
{
return btVector3(v1.m_floats[0] + v2.m_floats[0], v1.m_floats[1] + v2.m_floats[1], v1.m_floats[2] + v2.m_floats[2]);
}
/**@brief Return the elementwise product of two vectors */
SIMD_FORCE_INLINE btVector3
operator*(const btVector3& v1, const btVector3& v2)
{
return btVector3(v1.m_floats[0] * v2.m_floats[0], v1.m_floats[1] * v2.m_floats[1], v1.m_floats[2] * v2.m_floats[2]);
}
/**@brief Return the difference between two vectors */
SIMD_FORCE_INLINE btVector3
operator-(const btVector3& v1, const btVector3& v2)
{
return btVector3(v1.m_floats[0] - v2.m_floats[0], v1.m_floats[1] - v2.m_floats[1], v1.m_floats[2] - v2.m_floats[2]);
}
/**@brief Return the negative of the vector */
SIMD_FORCE_INLINE btVector3
operator-(const btVector3& v)
{
return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
}
/**@brief Return the vector scaled by s */
SIMD_FORCE_INLINE btVector3
operator*(const btVector3& v, const btScalar& s)
{
return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s);
}
/**@brief Return the vector scaled by s */
SIMD_FORCE_INLINE btVector3
operator*(const btScalar& s, const btVector3& v)
{
return v * s;
}
/**@brief Return the vector inversely scaled by s */
SIMD_FORCE_INLINE btVector3
operator/(const btVector3& v, const btScalar& s)
{
btFullAssert(s != btScalar(0.0));
return v * (btScalar(1.0) / s);
}
/**@brief Return the vector inversely scaled by s */
SIMD_FORCE_INLINE btVector3
operator/(const btVector3& v1, const btVector3& v2)
{
return btVector3(v1.m_floats[0] / v2.m_floats[0],v1.m_floats[1] / v2.m_floats[1],v1.m_floats[2] / v2.m_floats[2]);
}
/**@brief Return the dot product between two vectors */
SIMD_FORCE_INLINE btScalar
btDot(const btVector3& v1, const btVector3& v2)
{
return v1.dot(v2);
}
/**@brief Return the distance squared between two vectors */
SIMD_FORCE_INLINE btScalar
btDistance2(const btVector3& v1, const btVector3& v2)
{
return v1.distance2(v2);
}
/**@brief Return the distance between two vectors */
SIMD_FORCE_INLINE btScalar
btDistance(const btVector3& v1, const btVector3& v2)
{
return v1.distance(v2);
}
/**@brief Return the angle between two vectors */
SIMD_FORCE_INLINE btScalar
btAngle(const btVector3& v1, const btVector3& v2)
{
return v1.angle(v2);
}
/**@brief Return the cross product of two vectors */
SIMD_FORCE_INLINE btVector3
btCross(const btVector3& v1, const btVector3& v2)
{
return v1.cross(v2);
}
SIMD_FORCE_INLINE btScalar
btTriple(const btVector3& v1, const btVector3& v2, const btVector3& v3)
{
return v1.triple(v2, v3);
}
/**@brief Return the linear interpolation between two vectors
* @param v1 One vector
* @param v2 The other vector
* @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */
SIMD_FORCE_INLINE btVector3
lerp(const btVector3& v1, const btVector3& v2, const btScalar& t)
{
return v1.lerp(v2, t);
}
SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const
{
return (v - *this).length2();
}
SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const
{
return (v - *this).length();
}
SIMD_FORCE_INLINE btVector3 btVector3::normalized() const
{
return *this / length();
}
SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar angle ) const
{
// wAxis must be a unit lenght vector
btVector3 o = wAxis * wAxis.dot( *this );
btVector3 x = *this - o;
btVector3 y;
y = wAxis.cross( *this );
return ( o + x * btCos( angle ) + y * btSin( angle ) );
}
class btVector4 : public btVector3
{
public:
SIMD_FORCE_INLINE btVector4() {}
SIMD_FORCE_INLINE btVector4(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
: btVector3(x,y,z)
{
m_floats[3] = w;
}
SIMD_FORCE_INLINE btVector4 absolute4() const
{
return btVector4(
btFabs(m_floats[0]),
btFabs(m_floats[1]),
btFabs(m_floats[2]),
btFabs(m_floats[3]));
}
btScalar getW() const { return m_floats[3];}
SIMD_FORCE_INLINE int maxAxis4() const
{
int maxIndex = -1;
btScalar maxVal = btScalar(-BT_LARGE_FLOAT);
if (m_floats[0] > maxVal)
{
maxIndex = 0;
maxVal = m_floats[0];
}
if (m_floats[1] > maxVal)
{
maxIndex = 1;
maxVal = m_floats[1];
}
if (m_floats[2] > maxVal)
{
maxIndex = 2;
maxVal =m_floats[2];
}
if (m_floats[3] > maxVal)
{
maxIndex = 3;
maxVal = m_floats[3];
}
return maxIndex;
}
SIMD_FORCE_INLINE int minAxis4() const
{
int minIndex = -1;
btScalar minVal = btScalar(BT_LARGE_FLOAT);
if (m_floats[0] < minVal)
{
minIndex = 0;
minVal = m_floats[0];
}
if (m_floats[1] < minVal)
{
minIndex = 1;
minVal = m_floats[1];
}
if (m_floats[2] < minVal)
{
minIndex = 2;
minVal =m_floats[2];
}
if (m_floats[3] < minVal)
{
minIndex = 3;
minVal = m_floats[3];
}
return minIndex;
}
SIMD_FORCE_INLINE int closestAxis4() const
{
return absolute4().maxAxis4();
}
/**@brief Set x,y,z and zero w
* @param x Value of x
* @param y Value of y
* @param z Value of z
*/
/* void getValue(btScalar *m) const
{
m[0] = m_floats[0];
m[1] = m_floats[1];
m[2] =m_floats[2];
}
*/
/**@brief Set the values
* @param x Value of x
* @param y Value of y
* @param z Value of z
* @param w Value of w
*/
SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
{
m_floats[0]=x;
m_floats[1]=y;
m_floats[2]=z;
m_floats[3]=w;
}
};
///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal)
{
#ifdef BT_USE_DOUBLE_PRECISION
unsigned char* dest = (unsigned char*) &destVal;
unsigned char* src = (unsigned char*) &sourceVal;
dest[0] = src[7];
dest[1] = src[6];
dest[2] = src[5];
dest[3] = src[4];
dest[4] = src[3];
dest[5] = src[2];
dest[6] = src[1];
dest[7] = src[0];
#else
unsigned char* dest = (unsigned char*) &destVal;
unsigned char* src = (unsigned char*) &sourceVal;
dest[0] = src[3];
dest[1] = src[2];
dest[2] = src[1];
dest[3] = src[0];
#endif //BT_USE_DOUBLE_PRECISION
}
///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec)
{
for (int i=0;i<4;i++)
{
btSwapScalarEndian(sourceVec[i],destVec[i]);
}
}
///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector)
{
btVector3 swappedVec;
for (int i=0;i<4;i++)
{
btSwapScalarEndian(vector[i],swappedVec[i]);
}
vector = swappedVec;
}
template <class T>
SIMD_FORCE_INLINE void btPlaneSpace1 (const T& n, T& p, T& q)
{
if (btFabs(n[2]) > SIMDSQRT12) {
// choose p in y-z plane
btScalar a = n[1]*n[1] + n[2]*n[2];
btScalar k = btRecipSqrt (a);
p[0] = 0;
p[1] = -n[2]*k;
p[2] = n[1]*k;
// set q = n x p
q[0] = a*k;
q[1] = -n[0]*p[2];
q[2] = n[0]*p[1];
}
else {
// choose p in x-y plane
btScalar a = n[0]*n[0] + n[1]*n[1];
btScalar k = btRecipSqrt (a);
p[0] = -n[1]*k;
p[1] = n[0]*k;
p[2] = 0;
// set q = n x p
q[0] = -n[2]*p[1];
q[1] = n[2]*p[0];
q[2] = a*k;
}
}
struct btVector3FloatData
{
float m_floats[4];
};
struct btVector3DoubleData
{
double m_floats[4];
};
SIMD_FORCE_INLINE void btVector3::serializeFloat(struct btVector3FloatData& dataOut) const
{
///could also do a memcpy, check if it is worth it
for (int i=0;i<4;i++)
dataOut.m_floats[i] = float(m_floats[i]);
}
SIMD_FORCE_INLINE void btVector3::deSerializeFloat(const struct btVector3FloatData& dataIn)
{
for (int i=0;i<4;i++)
m_floats[i] = btScalar(dataIn.m_floats[i]);
}
SIMD_FORCE_INLINE void btVector3::serializeDouble(struct btVector3DoubleData& dataOut) const
{
///could also do a memcpy, check if it is worth it
for (int i=0;i<4;i++)
dataOut.m_floats[i] = double(m_floats[i]);
}
SIMD_FORCE_INLINE void btVector3::deSerializeDouble(const struct btVector3DoubleData& dataIn)
{
for (int i=0;i<4;i++)
m_floats[i] = btScalar(dataIn.m_floats[i]);
}
SIMD_FORCE_INLINE void btVector3::serialize(struct btVector3Data& dataOut) const
{
///could also do a memcpy, check if it is worth it
for (int i=0;i<4;i++)
dataOut.m_floats[i] = m_floats[i];
}
SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3Data& dataIn)
{
for (int i=0;i<4;i++)
m_floats[i] = dataIn.m_floats[i];
}
#endif //SIMD__VECTOR3_H