mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-15 00:24:40 +00:00
Bullet 2.85 update
This commit is contained in:
parent
38bf2b8175
commit
540c9b72c0
391 changed files with 32183 additions and 58559 deletions
|
|
@ -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})
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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__)
|
||||
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
92
Engine/lib/bullet/src/LinearMath/btCpuFeatureUtility.h
Normal file
92
Engine/lib/bullet/src/LinearMath/btCpuFeatureUtility.h
Normal 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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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] &&
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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(¤tTime);
|
||||
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(¤tTime, 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(¤tTime);
|
||||
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(¤tTime, 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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
|||
331
Engine/lib/bullet/src/LinearMath/btSpatialAlgebra.h
Normal file
331
Engine/lib/bullet/src/LinearMath/btSpatialAlgebra.h
Normal 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
|
||||
|
||||
230
Engine/lib/bullet/src/LinearMath/btThreads.cpp
Normal file
230
Engine/lib/bullet/src/LinearMath/btThreads.cpp
Normal 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
|
||||
|
||||
76
Engine/lib/bullet/src/LinearMath/btThreads.h
Normal file
76
Engine/lib/bullet/src/LinearMath/btThreads.h
Normal 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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 )
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
project "LinearMath"
|
||||
|
||||
|
||||
kind "StaticLib"
|
||||
targetdir "../../lib"
|
||||
includedirs {
|
||||
"..",
|
||||
}
|
||||
files {
|
||||
"**.cpp",
|
||||
"**.h"
|
||||
}
|
||||
"*.cpp",
|
||||
"*.h"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue