Bullet 2.85 update

This commit is contained in:
rextimmy 2016-12-28 18:32:21 +10:00
parent 38bf2b8175
commit 540c9b72c0
391 changed files with 32183 additions and 58559 deletions

View file

@ -11,6 +11,7 @@ SET(LinearMath_SRCS
btPolarDecomposition.cpp
btQuickprof.cpp
btSerializer.cpp
btThreads.cpp
btVector3.cpp
)
@ -38,6 +39,7 @@ SET(LinearMath_HDRS
btScalar.h
btSerializer.h
btStackAlloc.h
btThreads.h
btTransform.h
btTransformUtil.h
btVector3.h
@ -54,7 +56,7 @@ IF (INSTALL_LIBS)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS LinearMath DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS LinearMath
INSTALL(TARGETS LinearMath
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})

View file

@ -105,30 +105,94 @@ void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc)
}
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
static int allocations_id[10241024];
static int allocations_bytes[10241024];
static int mynumallocs = 0;
#include <stdio.h>
int btDumpMemoryLeaks()
{
int totalLeak = 0;
for (int i=0;i<mynumallocs;i++)
{
printf("Error: leaked memory of allocation #%d (%d bytes)\n", allocations_id[i], allocations_bytes[i]);
totalLeak+=allocations_bytes[i];
}
if (totalLeak)
{
printf("Error: memory leaks: %d allocations were not freed and leaked together %d bytes\n",mynumallocs,totalLeak);
}
return totalLeak;
}
//this generic allocator provides the total allocated number of bytes
#include <stdio.h>
struct btDebugPtrMagic
{
union
{
void** vptrptr;
void* vptr;
int* iptr;
char* cptr;
};
};
void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename)
{
if (size==0)
{
printf("Whaat? size==0");
return 0;
}
static int allocId = 0;
void *ret;
char *real;
// to find some particular memory leak, you could do something like this:
// if (allocId==172)
// {
// printf("catch me!\n");
// }
// if (size>1024*1024)
// {
// printf("big alloc!%d\n", size);
// }
gTotalBytesAlignedAllocs += size;
gNumAlignedAllocs++;
real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1));
int sz4prt = 4*sizeof(void *);
real = (char *)sAllocFunc(size + sz4prt + (alignment-1));
if (real) {
ret = (void*) btAlignPointer(real + 2*sizeof(void *), alignment);
*((void **)(ret)-1) = (void *)(real);
*((int*)(ret)-2) = size;
ret = (void*) btAlignPointer(real + sz4prt, alignment);
btDebugPtrMagic p;
p.vptr = ret;
p.cptr-=sizeof(void*);
*p.vptrptr = (void*)real;
p.cptr-=sizeof(void*);
*p.iptr = size;
p.cptr-=sizeof(void*);
*p.iptr = allocId;
allocations_id[mynumallocs] = allocId;
allocations_bytes[mynumallocs] = size;
mynumallocs++;
} else {
ret = (void *)(real);//??
}
printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size);
printf("allocation %d at address %x, from %s,line %d, size %d (total allocated = %d)\n",allocId,real, filename,line,size,gTotalBytesAlignedAllocs);
allocId++;
int* ptr = (int*)ret;
*ptr = 12;
return (ret);
@ -138,19 +202,43 @@ void btAlignedFreeInternal (void* ptr,int line,char* filename)
{
void* real;
gNumAlignedFree++;
if (ptr) {
real = *((void **)(ptr)-1);
int size = *((int*)(ptr)-2);
gTotalBytesAlignedAllocs -= size;
gNumAlignedFree++;
printf("free #%d at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size);
btDebugPtrMagic p;
p.vptr = ptr;
p.cptr-=sizeof(void*);
real = *p.vptrptr;
p.cptr-=sizeof(void*);
int size = *p.iptr;
p.cptr-=sizeof(void*);
int allocId = *p.iptr;
bool found = false;
for (int i=0;i<mynumallocs;i++)
{
if ( allocations_id[i] == allocId)
{
allocations_id[i] = allocations_id[mynumallocs-1];
allocations_bytes[i] = allocations_bytes[mynumallocs-1];
mynumallocs--;
found = true;
break;
}
}
gTotalBytesAlignedAllocs -= size;
int diff = gNumAlignedAllocs-gNumAlignedFree;
printf("free %d at address %x, from %s,line %d, size %d (total remain = %d in %d non-freed allocations)\n",allocId,real, filename,line,size, gTotalBytesAlignedAllocs, diff);
sFreeFunc(real);
} else
{
printf("NULL ptr\n");
//printf("deleting a NULL ptr, no effect\n");
}
}

View file

@ -21,9 +21,15 @@ subject to the following restrictions:
///that is better portable and more predictable
#include "btScalar.h"
//#define BT_DEBUG_MEMORY_ALLOCATIONS 1
///BT_DEBUG_MEMORY_ALLOCATIONS preprocessor can be set in build system
///for regression tests to detect memory leaks
///#define BT_DEBUG_MEMORY_ALLOCATIONS 1
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
int btDumpMemoryLeaks();
#define btAlignedAlloc(a,b) \
btAlignedAllocInternal(a,b,__LINE__,__FILE__)

View file

@ -39,6 +39,12 @@ subject to the following restrictions:
#include <new> //for placement new
#endif //BT_USE_PLACEMENT_NEW
// The register keyword is deprecated in C++11 so don't use it.
#if __cplusplus > 199711L
#define BT_REGISTER
#else
#define BT_REGISTER register
#endif
///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
@ -202,24 +208,16 @@ protected:
///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 resizeNoInitialize(int newsize)
{
int curSize = size();
if (newsize < curSize)
if (newsize > size())
{
} else
{
if (newsize > size())
{
reserve(newsize);
}
//leave this uninitialized
reserve(newsize);
}
m_size = newsize;
}
SIMD_FORCE_INLINE void resize(int newsize, const T& fillData=T())
{
int curSize = size();
const BT_REGISTER int curSize = size();
if (newsize < curSize)
{
@ -229,7 +227,7 @@ protected:
}
} else
{
if (newsize > size())
if (newsize > curSize)
{
reserve(newsize);
}
@ -246,7 +244,7 @@ protected:
}
SIMD_FORCE_INLINE T& expandNonInitializing( )
{
int sz = size();
const BT_REGISTER int sz = size();
if( sz == capacity() )
{
reserve( allocSize(size()) );
@ -259,7 +257,7 @@ protected:
SIMD_FORCE_INLINE T& expand( const T& fillValue=T())
{
int sz = size();
const BT_REGISTER int sz = size();
if( sz == capacity() )
{
reserve( allocSize(size()) );
@ -275,7 +273,7 @@ protected:
SIMD_FORCE_INLINE void push_back(const T& _Val)
{
int sz = size();
const BT_REGISTER int sz = size();
if( sz == capacity() )
{
reserve( allocSize(size()) );
@ -324,7 +322,7 @@ protected:
{
public:
bool operator() ( const T& a, const T& b )
bool operator() ( const T& a, const T& b ) const
{
return ( a < b );
}

View file

@ -87,7 +87,7 @@ btVector3 NormalOf(const btVector3 *vert, const int n);
btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1)
{
// returns the point where the line p0-p1 intersects the plane n&d
static btVector3 dif;
btVector3 dif;
dif = p1-p0;
btScalar dn= btDot(plane.normal,dif);
btScalar t = -(plane.dist+btDot(plane.normal,p0) )/dn;
@ -112,7 +112,7 @@ btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v
btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint)
{
static btVector3 cp;
btVector3 cp;
cp = btCross(udir,vdir).normalized();
btScalar distu = -btDot(cp,ustart);

View file

@ -0,0 +1,92 @@
#ifndef BT_CPU_UTILITY_H
#define BT_CPU_UTILITY_H
#include "LinearMath/btScalar.h"
#include <string.h>//memset
#ifdef USE_SIMD
#include <emmintrin.h>
#ifdef BT_ALLOW_SSE4
#include <intrin.h>
#endif //BT_ALLOW_SSE4
#endif //USE_SIMD
#if defined BT_USE_NEON
#define ARM_NEON_GCC_COMPATIBILITY 1
#include <arm_neon.h>
#include <sys/types.h>
#include <sys/sysctl.h> //for sysctlbyname
#endif //BT_USE_NEON
///Rudimentary btCpuFeatureUtility for CPU features: only report the features that Bullet actually uses (SSE4/FMA3, NEON_HPFP)
///We assume SSE2 in case BT_USE_SSE2 is defined in LinearMath/btScalar.h
class btCpuFeatureUtility
{
public:
enum btCpuFeature
{
CPU_FEATURE_FMA3=1,
CPU_FEATURE_SSE4_1=2,
CPU_FEATURE_NEON_HPFP=4
};
static int getCpuFeatures()
{
static int capabilities = 0;
static bool testedCapabilities = false;
if (0 != testedCapabilities)
{
return capabilities;
}
#ifdef BT_USE_NEON
{
uint32_t hasFeature = 0;
size_t featureSize = sizeof(hasFeature);
int err = sysctlbyname("hw.optional.neon_hpfp", &hasFeature, &featureSize, NULL, 0);
if (0 == err && hasFeature)
capabilities |= CPU_FEATURE_NEON_HPFP;
}
#endif //BT_USE_NEON
#ifdef BT_ALLOW_SSE4
{
int cpuInfo[4];
memset(cpuInfo, 0, sizeof(cpuInfo));
unsigned long long sseExt = 0;
__cpuid(cpuInfo, 1);
bool osUsesXSAVE_XRSTORE = cpuInfo[2] & (1 << 27) || false;
bool cpuAVXSuport = cpuInfo[2] & (1 << 28) || false;
if (osUsesXSAVE_XRSTORE && cpuAVXSuport)
{
sseExt = _xgetbv(0);
}
const int OSXSAVEFlag = (1UL << 27);
const int AVXFlag = ((1UL << 28) | OSXSAVEFlag);
const int FMAFlag = ((1UL << 12) | AVXFlag | OSXSAVEFlag);
if ((cpuInfo[2] & FMAFlag) == FMAFlag && (sseExt & 6) == 6)
{
capabilities |= btCpuFeatureUtility::CPU_FEATURE_FMA3;
}
const int SSE41Flag = (1 << 19);
if (cpuInfo[2] & SSE41Flag)
{
capabilities |= btCpuFeatureUtility::CPU_FEATURE_SSE4_1;
}
}
#endif//BT_ALLOW_SSE4
testedCapabilities = true;
return capabilities;
}
};
#endif //BT_CPU_UTILITY_H

View file

@ -25,14 +25,14 @@ ATTRIBUTE_ALIGNED16(struct) btDefaultMotionState : public btMotionState
///synchronizes world transform from user to physics
virtual void getWorldTransform(btTransform& centerOfMassWorldTrans ) const
{
centerOfMassWorldTrans = m_centerOfMassOffset.inverse() * m_graphicsWorldTrans ;
centerOfMassWorldTrans = m_graphicsWorldTrans * m_centerOfMassOffset.inverse() ;
}
///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 ;
m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset;
}

View file

@ -85,9 +85,17 @@ inline void GrahamScanConvexHull2D(btAlignedObjectArray<GrahamVector3>& original
originalPoints[0].m_angle = -1e30f;
for (int i=1;i<originalPoints.size();i++)
{
btVector3 xvec = axis0;
btVector3 ar = originalPoints[i]-originalPoints[0];
originalPoints[i].m_angle = btCross(xvec, ar).dot(normalAxis) / ar.length();
btVector3 ar = originalPoints[i]-originalPoints[0];
btScalar ar1 = axis1.dot(ar);
btScalar ar0 = axis0.dot(ar);
if( ar1*ar1+ar0*ar0 < FLT_EPSILON )
{
originalPoints[i].m_angle = 0.0f;
}
else
{
originalPoints[i].m_angle = btAtan2Fast(ar1, ar0);
}
}
//step 2: sort all points, based on 'angle' with this anchor
@ -111,6 +119,11 @@ inline void GrahamScanConvexHull2D(btAlignedObjectArray<GrahamVector3>& original
else
hull.push_back(originalPoints[i]);
}
if( hull.size() == 1 )
{
hull.push_back( originalPoints[i] );
}
}
}

View file

@ -395,10 +395,27 @@ protected:
return &m_valueArray[index];
}
Key getKeyAtIndex(int index)
{
btAssert(index < m_keyArray.size());
return m_keyArray[index];
}
const Key getKeyAtIndex(int index) const
{
btAssert(index < m_keyArray.size());
return m_keyArray[index];
}
Value* operator[](const Key& key) {
return find(key);
}
const Value* operator[](const Key& key) const {
return find(key);
}
const Value* find(const Key& key) const
{
int index = findIndex(key);

View file

@ -21,6 +21,7 @@ subject to the following restrictions:
#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.
@ -29,6 +30,29 @@ class btIDebugDraw
{
public:
ATTRIBUTE_ALIGNED16(struct) DefaultColors
{
btVector3 m_activeObject;
btVector3 m_deactivatedObject;
btVector3 m_wantsDeactivationObject;
btVector3 m_disabledDeactivationObject;
btVector3 m_disabledSimulationObject;
btVector3 m_aabb;
btVector3 m_contactPoint;
DefaultColors()
: m_activeObject(1,1,1),
m_deactivatedObject(0,1,0),
m_wantsDeactivationObject(0,1,1),
m_disabledDeactivationObject(1,0,0),
m_disabledSimulationObject(1,1,0),
m_aabb(1,0,0),
m_contactPoint(1,1,0)
{
}
};
enum DebugDrawModes
{
DBG_NoDebug=0,
@ -46,12 +70,18 @@ class btIDebugDraw
DBG_DrawConstraints = (1 << 11),
DBG_DrawConstraintLimits = (1 << 12),
DBG_FastWireframe = (1<<13),
DBG_DrawNormals = (1<<14),
DBG_DrawNormals = (1<<14),
DBG_DrawFrames = (1<<15),
DBG_MAX_DEBUG_DRAW_MODE
};
virtual ~btIDebugDraw() {};
virtual DefaultColors getDefaultColors() const { DefaultColors colors; return colors; }
///the default implementation for setDefaultColors has no effect. A derived class can implement it and store the colors.
virtual void setDefaultColors(const DefaultColors& /*colors*/) {}
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)
@ -136,9 +166,9 @@ class btIDebugDraw
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));
drawLine(start, start+transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(1.f,0.3,0.3));
drawLine(start, start+transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(0.3,1.f, 0.3));
drawLine(start, start+transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(0.3, 0.3,1.f));
}
virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle,
@ -147,7 +177,7 @@ class btIDebugDraw
const btVector3& vx = axis;
btVector3 vy = normal.cross(axis);
btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
int nSteps = (int)((maxAngle - minAngle) / step);
int nSteps = (int)btFabs((maxAngle - minAngle) / step);
if(!nSteps) nSteps = 1;
btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle);
if(drawSect)
@ -438,6 +468,10 @@ class btIDebugDraw
drawLine(transform*pt0,transform*pt1,color);
drawLine(transform*pt2,transform*pt3,color);
}
virtual void flushLines()
{
}
};

View file

@ -610,6 +610,27 @@ public:
/**@brief Return the inverse of the matrix */
btMatrix3x3 inverse() const;
/// Solve A * x = b, where b is a column vector. This is more efficient
/// than computing the inverse in one-shot cases.
///Solve33 is from Box2d, thanks to Erin Catto,
btVector3 solve33(const btVector3& b) const
{
btVector3 col1 = getColumn(0);
btVector3 col2 = getColumn(1);
btVector3 col3 = getColumn(2);
btScalar det = btDot(col1, btCross(col2, col3));
if (btFabs(det)>SIMD_EPSILON)
{
det = 1.0f / det;
}
btVector3 x;
x[0] = det * btDot(b, btCross(col2, col3));
x[1] = det * btDot(col1, btCross(b, col3));
x[2] = det * btDot(col1, btCross(col2, b));
return x;
}
btMatrix3x3 transposeTimes(const btMatrix3x3& m) const;
btMatrix3x3 timesTranspose(const btMatrix3x3& m) const;
@ -1026,7 +1047,8 @@ 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));
//btFullAssert(det != btScalar(0.0));
btAssert(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,
@ -1308,7 +1330,9 @@ SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2)
c0 = _mm_and_ps(c0, c1);
c0 = _mm_and_ps(c0, c2);
return (0x7 == _mm_movemask_ps((__m128)c0));
int m = _mm_movemask_ps((__m128)c0);
return (0x7 == (m & 0x7));
#else
return
( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&

View file

@ -19,6 +19,13 @@ subject to the following restrictions:
#include "LinearMath/btQuickprof.h"
#include "LinearMath/btAlignedObjectArray.h"
#include <stdio.h>
//#define BT_DEBUG_OSTREAM
#ifdef BT_DEBUG_OSTREAM
#include <iostream>
#include <iomanip> // std::setw
#endif //BT_DEBUG_OSTREAM
class btIntSortPredicate
{
@ -30,6 +37,121 @@ class btIntSortPredicate
};
template <typename T>
struct btVectorX
{
btAlignedObjectArray<T> m_storage;
btVectorX()
{
}
btVectorX(int numRows)
{
m_storage.resize(numRows);
}
void resize(int rows)
{
m_storage.resize(rows);
}
int cols() const
{
return 1;
}
int rows() const
{
return m_storage.size();
}
int size() const
{
return rows();
}
T nrm2() const
{
T norm = T(0);
int nn = rows();
{
if (nn == 1)
{
norm = btFabs((*this)[0]);
}
else
{
T scale = 0.0;
T ssq = 1.0;
/* The following loop is equivalent to this call to the LAPACK
auxiliary routine: CALL SLASSQ( N, X, INCX, SCALE, SSQ ) */
for (int ix=0;ix<nn;ix++)
{
if ((*this)[ix] != 0.0)
{
T absxi = btFabs((*this)[ix]);
if (scale < absxi)
{
T temp;
temp = scale / absxi;
ssq = ssq * (temp * temp) + BT_ONE;
scale = absxi;
}
else
{
T temp;
temp = absxi / scale;
ssq += temp * temp;
}
}
}
norm = scale * sqrt(ssq);
}
}
return norm;
}
void setZero()
{
if (m_storage.size())
{
// for (int i=0;i<m_storage.size();i++)
// m_storage[i]=0;
//memset(&m_storage[0],0,sizeof(T)*m_storage.size());
btSetZero(&m_storage[0],m_storage.size());
}
}
const T& operator[] (int index) const
{
return m_storage[index];
}
T& operator[] (int index)
{
return m_storage[index];
}
T* getBufferPointerWritable()
{
return m_storage.size() ? &m_storage[0] : 0;
}
const T* getBufferPointer() const
{
return m_storage.size() ? &m_storage[0] : 0;
}
};
/*
template <typename T>
void setElem(btMatrixX<T>& mat, int row, int col, T val)
{
mat.setElem(row,col,val);
}
*/
template <typename T>
struct btMatrixX
{
@ -40,8 +162,7 @@ struct btMatrixX
int m_setElemOperations;
btAlignedObjectArray<T> m_storage;
btAlignedObjectArray< btAlignedObjectArray<int> > m_rowNonZeroElements1;
btAlignedObjectArray< btAlignedObjectArray<int> > m_colNonZeroElements;
mutable btAlignedObjectArray< btAlignedObjectArray<int> > m_rowNonZeroElements1;
T* getBufferPointerWritable()
{
@ -78,7 +199,6 @@ struct btMatrixX
BT_PROFILE("m_storage.resize");
m_storage.resize(rows*cols);
}
clearSparseInfo();
}
int cols() const
{
@ -109,49 +229,44 @@ struct btMatrixX
}
}
void setElem(int row,int col, T val)
{
m_setElemOperations++;
m_storage[row*m_cols+col] = val;
}
void mulElem(int row,int col, T val)
{
m_setElemOperations++;
//mul doesn't change sparsity info
m_storage[row*m_cols+col] *= val;
}
void copyLowerToUpperTriangle()
{
int count=0;
for (int row=0;row<m_rowNonZeroElements1.size();row++)
for (int row=0;row<rows();row++)
{
for (int j=0;j<m_rowNonZeroElements1[row].size();j++)
for (int col=0;col<row;col++)
{
int col = m_rowNonZeroElements1[row][j];
setElem(col,row, (*this)(row,col));
count++;
}
}
//printf("copyLowerToUpperTriangle copied %d elements out of %dx%d=%d\n", count,rows(),cols(),cols()*rows());
}
void setElem(int row,int col, T val)
{
m_setElemOperations++;
if (val)
{
if (m_storage[col+row*m_cols]==0.f)
{
m_rowNonZeroElements1[row].push_back(col);
m_colNonZeroElements[col].push_back(row);
}
m_storage[row*m_cols+col] = val;
}
}
const T& operator() (int row,int col) const
{
return m_storage[col+row*m_cols];
}
void clearSparseInfo()
{
BT_PROFILE("clearSparseInfo=0");
m_rowNonZeroElements1.resize(m_rows);
m_colNonZeroElements.resize(m_cols);
for (int i=0;i<m_rows;i++)
m_rowNonZeroElements1[i].resize(0);
for (int j=0;j<m_cols;j++)
m_colNonZeroElements[j].resize(0);
}
void setZero()
{
@ -162,12 +277,21 @@ struct btMatrixX
//for (int i=0;i<m_storage.size();i++)
// m_storage[i]=0;
}
}
void setIdentity()
{
btAssert(rows() == cols());
setZero();
for (int row=0;row<rows();row++)
{
BT_PROFILE("clearSparseInfo=0");
clearSparseInfo();
setElem(row,row,1);
}
}
void printMatrix(const char* msg)
{
printf("%s ---------------------\n",msg);
@ -182,28 +306,9 @@ struct btMatrixX
printf("\n---------------------\n");
}
void printNumZeros(const char* msg)
{
printf("%s: ",msg);
int numZeros = 0;
for (int i=0;i<m_storage.size();i++)
if (m_storage[i]==0)
numZeros++;
int total = m_cols*m_rows;
int computedNonZero = total-numZeros;
int nonZero = 0;
for (int i=0;i<m_colNonZeroElements.size();i++)
nonZero += m_colNonZeroElements[i].size();
btAssert(computedNonZero==nonZero);
if(computedNonZero!=nonZero)
{
printf("Error: computedNonZero=%d, but nonZero=%d\n",computedNonZero,nonZero);
}
//printf("%d numZeros out of %d (%f)\n",numZeros,m_cols*m_rows,numZeros/(m_cols*m_rows));
printf("total %d, %d rows, %d cols, %d non-zeros (%f %)\n", total, rows(),cols(), nonZero,100.f*(T)nonZero/T(total));
}
/*
void rowComputeNonZeroElements()
void rowComputeNonZeroElements() const
{
m_rowNonZeroElements1.resize(rows());
for (int i=0;i<rows();i++)
@ -218,13 +323,11 @@ struct btMatrixX
}
}
}
*/
btMatrixX transpose() const
{
//transpose is optimized for sparse matrices
btMatrixX tr(m_cols,m_rows);
tr.setZero();
#if 0
for (int i=0;i<m_cols;i++)
for (int j=0;j<m_rows;j++)
{
@ -234,37 +337,13 @@ struct btMatrixX
tr.setElem(i,j,v);
}
}
#else
for (int i=0;i<m_colNonZeroElements.size();i++)
for (int h=0;h<m_colNonZeroElements[i].size();h++)
{
int j = m_colNonZeroElements[i][h];
T v = (*this)(j,i);
tr.setElem(i,j,v);
}
#endif
return tr;
}
void sortRowIndexArrays()
{
for (int i=0;i<m_rowNonZeroElements1[i].size();i++)
{
m_rowNonZeroElements1[i].quickSort(btIntSortPredicate());
}
}
void sortColIndexArrays()
{
for (int i=0;i<m_colNonZeroElements[i].size();i++)
{
m_colNonZeroElements[i].quickSort(btIntSortPredicate());
}
}
btMatrixX operator*(const btMatrixX& other)
{
//btMatrixX*btMatrixX implementation, optimized for sparse matrices
//btMatrixX*btMatrixX implementation, brute force
btAssert(cols() == other.rows());
btMatrixX res(rows(),other.cols());
@ -272,76 +351,18 @@ struct btMatrixX
// BT_PROFILE("btMatrixX mul");
for (int j=0; j < res.cols(); ++j)
{
//int numZero=other.m_colNonZeroElements[j].size();
//if (numZero)
{
for (int i=0; i < res.rows(); ++i)
//for (int g = 0;g<m_colNonZeroElements[j].size();g++)
{
T dotProd=0;
T dotProd2=0;
int waste=0,waste2=0;
// T dotProd2=0;
//int waste=0,waste2=0;
bool doubleWalk = false;
if (doubleWalk)
{
int numRows = m_rowNonZeroElements1[i].size();
int numOtherCols = other.m_colNonZeroElements[j].size();
for (int ii=0;ii<numRows;ii++)
// bool useOtherCol = true;
{
int vThis=m_rowNonZeroElements1[i][ii];
}
for (int ii=0;ii<numOtherCols;ii++)
{
int vOther = other.m_colNonZeroElements[j][ii];
}
int indexRow = 0;
int indexOtherCol = 0;
while (indexRow < numRows && indexOtherCol < numOtherCols)
{
int vThis=m_rowNonZeroElements1[i][indexRow];
int vOther = other.m_colNonZeroElements[j][indexOtherCol];
if (vOther==vThis)
for (int v=0;v<rows();v++)
{
dotProd += (*this)(i,vThis) * other(vThis,j);
}
if (vThis<vOther)
{
indexRow++;
} else
{
indexOtherCol++;
}
}
} else
{
bool useOtherCol = true;
if (other.m_colNonZeroElements[j].size() <m_rowNonZeroElements1[i].size())
{
useOtherCol=true;
}
if (!useOtherCol )
{
for (int q=0;q<other.m_colNonZeroElements[j].size();q++)
{
int v = other.m_colNonZeroElements[j][q];
T w = (*this)(i,v);
if (w!=0.f)
{
dotProd+=w*other(v,j);
}
}
}
else
{
for (int q=0;q<m_rowNonZeroElements1[i].size();q++)
{
int v=m_rowNonZeroElements1[i][q];
T w = (*this)(i,v);
if (other(v,j)!=0.f)
{
@ -404,73 +425,61 @@ struct btMatrixX
bb += 8;
}
}
};
template <typename T>
struct btVectorX
{
btAlignedObjectArray<T> m_storage;
btVectorX()
void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const T value)
{
int numRows = rowend+1-rowstart;
int numCols = colend+1-colstart;
for (int row=0;row<numRows;row++)
{
for (int col=0;col<numCols;col++)
{
setElem(rowstart+row,colstart+col,value);
}
}
}
btVectorX(int numRows)
void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const btMatrixX& block)
{
m_storage.resize(numRows);
btAssert(rowend+1-rowstart == block.rows());
btAssert(colend+1-colstart == block.cols());
for (int row=0;row<block.rows();row++)
{
for (int col=0;col<block.cols();col++)
{
setElem(rowstart+row,colstart+col,block(row,col));
}
}
}
void resize(int rows)
void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const btVectorX<T>& block)
{
m_storage.resize(rows);
btAssert(rowend+1-rowstart == block.rows());
btAssert(colend+1-colstart == block.cols());
for (int row=0;row<block.rows();row++)
{
for (int col=0;col<block.cols();col++)
{
setElem(rowstart+row,colstart+col,block[row]);
}
}
}
int cols() const
btMatrixX negative()
{
return 1;
}
int rows() const
{
return m_storage.size();
}
int size() const
{
return rows();
}
void setZero()
{
// for (int i=0;i<m_storage.size();i++)
// m_storage[i]=0;
//memset(&m_storage[0],0,sizeof(T)*m_storage.size());
btSetZero(&m_storage[0],m_storage.size());
}
const T& operator[] (int index) const
{
return m_storage[index];
}
T& operator[] (int index)
{
return m_storage[index];
}
T* getBufferPointerWritable()
{
return m_storage.size() ? &m_storage[0] : 0;
}
const T* getBufferPointer() const
{
return m_storage.size() ? &m_storage[0] : 0;
btMatrixX neg(rows(),cols());
for (int i=0;i<rows();i++)
for (int j=0;j<cols();j++)
{
T v = (*this)(i,j);
neg.setElem(i,j,-v);
}
return neg;
}
};
/*
template <typename T>
void setElem(btMatrixX<T>& mat, int row, int col, T val)
{
mat.setElem(row,col,val);
}
*/
typedef btMatrixX<float> btMatrixXf;
@ -480,6 +489,47 @@ typedef btMatrixX<double> btMatrixXd;
typedef btVectorX<double> btVectorXd;
#ifdef BT_DEBUG_OSTREAM
template <typename T>
std::ostream& operator<< (std::ostream& os, const btMatrixX<T>& mat)
{
os << " [";
//printf("%s ---------------------\n",msg);
for (int i=0;i<mat.rows();i++)
{
for (int j=0;j<mat.cols();j++)
{
os << std::setw(12) << mat(i,j);
}
if (i!=mat.rows()-1)
os << std::endl << " ";
}
os << " ]";
//printf("\n---------------------\n");
return os;
}
template <typename T>
std::ostream& operator<< (std::ostream& os, const btVectorX<T>& mat)
{
os << " [";
//printf("%s ---------------------\n",msg);
for (int i=0;i<mat.rows();i++)
{
os << std::setw(12) << mat[i];
if (i!=mat.rows()-1)
os << std::endl << " ";
}
os << " ]";
//printf("\n---------------------\n");
return os;
}
#endif //BT_DEBUG_OSTREAM
inline void setElem(btMatrixXd& mat, int row, int col, double val)
{

View file

@ -30,8 +30,7 @@ namespace
}
}
const btScalar btPolarDecomposition::DEFAULT_TOLERANCE = btScalar(0.0001);
const unsigned int btPolarDecomposition::DEFAULT_MAX_ITERATIONS = 16;
btPolarDecomposition::btPolarDecomposition(btScalar tolerance, unsigned int maxIterations)
: m_tolerance(tolerance)

View file

@ -14,8 +14,7 @@
class btPolarDecomposition
{
public:
static const btScalar DEFAULT_TOLERANCE;
static const unsigned int DEFAULT_MAX_ITERATIONS;
/**
* Creates an instance with optional parameters.
@ -25,8 +24,8 @@ class btPolarDecomposition
* @param maxIterations - the maximum number of iterations used to achieve
* convergence
*/
btPolarDecomposition(btScalar tolerance = DEFAULT_TOLERANCE,
unsigned int maxIterations = DEFAULT_MAX_ITERATIONS);
btPolarDecomposition(btScalar tolerance = btScalar(0.0001),
unsigned int maxIterations = 16);
/**
* Decomposes a matrix into orthogonal and symmetric, positive-definite

View file

@ -18,6 +18,7 @@ subject to the following restrictions:
#include "btScalar.h"
#include "btAlignedAllocator.h"
#include "btThreads.h"
///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
class btPoolAllocator
@ -27,6 +28,7 @@ class btPoolAllocator
int m_freeCount;
void* m_firstFree;
unsigned char* m_pool;
btSpinMutex m_mutex; // only used if BT_THREADSAFE
public:
@ -71,11 +73,16 @@ public:
{
// release mode fix
(void)size;
btMutexLock(&m_mutex);
btAssert(!size || size<=m_elemSize);
btAssert(m_freeCount>0);
//btAssert(m_freeCount>0); // should return null if all full
void* result = m_firstFree;
m_firstFree = *(void**)m_firstFree;
--m_freeCount;
if (NULL != m_firstFree)
{
m_firstFree = *(void**)m_firstFree;
--m_freeCount;
}
btMutexUnlock(&m_mutex);
return result;
}
@ -95,9 +102,11 @@ public:
if (ptr) {
btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
btMutexLock(&m_mutex);
*(void**)ptr = m_firstFree;
m_firstFree = ptr;
++m_freeCount;
btMutexUnlock(&m_mutex);
}
}

View file

@ -73,7 +73,7 @@ public:
public:
#if defined(BT_USE_SSE) || defined(BT_USE_NEON)
#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
// Set Vector
SIMD_FORCE_INLINE btQuadWord(const btSimdFloat4 vec)

View file

@ -22,6 +22,13 @@ subject to the following restrictions:
#include "btQuadWord.h"
#ifdef BT_USE_DOUBLE_PRECISION
#define btQuaternionData btQuaternionDoubleData
#define btQuaternionDataName "btQuaternionDoubleData"
#else
#define btQuaternionData btQuaternionFloatData
#define btQuaternionDataName "btQuaternionFloatData"
#endif //BT_USE_DOUBLE_PRECISION
@ -411,22 +418,21 @@ public:
return btAcos(dot(q) / s) * btScalar(2.0);
}
/**@brief Return the angle of rotation represented by this quaternion */
/**@brief Return the angle [0, 2Pi] of rotation represented by this quaternion */
btScalar getAngle() const
{
btScalar s = btScalar(2.) * btAcos(m_floats[3]);
return s;
}
/**@brief Return the angle of rotation represented by this quaternion along the shortest path*/
/**@brief Return the angle [0, Pi] of rotation represented by this quaternion along the shortest path */
btScalar getAngleShortestPath() const
{
btScalar s;
if (dot(*this) < 0)
if (m_floats[3] >= 0)
s = btScalar(2.) * btAcos(m_floats[3]);
else
s = btScalar(2.) * btAcos(-m_floats[3]);
return s;
}
@ -526,25 +532,29 @@ public:
* Slerp interpolates assuming constant velocity. */
btQuaternion slerp(const btQuaternion& q, const btScalar& t) const
{
btScalar magnitude = btSqrt(length2() * q.length2());
btAssert(magnitude > btScalar(0));
btScalar product = dot(q) / magnitude;
if (btFabs(product) < btScalar(1))
const btScalar magnitude = btSqrt(length2() * q.length2());
btAssert(magnitude > btScalar(0));
const btScalar product = dot(q) / magnitude;
const btScalar absproduct = btFabs(product);
if(absproduct < btScalar(1.0 - SIMD_EPSILON))
{
// Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1);
const btScalar theta = btAcos(sign * product);
const btScalar s1 = btSin(sign * t * theta);
const btScalar d = btScalar(1.0) / btSin(theta);
const btScalar s0 = btSin((btScalar(1.0) - t) * theta);
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);
// Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
const btScalar theta = btAcos(absproduct);
const btScalar d = btSin(theta);
btAssert(d > btScalar(0));
const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1);
const btScalar s0 = btSin((btScalar(1.0) - t) * theta) / d;
const btScalar s1 = btSin(sign * t * theta) / d;
return btQuaternion(
(m_floats[0] * s0 + q.x() * s1),
(m_floats[1] * s0 + q.y() * s1),
(m_floats[2] * s0 + q.z() * s1),
(m_floats[3] * s0 + q.w() * s1));
}
else
{
@ -560,7 +570,18 @@ public:
SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; }
SIMD_FORCE_INLINE void serialize(struct btQuaternionData& dataOut) const;
SIMD_FORCE_INLINE void deSerialize(const struct btQuaternionData& dataIn);
SIMD_FORCE_INLINE void serializeFloat(struct btQuaternionFloatData& dataOut) const;
SIMD_FORCE_INLINE void deSerializeFloat(const struct btQuaternionFloatData& dataIn);
SIMD_FORCE_INLINE void serializeDouble(struct btQuaternionDoubleData& dataOut) const;
SIMD_FORCE_INLINE void deSerializeDouble(const struct btQuaternionDoubleData& dataIn);
};
@ -903,6 +924,62 @@ shortestArcQuatNormalize2(btVector3& v0,btVector3& v1)
return shortestArcQuat(v0,v1);
}
struct btQuaternionFloatData
{
float m_floats[4];
};
struct btQuaternionDoubleData
{
double m_floats[4];
};
SIMD_FORCE_INLINE void btQuaternion::serializeFloat(struct btQuaternionFloatData& 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 btQuaternion::deSerializeFloat(const struct btQuaternionFloatData& dataIn)
{
for (int i=0;i<4;i++)
m_floats[i] = btScalar(dataIn.m_floats[i]);
}
SIMD_FORCE_INLINE void btQuaternion::serializeDouble(struct btQuaternionDoubleData& 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 btQuaternion::deSerializeDouble(const struct btQuaternionDoubleData& dataIn)
{
for (int i=0;i<4;i++)
m_floats[i] = btScalar(dataIn.m_floats[i]);
}
SIMD_FORCE_INLINE void btQuaternion::serialize(struct btQuaternionData& 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 btQuaternion::deSerialize(const struct btQuaternionData& dataIn)
{
for (int i=0;i<4;i++)
m_floats[i] = dataIn.m_floats[i];
}
#endif //BT_SIMD__QUATERNION_H_

View file

@ -10,15 +10,15 @@
**
***************************************************************************************************/
// Credits: The Clock class was inspired by the Timer classes in
// 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;
#if BT_THREADSAFE
#include "btThreads.h"
#endif //#if BT_THREADSAFE
#ifdef __CELLOS_LV2__
@ -27,8 +27,8 @@ static btClock gProfileClock;
#include <stdio.h>
#endif
#if defined (SUNOS) || defined (__SUNOS__)
#include <stdio.h>
#if defined (SUNOS) || defined (__SUNOS__)
#include <stdio.h>
#endif
#if defined(WIN32) || defined(_WIN32)
@ -37,12 +37,17 @@ static btClock gProfileClock;
#define WIN32_LEAN_AND_MEAN
#define NOWINRES
#define NOMCX
#define NOIME
#define NOIME
#ifdef _XBOX
#include <Xtl.h>
#else //_XBOX
#include <windows.h>
#if WINVER <0x0602
#define GetTickCount64 GetTickCount
#endif
#endif //_XBOX
#include <time.h>
@ -59,7 +64,7 @@ struct btClockData
#ifdef BT_USE_WINDOWS_TIMERS
LARGE_INTEGER mClockFrequency;
DWORD mStartTick;
LONGLONG mStartTick;
LONGLONG mPrevElapsedTime;
LARGE_INTEGER mStartTime;
#else
@ -105,7 +110,7 @@ void btClock::reset()
{
#ifdef BT_USE_WINDOWS_TIMERS
QueryPerformanceCounter(&m_data->mStartTime);
m_data->mStartTick = GetTickCount();
m_data->mStartTick = GetTickCount64();
m_data->mPrevElapsedTime = 0;
#else
#ifdef __CELLOS_LV2__
@ -121,34 +126,34 @@ void btClock::reset()
#endif
}
/// Returns the time in ms since the last call to reset or since
/// 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 -
LONGLONG elapsedTime = currentTime.QuadPart -
m_data->mStartTime.QuadPart;
// Compute the number of millisecond ticks elapsed.
unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
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
// 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;
unsigned long elapsedTicks = (unsigned long)(GetTickCount64() - 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 -
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 /
msecTicks = (unsigned long)(1000 * elapsedTime /
m_data->mClockFrequency.QuadPart);
}
@ -171,36 +176,36 @@ unsigned long int btClock::getTimeMilliseconds()
struct timeval currentTime;
gettimeofday(&currentTime, 0);
return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 +
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
/// 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 -
LONGLONG elapsedTime = currentTime.QuadPart -
m_data->mStartTime.QuadPart;
// Compute the number of millisecond ticks elapsed.
unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
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
// 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;
unsigned long elapsedTicks = (unsigned long)(GetTickCount64() - 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 -
LONGLONG msecAdjustment = mymin(msecOff *
m_data->mClockFrequency.QuadPart / 1000, elapsedTime -
m_data->mPrevElapsedTime);
m_data->mStartTime.QuadPart += msecAdjustment;
elapsedTime -= msecAdjustment;
@ -210,7 +215,7 @@ unsigned long int btClock::getTimeMicroseconds()
m_data->mPrevElapsedTime = elapsedTime;
// Convert to microseconds.
unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime /
unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime /
m_data->mClockFrequency.QuadPart);
return usecTicks;
@ -229,14 +234,26 @@ unsigned long int btClock::getTimeMicroseconds()
struct timeval currentTime;
gettimeofday(&currentTime, 0);
return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 +
return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 +
(currentTime.tv_usec - m_data->mStartTime.tv_usec);
#endif//__CELLOS_LV2__
#endif
#endif
}
/// Returns the time in s since the last call to reset or since
/// the Clock was created.
btScalar btClock::getTimeSeconds()
{
static const btScalar microseconds_to_seconds = btScalar(0.000001);
return btScalar(getTimeMicroseconds()) * microseconds_to_seconds;
}
#ifndef BT_NO_PROFILE
static btClock gProfileClock;
inline void Profile_Get_Ticks(unsigned long int * ticks)
@ -252,7 +269,6 @@ inline float Profile_Get_Tick_Rate(void)
}
/***************************************************************************************************
**
** CProfileNode
@ -293,8 +309,7 @@ void CProfileNode::CleanupMemory()
CProfileNode::~CProfileNode( void )
{
delete ( Child);
delete ( Sibling);
CleanupMemory();
}
@ -318,7 +333,7 @@ CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
}
// We didn't find it, so add it
CProfileNode * node = new CProfileNode( name, this );
node->Sibling = Child;
Child = node;
@ -330,7 +345,7 @@ void CProfileNode::Reset( void )
{
TotalCalls = 0;
TotalTime = 0.0f;
if ( Child ) {
Child->Reset();
@ -352,7 +367,7 @@ void CProfileNode::Call( void )
bool CProfileNode::Return( void )
{
if ( --RecursionCounter == 0 && TotalCalls != 0 ) {
if ( --RecursionCounter == 0 && TotalCalls != 0 ) {
unsigned long int time;
Profile_Get_Ticks(&time);
time-=StartTime;
@ -443,10 +458,18 @@ unsigned long int CProfileManager::ResetTime = 0;
*=============================================================================================*/
void CProfileManager::Start_Profile( const char * name )
{
#if BT_THREADSAFE
// profile system is not designed for profiling multiple threads
// disable collection on all but the main thread
if ( !btIsMainThread() )
{
return;
}
#endif //#if BT_THREADSAFE
if (name != CurrentNode->Get_Name()) {
CurrentNode = CurrentNode->Get_Sub_Node( name );
}
}
CurrentNode->Call();
}
@ -456,6 +479,14 @@ void CProfileManager::Start_Profile( const char * name )
*=============================================================================================*/
void CProfileManager::Stop_Profile( void )
{
#if BT_THREADSAFE
// profile system is not designed for profiling multiple threads
// disable collection on all but the main thread
if ( !btIsMainThread() )
{
return;
}
#endif //#if BT_THREADSAFE
// Return will indicate whether we should back up to our parent (we may
// be profiling a recursive function)
if (CurrentNode->Return()) {
@ -470,7 +501,7 @@ void CProfileManager::Stop_Profile( void )
* 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();
@ -516,9 +547,9 @@ void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spaci
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++;
@ -535,11 +566,11 @@ void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spaci
if (parent_time < accumulated_time)
{
printf("what's wrong\n");
//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);

View file

@ -15,18 +15,7 @@
#ifndef BT_QUICK_PROF_H
#define BT_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
@ -52,6 +41,11 @@ public:
/// Returns the time in us since the last call to reset or since
/// the Clock was created.
unsigned long int getTimeMicroseconds();
/// Returns the time in s since the last call to reset or since
/// the Clock was created.
btScalar getTimeSeconds();
private:
struct btClockData* m_data;
};
@ -59,6 +53,20 @@ private:
#endif //USE_BT_CLOCK
//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 "btAlignedAllocator.h"
#include <new>
///A node in the Profile Hierarchy Tree

View file

@ -17,6 +17,7 @@ subject to the following restrictions:
#ifndef BT_SCALAR_H
#define BT_SCALAR_H
#ifdef BT_MANAGED_CODE
//Aligned data types not supported in managed code
#pragma unmanaged
@ -28,7 +29,7 @@ subject to the following restrictions:
#include <float.h>
/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
#define BT_BULLET_VERSION 282
#define BT_BULLET_VERSION 285
inline int btGetVersion()
{
@ -48,11 +49,16 @@ inline int btGetVersion()
#define ATTRIBUTE_ALIGNED16(a) a
#define ATTRIBUTE_ALIGNED64(a) a
#define ATTRIBUTE_ALIGNED128(a) a
#elif (_M_ARM)
#define SIMD_FORCE_INLINE __forceinline
#define ATTRIBUTE_ALIGNED16(a) __declspec() a
#define ATTRIBUTE_ALIGNED64(a) __declspec() a
#define ATTRIBUTE_ALIGNED128(a) __declspec () 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:4996) //Turn off warnings about deprecated C routines
// #pragma warning(disable:4786) // Disable the "debug name too long" warning
#define SIMD_FORCE_INLINE __forceinline
@ -67,13 +73,20 @@ inline int btGetVersion()
#define btFsel(a,b,c) __fsel((a),(b),(c))
#else
#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))
#if defined (_M_ARM)
//Do not turn SSE on for ARM (may want to turn on BT_USE_NEON however)
#elif (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))
#if _MSC_VER>1400
#define BT_USE_SIMD_VECTOR3
#endif
#define BT_USE_SSE
#ifdef BT_USE_SSE
#if (_MSC_FULL_VER >= 170050727)//Visual Studio 2012 can compile SSE4/FMA3 (but SSE4/FMA3 is not enabled by default)
#define BT_ALLOW_SSE4
#endif //(_MSC_FULL_VER >= 160040219)
//BT_USE_SSE_IN_API is disabled under Windows by default, because
//it makes it harder to integrate Bullet into your application under Windows
//(structured embedding Bullet structs/classes need to be 16-byte aligned)
@ -92,7 +105,7 @@ inline int btGetVersion()
#ifdef BT_DEBUG
#ifdef _MSC_VER
#include <stdio.h>
#define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak(); }}
#define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak(); }}
#else//_MSC_VER
#include <assert.h>
#define btAssert assert
@ -284,6 +297,10 @@ static int btNanMask = 0x7F800001;
#ifndef BT_INFINITY
static int btInfinityMask = 0x7F800000;
#define BT_INFINITY (*(float*)&btInfinityMask)
inline int btGetInfinityMask()//suppress stupid compiler warning
{
return btInfinityMask;
}
#endif
//use this, in case there are clashes (such as xnamath.h)
@ -334,8 +351,23 @@ inline __m128 operator * (const __m128 A, const __m128 B)
#else//BT_USE_NEON
#ifndef BT_INFINITY
static int btInfinityMask = 0x7F800000;
#define BT_INFINITY (*(float*)&btInfinityMask)
struct btInfMaskConverter
{
union {
float mask;
int intmask;
};
btInfMaskConverter(int mask=0x7F800000)
:intmask(mask)
{
}
};
static btInfMaskConverter btInfinityMask = 0x7F800000;
#define BT_INFINITY (btInfinityMask.mask)
inline int btGetInfinityMask()//suppress stupid compiler warning
{
return btInfinityMask.intmask;
}
#endif
#endif//BT_USE_NEON
@ -387,19 +419,30 @@ SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmod(x,y); }
SIMD_FORCE_INLINE btScalar btSqrt(btScalar y)
{
#ifdef USE_APPROXIMATION
#ifdef __LP64__
float xhalf = 0.5f*y;
int i = *(int*)&y;
i = 0x5f375a86 - (i>>1);
y = *(float*)&i;
y = y*(1.5f - xhalf*y*y);
y = y*(1.5f - xhalf*y*y);
y = y*(1.5f - xhalf*y*y);
y=1/y;
return y;
#else
double x, z, tempf;
unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
tempf = y;
*tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */
x = tempf;
z = y*btScalar(0.5);
x = (btScalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */
x = (btScalar(1.5)*x)-(x*x)*(x*z);
x = (btScalar(1.5)*x)-(x*x)*(x*z);
x = (btScalar(1.5)*x)-(x*x)*(x*z);
x = (btScalar(1.5)*x)-(x*x)*(x*z);
return x*y;
tempf = y;
*tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */
x = tempf;
z = y*btScalar(0.5);
x = (btScalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */
x = (btScalar(1.5)*x)-(x*x)*(x*z);
x = (btScalar(1.5)*x)-(x*x)*(x*z);
x = (btScalar(1.5)*x)-(x*x)*(x*z);
x = (btScalar(1.5)*x)-(x*x)*(x*z);
return x*y;
#endif
#else
return sqrtf(y);
#endif
@ -432,7 +475,7 @@ SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmodf(x,y); }
#endif
#define SIMD_PI btScalar(3.1415926535897932384626433832795029)
#define SIMD_2_PI btScalar(2.0) * SIMD_PI
#define SIMD_2_PI (btScalar(2.0) * SIMD_PI)
#define SIMD_HALF_PI (SIMD_PI * btScalar(0.5))
#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0))
#define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI)
@ -444,9 +487,17 @@ SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmodf(x,y); }
#ifdef BT_USE_DOUBLE_PRECISION
#define SIMD_EPSILON DBL_EPSILON
#define SIMD_INFINITY DBL_MAX
#define BT_ONE 1.0
#define BT_ZERO 0.0
#define BT_TWO 2.0
#define BT_HALF 0.5
#else
#define SIMD_EPSILON FLT_EPSILON
#define SIMD_INFINITY FLT_MAX
#define BT_ONE 1.0f
#define BT_ZERO 0.0f
#define BT_TWO 2.0f
#define BT_HALF 0.5f
#endif
SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x)
@ -728,4 +779,5 @@ template <typename T>T* btAlignPointer(T* unalignedPtr, size_t alignment)
return converter.ptr;
}
#endif //BT_SCALAR_H

File diff suppressed because it is too large Load diff

View file

@ -4,8 +4,8 @@ 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,
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.
@ -32,12 +32,12 @@ extern int sBulletDNAlen;
extern char sBulletDNAstr64[];
extern int sBulletDNAlen64;
SIMD_FORCE_INLINE int btStrLen(const char* str)
SIMD_FORCE_INLINE int btStrLen(const char* str)
{
if (!str)
if (!str)
return(0);
int len = 0;
while (*str != 0)
{
str++;
@ -85,7 +85,7 @@ public:
virtual void* getUniquePointer(void*oldPtr) = 0;
virtual void startSerialization() = 0;
virtual void finishSerialization() = 0;
virtual const char* findNameForPointer(const void* ptr) const = 0;
@ -98,6 +98,9 @@ public:
virtual void setSerializationFlags(int flags) = 0;
virtual int getNumChunks() const = 0;
virtual const btChunk* getChunk(int chunkIndex) const = 0;
};
@ -110,6 +113,8 @@ public:
# define BT_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
#endif
#define BT_MULTIBODY_CODE BT_MAKE_ID('M','B','D','Y')
#define BT_SOFTBODY_CODE BT_MAKE_ID('S','B','D','Y')
#define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C','O','B','J')
#define BT_RIGIDBODY_CODE BT_MAKE_ID('R','B','D','Y')
@ -134,21 +139,46 @@ struct btPointerUid
};
};
struct btBulletSerializedArrays
{
btBulletSerializedArrays()
{
}
btAlignedObjectArray<struct btQuantizedBvhDoubleData*> m_bvhsDouble;
btAlignedObjectArray<struct btQuantizedBvhFloatData*> m_bvhsFloat;
btAlignedObjectArray<struct btCollisionShapeData*> m_colShapeData;
btAlignedObjectArray<struct btDynamicsWorldDoubleData*> m_dynamicWorldInfoDataDouble;
btAlignedObjectArray<struct btDynamicsWorldFloatData*> m_dynamicWorldInfoDataFloat;
btAlignedObjectArray<struct btRigidBodyDoubleData*> m_rigidBodyDataDouble;
btAlignedObjectArray<struct btRigidBodyFloatData*> m_rigidBodyDataFloat;
btAlignedObjectArray<struct btCollisionObjectDoubleData*> m_collisionObjectDataDouble;
btAlignedObjectArray<struct btCollisionObjectFloatData*> m_collisionObjectDataFloat;
btAlignedObjectArray<struct btTypedConstraintFloatData*> m_constraintDataFloat;
btAlignedObjectArray<struct btTypedConstraintDoubleData*> m_constraintDataDouble;
btAlignedObjectArray<struct btTypedConstraintData*> m_constraintData;//for backwards compatibility
btAlignedObjectArray<struct btSoftBodyFloatData*> m_softBodyFloatData;
btAlignedObjectArray<struct btSoftBodyDoubleData*> m_softBodyDoubleData;
};
///The btDefaultSerializer is the main Bullet serialization class.
///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
class btDefaultSerializer : public btSerializer
{
protected:
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;
@ -156,6 +186,7 @@ class btDefaultSerializer : public btSerializer
int m_totalSize;
unsigned char* m_buffer;
bool m_ownsBuffer;
int m_currentSize;
void* m_dna;
int m_dnaLength;
@ -164,10 +195,11 @@ class btDefaultSerializer : public btSerializer
btAlignedObjectArray<btChunk*> m_chunkPtrs;
protected:
virtual void* findPointer(void* oldPtr)
virtual void* findPointer(void* oldPtr)
{
void** ptr = m_chunkP.find(oldPtr);
if (ptr && *ptr)
@ -175,11 +207,11 @@ protected:
return 0;
}
void writeDNA()
virtual void writeDNA()
{
btChunk* dnaChunk = allocate(m_dnaLength,1);
memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
@ -193,7 +225,7 @@ protected:
const int* valuePtr = mTypeLookup.find(key);
if (valuePtr)
return *valuePtr;
return -1;
}
@ -205,7 +237,7 @@ protected:
int littleEndian= 1;
littleEndian= ((char*)&littleEndian)[0];
m_dna = btAlignedAlloc(dnalen,16);
memcpy(m_dna,bdnaOrg,dnalen);
@ -233,16 +265,16 @@ protected:
// 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++;
}
@ -260,11 +292,11 @@ protected:
if (!littleEndian)
*intPtr = btSwapEndian(*intPtr);
dataLen = *intPtr;
intPtr++;
cp = (char*)intPtr;
for (i=0; i<dataLen; i++)
{
@ -315,7 +347,7 @@ protected:
if (!littleEndian)
*intPtr = btSwapEndian(*intPtr);
dataLen = *intPtr ;
dataLen = *intPtr ;
intPtr++;
@ -323,7 +355,7 @@ protected:
for (i=0; i<dataLen; i++)
{
mStructs.push_back (shtPtr);
if (!littleEndian)
{
shtPtr[0]= btSwapEndian(shtPtr[0]);
@ -353,20 +385,29 @@ protected:
}
}
public:
public:
btHashMap<btHashPtr,void*> m_skipPointers;
btDefaultSerializer(int totalSize=0)
:m_totalSize(totalSize),
btDefaultSerializer(int totalSize=0, unsigned char* buffer=0)
:m_uniqueIdGenerator(0),
m_totalSize(totalSize),
m_currentSize(0),
m_dna(0),
m_dnaLength(0),
m_serializationFlags(0)
{
m_buffer = m_totalSize?(unsigned char*)btAlignedAlloc(totalSize,16):0;
if (buffer==0)
{
m_buffer = m_totalSize?(unsigned char*)btAlignedAlloc(totalSize,16):0;
m_ownsBuffer = true;
} else
{
m_buffer = buffer;
m_ownsBuffer = false;
}
const bool VOID_IS_8 = ((sizeof(void*)==8));
#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
@ -385,7 +426,7 @@ public:
btAssert(0);
#endif
}
#else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
if (VOID_IS_8)
{
@ -395,27 +436,53 @@ public:
initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
}
#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
}
virtual ~btDefaultSerializer()
virtual ~btDefaultSerializer()
{
if (m_buffer)
if (m_buffer && m_ownsBuffer)
btAlignedFree(m_buffer);
if (m_dna)
btAlignedFree(m_dna);
}
static int getMemoryDnaSizeInBytes()
{
const bool VOID_IS_8 = ((sizeof(void*) == 8));
if (VOID_IS_8)
{
return sBulletDNAlen64;
}
return sBulletDNAlen;
}
static const char* getMemoryDna()
{
const bool VOID_IS_8 = ((sizeof(void*) == 8));
if (VOID_IS_8)
{
return (const char*)sBulletDNAstr64;
}
return (const char*)sBulletDNAstr;
}
void insertHeader()
{
writeHeader(m_buffer);
m_currentSize += BT_HEADER_LENGTH;
}
void writeHeader(unsigned char* buffer) const
{
#ifdef BT_USE_DOUBLE_PRECISION
memcpy(buffer, "BULLETd", 7);
#else
memcpy(buffer, "BULLETf", 7);
#endif //BT_USE_DOUBLE_PRECISION
int littleEndian= 1;
littleEndian= ((char*)&littleEndian)[0];
@ -429,7 +496,7 @@ public:
if (littleEndian)
{
buffer[8]='v';
buffer[8]='v';
} else
{
buffer[8]='V';
@ -438,7 +505,7 @@ public:
buffer[9] = '2';
buffer[10] = '8';
buffer[11] = '2';
buffer[11] = '5';
}
@ -450,7 +517,7 @@ public:
unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
writeHeader(buffer);
}
}
virtual void finishSerialization()
@ -486,6 +553,7 @@ public:
mTlens.clear();
mStructReverse.clear();
mTypeLookup.clear();
m_skipPointers.clear();
m_chunkP.clear();
m_nameMap.clear();
m_uniquePointers.clear();
@ -494,6 +562,7 @@ public:
virtual void* getUniquePointer(void*oldPtr)
{
btAssert(m_uniqueIdGenerator >= 0);
if (!oldPtr)
return 0;
@ -502,8 +571,15 @@ public:
{
return uptr->m_ptr;
}
void** ptr2 = m_skipPointers[oldPtr];
if (ptr2)
{
return 0;
}
m_uniqueIdGenerator++;
btPointerUid uid;
uid.m_uniqueIds[0] = m_uniqueIdGenerator;
uid.m_uniqueIds[1] = m_uniqueIdGenerator;
@ -530,17 +606,17 @@ public:
}
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 unsigned char* internalAlloc(size_t size)
{
unsigned char* ptr = 0;
@ -558,7 +634,7 @@ public:
return ptr;
}
virtual btChunk* allocate(size_t size, int numElements)
{
@ -566,15 +642,15 @@ public:
unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(btChunk));
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;
}
@ -631,9 +707,202 @@ public:
{
m_serializationFlags = flags;
}
int getNumChunks() const
{
return m_chunkPtrs.size();
}
const btChunk* getChunk(int chunkIndex) const
{
return m_chunkPtrs[chunkIndex];
}
};
///In general it is best to use btDefaultSerializer,
///in particular when writing the data to disk or sending it over the network.
///The btInMemorySerializer is experimental and only suitable in a few cases.
///The btInMemorySerializer takes a shortcut and can be useful to create a deep-copy
///of objects. There will be a demo on how to use the btInMemorySerializer.
#ifdef ENABLE_INMEMORY_SERIALIZER
struct btInMemorySerializer : public btDefaultSerializer
{
btHashMap<btHashPtr,btChunk*> m_uid2ChunkPtr;
btHashMap<btHashPtr,void*> m_orgPtr2UniqueDataPtr;
btHashMap<btHashString,const void*> m_names2Ptr;
btBulletSerializedArrays m_arrays;
btInMemorySerializer(int totalSize=0, unsigned char* buffer=0)
:btDefaultSerializer(totalSize,buffer)
{
}
virtual void startSerialization()
{
m_uid2ChunkPtr.clear();
//todo: m_arrays.clear();
btDefaultSerializer::startSerialization();
}
btChunk* findChunkFromUniquePointer(void* uniquePointer)
{
btChunk** chkPtr = m_uid2ChunkPtr[uniquePointer];
if (chkPtr)
{
return *chkPtr;
}
return 0;
}
virtual void registerNameForPointer(const void* ptr, const char* name)
{
btDefaultSerializer::registerNameForPointer(ptr,name);
m_names2Ptr.insert(name,ptr);
}
virtual void finishSerialization()
{
}
virtual void* getUniquePointer(void*oldPtr)
{
if (oldPtr==0)
return 0;
// void* uniquePtr = getUniquePointer(oldPtr);
btChunk* chunk = findChunkFromUniquePointer(oldPtr);
if (chunk)
{
return chunk->m_oldPtr;
} else
{
const char* n = (const char*) oldPtr;
const void** ptr = m_names2Ptr[n];
if (ptr)
{
return oldPtr;
} else
{
void** ptr2 = m_skipPointers[oldPtr];
if (ptr2)
{
return 0;
} else
{
//If this assert hit, serialization happened in the wrong order
// 'getUniquePointer'
btAssert(0);
}
}
return 0;
}
return oldPtr;
}
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,oldPtr);//chunk->m_oldPtr);
// chunk->m_oldPtr = uniquePtr;//oldPtr;
void* uid = findPointer(oldPtr);
m_uid2ChunkPtr.insert(uid,chunk);
switch (chunk->m_chunkCode)
{
case BT_SOFTBODY_CODE:
{
#ifdef BT_USE_DOUBLE_PRECISION
m_arrays.m_softBodyDoubleData.push_back((btSoftBodyDoubleData*) chunk->m_oldPtr);
#else
m_arrays.m_softBodyFloatData.push_back((btSoftBodyFloatData*) chunk->m_oldPtr);
#endif
break;
}
case BT_COLLISIONOBJECT_CODE:
{
#ifdef BT_USE_DOUBLE_PRECISION
m_arrays.m_collisionObjectDataDouble.push_back((btCollisionObjectDoubleData*)chunk->m_oldPtr);
#else//BT_USE_DOUBLE_PRECISION
m_arrays.m_collisionObjectDataFloat.push_back((btCollisionObjectFloatData*)chunk->m_oldPtr);
#endif //BT_USE_DOUBLE_PRECISION
break;
}
case BT_RIGIDBODY_CODE:
{
#ifdef BT_USE_DOUBLE_PRECISION
m_arrays.m_rigidBodyDataDouble.push_back((btRigidBodyDoubleData*)chunk->m_oldPtr);
#else
m_arrays.m_rigidBodyDataFloat.push_back((btRigidBodyFloatData*)chunk->m_oldPtr);
#endif//BT_USE_DOUBLE_PRECISION
break;
};
case BT_CONSTRAINT_CODE:
{
#ifdef BT_USE_DOUBLE_PRECISION
m_arrays.m_constraintDataDouble.push_back((btTypedConstraintDoubleData*)chunk->m_oldPtr);
#else
m_arrays.m_constraintDataFloat.push_back((btTypedConstraintFloatData*)chunk->m_oldPtr);
#endif
break;
}
case BT_QUANTIZED_BVH_CODE:
{
#ifdef BT_USE_DOUBLE_PRECISION
m_arrays.m_bvhsDouble.push_back((btQuantizedBvhDoubleData*) chunk->m_oldPtr);
#else
m_arrays.m_bvhsFloat.push_back((btQuantizedBvhFloatData*) chunk->m_oldPtr);
#endif
break;
}
case BT_SHAPE_CODE:
{
btCollisionShapeData* shapeData = (btCollisionShapeData*) chunk->m_oldPtr;
m_arrays.m_colShapeData.push_back(shapeData);
break;
}
case BT_TRIANLGE_INFO_MAP:
case BT_ARRAY_CODE:
case BT_SBMATERIAL_CODE:
case BT_SBNODE_CODE:
case BT_DYNAMICSWORLD_CODE:
case BT_DNA_CODE:
{
break;
}
default:
{
}
};
}
int getNumChunks() const
{
return m_uid2ChunkPtr.size();
}
const btChunk* getChunk(int chunkIndex) const
{
return *m_uid2ChunkPtr.getAtIndex(chunkIndex);
}
};
#endif //ENABLE_INMEMORY_SERIALIZER
#endif //BT_SERIALIZER_H

View file

@ -0,0 +1,331 @@
/*
Copyright (c) 2003-2015 Erwin Coumans, Jakub Stepien
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.
*/
///These spatial algebra classes are used for btMultiBody,
///see BulletDynamics/Featherstone
#ifndef BT_SPATIAL_ALGEBRA_H
#define BT_SPATIAL_ALGEBRA_H
#include "btMatrix3x3.h"
struct btSpatialForceVector
{
btVector3 m_topVec, m_bottomVec;
//
btSpatialForceVector() { setZero(); }
btSpatialForceVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(linear), m_bottomVec(angular) {}
btSpatialForceVector(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
{
setValue(ax, ay, az, lx, ly, lz);
}
//
void setVector(const btVector3 &angular, const btVector3 &linear) { m_topVec = linear; m_bottomVec = angular; }
void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
{
m_bottomVec.setValue(ax, ay, az); m_topVec.setValue(lx, ly, lz);
}
//
void addVector(const btVector3 &angular, const btVector3 &linear) { m_topVec += linear; m_bottomVec += angular; }
void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
{
m_bottomVec[0] += ax; m_bottomVec[1] += ay; m_bottomVec[2] += az;
m_topVec[0] += lx; m_topVec[1] += ly; m_topVec[2] += lz;
}
//
const btVector3 & getLinear() const { return m_topVec; }
const btVector3 & getAngular() const { return m_bottomVec; }
//
void setLinear(const btVector3 &linear) { m_topVec = linear; }
void setAngular(const btVector3 &angular) { m_bottomVec = angular; }
//
void addAngular(const btVector3 &angular) { m_bottomVec += angular; }
void addLinear(const btVector3 &linear) { m_topVec += linear; }
//
void setZero() { m_topVec.setZero(); m_bottomVec.setZero(); }
//
btSpatialForceVector & operator += (const btSpatialForceVector &vec) { m_topVec += vec.m_topVec; m_bottomVec += vec.m_bottomVec; return *this; }
btSpatialForceVector & operator -= (const btSpatialForceVector &vec) { m_topVec -= vec.m_topVec; m_bottomVec -= vec.m_bottomVec; return *this; }
btSpatialForceVector operator - (const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec - vec.m_bottomVec, m_topVec - vec.m_topVec); }
btSpatialForceVector operator + (const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec + vec.m_bottomVec, m_topVec + vec.m_topVec); }
btSpatialForceVector operator - () const { return btSpatialForceVector(-m_bottomVec, -m_topVec); }
btSpatialForceVector operator * (const btScalar &s) const { return btSpatialForceVector(s * m_bottomVec, s * m_topVec); }
//btSpatialForceVector & operator = (const btSpatialForceVector &vec) { m_topVec = vec.m_topVec; m_bottomVec = vec.m_bottomVec; return *this; }
};
struct btSpatialMotionVector
{
btVector3 m_topVec, m_bottomVec;
//
btSpatialMotionVector() { setZero(); }
btSpatialMotionVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(angular), m_bottomVec(linear) {}
//
void setVector(const btVector3 &angular, const btVector3 &linear) { m_topVec = angular; m_bottomVec = linear; }
void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
{
m_topVec.setValue(ax, ay, az); m_bottomVec.setValue(lx, ly, lz);
}
//
void addVector(const btVector3 &angular, const btVector3 &linear) { m_topVec += linear; m_bottomVec += angular; }
void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
{
m_topVec[0] += ax; m_topVec[1] += ay; m_topVec[2] += az;
m_bottomVec[0] += lx; m_bottomVec[1] += ly; m_bottomVec[2] += lz;
}
//
const btVector3 & getAngular() const { return m_topVec; }
const btVector3 & getLinear() const { return m_bottomVec; }
//
void setAngular(const btVector3 &angular) { m_topVec = angular; }
void setLinear(const btVector3 &linear) { m_bottomVec = linear; }
//
void addAngular(const btVector3 &angular) { m_topVec += angular; }
void addLinear(const btVector3 &linear) { m_bottomVec += linear; }
//
void setZero() { m_topVec.setZero(); m_bottomVec.setZero(); }
//
btScalar dot(const btSpatialForceVector &b) const
{
return m_bottomVec.dot(b.m_topVec) + m_topVec.dot(b.m_bottomVec);
}
//
template<typename SpatialVectorType>
void cross(const SpatialVectorType &b, SpatialVectorType &out) const
{
out.m_topVec = m_topVec.cross(b.m_topVec);
out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
}
template<typename SpatialVectorType>
SpatialVectorType cross(const SpatialVectorType &b) const
{
SpatialVectorType out;
out.m_topVec = m_topVec.cross(b.m_topVec);
out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
return out;
}
//
btSpatialMotionVector & operator += (const btSpatialMotionVector &vec) { m_topVec += vec.m_topVec; m_bottomVec += vec.m_bottomVec; return *this; }
btSpatialMotionVector & operator -= (const btSpatialMotionVector &vec) { m_topVec -= vec.m_topVec; m_bottomVec -= vec.m_bottomVec; return *this; }
btSpatialMotionVector & operator *= (const btScalar &s) { m_topVec *= s; m_bottomVec *= s; return *this; }
btSpatialMotionVector operator - (const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec - vec.m_topVec, m_bottomVec - vec.m_bottomVec); }
btSpatialMotionVector operator + (const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec + vec.m_topVec, m_bottomVec + vec.m_bottomVec); }
btSpatialMotionVector operator - () const { return btSpatialMotionVector(-m_topVec, -m_bottomVec); }
btSpatialMotionVector operator * (const btScalar &s) const { return btSpatialMotionVector(s * m_topVec, s * m_bottomVec); }
};
struct btSymmetricSpatialDyad
{
btMatrix3x3 m_topLeftMat, m_topRightMat, m_bottomLeftMat;
//
btSymmetricSpatialDyad() { setIdentity(); }
btSymmetricSpatialDyad(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat) { setMatrix(topLeftMat, topRightMat, bottomLeftMat); }
//
void setMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
{
m_topLeftMat = topLeftMat;
m_topRightMat = topRightMat;
m_bottomLeftMat = bottomLeftMat;
}
//
void addMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
{
m_topLeftMat += topLeftMat;
m_topRightMat += topRightMat;
m_bottomLeftMat += bottomLeftMat;
}
//
void setIdentity() { m_topLeftMat.setIdentity(); m_topRightMat.setIdentity(); m_bottomLeftMat.setIdentity(); }
//
btSymmetricSpatialDyad & operator -= (const btSymmetricSpatialDyad &mat)
{
m_topLeftMat -= mat.m_topLeftMat;
m_topRightMat -= mat.m_topRightMat;
m_bottomLeftMat -= mat.m_bottomLeftMat;
return *this;
}
//
btSpatialForceVector operator * (const btSpatialMotionVector &vec)
{
return btSpatialForceVector(m_bottomLeftMat * vec.m_topVec + m_topLeftMat.transpose() * vec.m_bottomVec, m_topLeftMat * vec.m_topVec + m_topRightMat * vec.m_bottomVec);
}
};
struct btSpatialTransformationMatrix
{
btMatrix3x3 m_rotMat; //btMatrix3x3 m_trnCrossMat;
btVector3 m_trnVec;
//
enum eOutputOperation
{
None = 0,
Add = 1,
Subtract = 2
};
//
template<typename SpatialVectorType>
void transform( const SpatialVectorType &inVec,
SpatialVectorType &outVec,
eOutputOperation outOp = None)
{
if(outOp == None)
{
outVec.m_topVec = m_rotMat * inVec.m_topVec;
outVec.m_bottomVec = -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
}
else if(outOp == Add)
{
outVec.m_topVec += m_rotMat * inVec.m_topVec;
outVec.m_bottomVec += -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
}
else if(outOp == Subtract)
{
outVec.m_topVec -= m_rotMat * inVec.m_topVec;
outVec.m_bottomVec -= -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
}
}
template<typename SpatialVectorType>
void transformRotationOnly( const SpatialVectorType &inVec,
SpatialVectorType &outVec,
eOutputOperation outOp = None)
{
if(outOp == None)
{
outVec.m_topVec = m_rotMat * inVec.m_topVec;
outVec.m_bottomVec = m_rotMat * inVec.m_bottomVec;
}
else if(outOp == Add)
{
outVec.m_topVec += m_rotMat * inVec.m_topVec;
outVec.m_bottomVec += m_rotMat * inVec.m_bottomVec;
}
else if(outOp == Subtract)
{
outVec.m_topVec -= m_rotMat * inVec.m_topVec;
outVec.m_bottomVec -= m_rotMat * inVec.m_bottomVec;
}
}
template<typename SpatialVectorType>
void transformInverse( const SpatialVectorType &inVec,
SpatialVectorType &outVec,
eOutputOperation outOp = None)
{
if(outOp == None)
{
outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
outVec.m_bottomVec = m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
}
else if(outOp == Add)
{
outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
outVec.m_bottomVec += m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
}
else if(outOp == Subtract)
{
outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
outVec.m_bottomVec -= m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
}
}
template<typename SpatialVectorType>
void transformInverseRotationOnly( const SpatialVectorType &inVec,
SpatialVectorType &outVec,
eOutputOperation outOp = None)
{
if(outOp == None)
{
outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
outVec.m_bottomVec = m_rotMat.transpose() * inVec.m_bottomVec;
}
else if(outOp == Add)
{
outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
outVec.m_bottomVec += m_rotMat.transpose() * inVec.m_bottomVec;
}
else if(outOp == Subtract)
{
outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
outVec.m_bottomVec -= m_rotMat.transpose() * inVec.m_bottomVec;
}
}
void transformInverse( const btSymmetricSpatialDyad &inMat,
btSymmetricSpatialDyad &outMat,
eOutputOperation outOp = None)
{
const btMatrix3x3 r_cross( 0, -m_trnVec[2], m_trnVec[1],
m_trnVec[2], 0, -m_trnVec[0],
-m_trnVec[1], m_trnVec[0], 0);
if(outOp == None)
{
outMat.m_topLeftMat = m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
outMat.m_topRightMat = m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
outMat.m_bottomLeftMat = m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
}
else if(outOp == Add)
{
outMat.m_topLeftMat += m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
outMat.m_topRightMat += m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
outMat.m_bottomLeftMat += m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
}
else if(outOp == Subtract)
{
outMat.m_topLeftMat -= m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
outMat.m_topRightMat -= m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
outMat.m_bottomLeftMat -= m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
}
}
template<typename SpatialVectorType>
SpatialVectorType operator * (const SpatialVectorType &vec)
{
SpatialVectorType out;
transform(vec, out);
return out;
}
};
template<typename SpatialVectorType>
void symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b, btSymmetricSpatialDyad &out)
{
//output op maybe?
out.m_topLeftMat = outerProduct(a.m_topVec, b.m_bottomVec);
out.m_topRightMat = outerProduct(a.m_topVec, b.m_topVec);
out.m_topLeftMat = outerProduct(a.m_bottomVec, b.m_bottomVec);
//maybe simple a*spatTranspose(a) would be nicer?
}
template<typename SpatialVectorType>
btSymmetricSpatialDyad symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b)
{
btSymmetricSpatialDyad out;
out.m_topLeftMat = outerProduct(a.m_topVec, b.m_bottomVec);
out.m_topRightMat = outerProduct(a.m_topVec, b.m_topVec);
out.m_bottomLeftMat = outerProduct(a.m_bottomVec, b.m_bottomVec);
return out;
//maybe simple a*spatTranspose(a) would be nicer?
}
#endif //BT_SPATIAL_ALGEBRA_H

View file

@ -0,0 +1,230 @@
/*
Copyright (c) 2003-2014 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.
*/
#include "btThreads.h"
//
// Lightweight spin-mutex based on atomics
// Using ordinary system-provided mutexes like Windows critical sections was noticeably slower
// presumably because when it fails to lock at first it would sleep the thread and trigger costly
// context switching.
//
#if BT_THREADSAFE
#if __cplusplus >= 201103L
// for anything claiming full C++11 compliance, use C++11 atomics
// on GCC or Clang you need to compile with -std=c++11
#define USE_CPP11_ATOMICS 1
#elif defined( _MSC_VER )
// on MSVC, use intrinsics instead
#define USE_MSVC_INTRINSICS 1
#elif defined( __GNUC__ ) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
// available since GCC 4.7 and some versions of clang
// todo: check for clang
#define USE_GCC_BUILTIN_ATOMICS 1
#elif defined( __GNUC__ ) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
// available since GCC 4.1
#define USE_GCC_BUILTIN_ATOMICS_OLD 1
#endif
#if USE_CPP11_ATOMICS
#include <atomic>
#include <thread>
#define THREAD_LOCAL_STATIC thread_local static
bool btSpinMutex::tryLock()
{
std::atomic<int>* aDest = reinterpret_cast<std::atomic<int>*>(&mLock);
int expected = 0;
return std::atomic_compare_exchange_weak_explicit( aDest, &expected, int(1), std::memory_order_acq_rel, std::memory_order_acquire );
}
void btSpinMutex::lock()
{
// note: this lock does not sleep the thread.
while (! tryLock())
{
// spin
}
}
void btSpinMutex::unlock()
{
std::atomic<int>* aDest = reinterpret_cast<std::atomic<int>*>(&mLock);
std::atomic_store_explicit( aDest, int(0), std::memory_order_release );
}
#elif USE_MSVC_INTRINSICS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <intrin.h>
#define THREAD_LOCAL_STATIC __declspec( thread ) static
bool btSpinMutex::tryLock()
{
volatile long* aDest = reinterpret_cast<long*>(&mLock);
return ( 0 == _InterlockedCompareExchange( aDest, 1, 0) );
}
void btSpinMutex::lock()
{
// note: this lock does not sleep the thread
while (! tryLock())
{
// spin
}
}
void btSpinMutex::unlock()
{
volatile long* aDest = reinterpret_cast<long*>( &mLock );
_InterlockedExchange( aDest, 0 );
}
#elif USE_GCC_BUILTIN_ATOMICS
#define THREAD_LOCAL_STATIC static __thread
bool btSpinMutex::tryLock()
{
int expected = 0;
bool weak = false;
const int memOrderSuccess = __ATOMIC_ACQ_REL;
const int memOrderFail = __ATOMIC_ACQUIRE;
return __atomic_compare_exchange_n(&mLock, &expected, int(1), weak, memOrderSuccess, memOrderFail);
}
void btSpinMutex::lock()
{
// note: this lock does not sleep the thread
while (! tryLock())
{
// spin
}
}
void btSpinMutex::unlock()
{
__atomic_store_n(&mLock, int(0), __ATOMIC_RELEASE);
}
#elif USE_GCC_BUILTIN_ATOMICS_OLD
#define THREAD_LOCAL_STATIC static __thread
bool btSpinMutex::tryLock()
{
return __sync_bool_compare_and_swap(&mLock, int(0), int(1));
}
void btSpinMutex::lock()
{
// note: this lock does not sleep the thread
while (! tryLock())
{
// spin
}
}
void btSpinMutex::unlock()
{
// write 0
__sync_fetch_and_and(&mLock, int(0));
}
#else //#elif USE_MSVC_INTRINSICS
#error "no threading primitives defined -- unknown platform"
#endif //#else //#elif USE_MSVC_INTRINSICS
struct ThreadsafeCounter
{
unsigned int mCounter;
btSpinMutex mMutex;
ThreadsafeCounter() {mCounter=0;}
unsigned int getNext()
{
// no need to optimize this with atomics, it is only called ONCE per thread!
mMutex.lock();
unsigned int val = mCounter++;
mMutex.unlock();
return val;
}
};
static ThreadsafeCounter gThreadCounter;
// return a unique index per thread, starting with 0 and counting up
unsigned int btGetCurrentThreadIndex()
{
const unsigned int kNullIndex = ~0U;
THREAD_LOCAL_STATIC unsigned int sThreadIndex = kNullIndex;
if ( sThreadIndex == kNullIndex )
{
sThreadIndex = gThreadCounter.getNext();
}
return sThreadIndex;
}
bool btIsMainThread()
{
return btGetCurrentThreadIndex() == 0;
}
#else // #if BT_THREADSAFE
// These should not be called ever
void btSpinMutex::lock()
{
btAssert(!"unimplemented btSpinMutex::lock() called");
}
void btSpinMutex::unlock()
{
btAssert(!"unimplemented btSpinMutex::unlock() called");
}
bool btSpinMutex::tryLock()
{
btAssert(!"unimplemented btSpinMutex::tryLock() called");
return true;
}
#endif // #else // #if BT_THREADSAFE

View file

@ -0,0 +1,76 @@
/*
Copyright (c) 2003-2014 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 BT_THREADS_H
#define BT_THREADS_H
#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
///
/// btSpinMutex -- lightweight spin-mutex implemented with atomic ops, never puts
/// a thread to sleep because it is designed to be used with a task scheduler
/// which has one thread per core and the threads don't sleep until they
/// run out of tasks. Not good for general purpose use.
///
class btSpinMutex
{
int mLock;
public:
btSpinMutex()
{
mLock = 0;
}
void lock();
void unlock();
bool tryLock();
};
#if BT_THREADSAFE
// for internal Bullet use only
SIMD_FORCE_INLINE void btMutexLock( btSpinMutex* mutex )
{
mutex->lock();
}
SIMD_FORCE_INLINE void btMutexUnlock( btSpinMutex* mutex )
{
mutex->unlock();
}
SIMD_FORCE_INLINE bool btMutexTryLock( btSpinMutex* mutex )
{
return mutex->tryLock();
}
// for internal use only
bool btIsMainThread();
unsigned int btGetCurrentThreadIndex();
const unsigned int BT_MAX_THREAD_COUNT = 64;
#else
// for internal Bullet use only
// if BT_THREADSAFE is undefined or 0, should optimize away to nothing
SIMD_FORCE_INLINE void btMutexLock( btSpinMutex* ) {}
SIMD_FORCE_INLINE void btMutexUnlock( btSpinMutex* ) {}
SIMD_FORCE_INLINE bool btMutexTryLock( btSpinMutex* ) {return true;}
#endif
#endif //BT_THREADS_H

View file

@ -127,7 +127,7 @@ public:
/**@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 */
* @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */
void setFromOpenGLMatrix(const btScalar *m)
{
m_basis.setFromOpenGLSubMatrix(m);
@ -135,7 +135,7 @@ public:
}
/**@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 */
* @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */
void getOpenGLMatrix(btScalar *m) const
{
m_basis.getOpenGLSubMatrix(m);

View file

@ -63,7 +63,7 @@ long _maxdot_large( const float *vv, const float *vec, unsigned long count, floa
float4 stack_array[ STACK_ARRAY_COUNT ];
#if DEBUG
memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
//memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
#endif
size_t index;
@ -448,7 +448,7 @@ long _mindot_large( const float *vv, const float *vec, unsigned long count, floa
float4 stack_array[ STACK_ARRAY_COUNT ];
#if DEBUG
memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
//memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
#endif
size_t index;
@ -821,6 +821,7 @@ long _mindot_large( const float *vv, const float *vec, unsigned long count, floa
#elif defined BT_USE_NEON
#define ARM_NEON_GCC_COMPATIBILITY 1
#include <arm_neon.h>
#include <sys/types.h>
@ -884,7 +885,12 @@ static long _mindot_large_sel( const float *vv, const float *vec, unsigned long
#define vld1q_f32_aligned_postincrement( _ptr ) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
#if defined __arm__
# define vld1q_f32_aligned_postincrement( _ptr ) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
#else
//support 64bit arm
# define vld1q_f32_aligned_postincrement( _ptr) ({ float32x4_t _r = ((float32x4_t*)(_ptr))[0]; (_ptr) = (const float*) ((const char*)(_ptr) + 16L); /*return*/ _r; })
#endif
long _maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult )

View file

@ -267,10 +267,20 @@ public:
/**@brief Return the norm (length) of the vector */
SIMD_FORCE_INLINE btScalar norm() const
{
{
return length();
}
/**@brief Return the norm (length) of the vector */
SIMD_FORCE_INLINE btScalar safeNorm() const
{
btScalar d = length2();
//workaround for some clang/gcc issue of sqrtf(tiny number) = -INF
if (d>SIMD_EPSILON)
return btSqrt(d);
return btScalar(0);
}
/**@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;
@ -297,7 +307,7 @@ public:
SIMD_FORCE_INLINE btVector3& normalize()
{
btAssert(length() != btScalar(0));
btAssert(!fuzzyZero());
#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
// dot product first
@ -501,10 +511,10 @@ public:
__m128 tmp3 = _mm_add_ps(r0,r1);
mVec128 = tmp3;
#elif defined(BT_USE_NEON)
mVec128 = vsubq_f32(v1.mVec128, v0.mVec128);
mVec128 = vmulq_n_f32(mVec128, rt);
mVec128 = vaddq_f32(mVec128, v0.mVec128);
#else
float32x4_t vl = vsubq_f32(v1.mVec128, v0.mVec128);
vl = vmulq_n_f32(vl, rt);
mVec128 = vaddq_f32(vl, v0.mVec128);
#else
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];
@ -685,9 +695,10 @@ public:
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;
return length2() < SIMD_EPSILON*SIMD_EPSILON;
}
SIMD_FORCE_INLINE void serialize(struct btVector3Data& dataOut) const;
@ -950,9 +961,9 @@ SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const
SIMD_FORCE_INLINE btVector3 btVector3::normalized() const
{
btVector3 norm = *this;
btVector3 nrm = *this;
return norm.normalize();
return nrm.normalize();
}
SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar _angle ) const
@ -1010,21 +1021,21 @@ SIMD_FORCE_INLINE long btVector3::maxDot( const btVector3 *array, long arra
if( array_count < scalar_cutoff )
#endif
{
btScalar maxDot = -SIMD_INFINITY;
btScalar maxDot1 = -SIMD_INFINITY;
int i = 0;
int ptIndex = -1;
for( i = 0; i < array_count; i++ )
{
btScalar dot = array[i].dot(*this);
if( dot > maxDot )
if( dot > maxDot1 )
{
maxDot = dot;
maxDot1 = dot;
ptIndex = i;
}
}
dotOut = maxDot;
dotOut = maxDot1;
return ptIndex;
}
#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)

View file

@ -1,11 +1,10 @@
project "LinearMath"
kind "StaticLib"
targetdir "../../lib"
includedirs {
"..",
}
files {
"**.cpp",
"**.h"
}
"*.cpp",
"*.h"
}