From ba0dd676aa7e1f57cdec1c02d653e9eb58b9325e Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Sun, 2 Nov 2014 14:12:54 -0800 Subject: [PATCH 1/2] comment-out the memset in DEBUG mode in btVector3.cpp and b3Vector3.cpp --- src/Bullet3Common/b3Vector3.cpp | 488 ++++++++++++++++---------------- src/LinearMath/btVector3.cpp | 4 +- 2 files changed, 246 insertions(+), 246 deletions(-) diff --git a/src/Bullet3Common/b3Vector3.cpp b/src/Bullet3Common/b3Vector3.cpp index e43f13897..5f5ac4ac0 100644 --- a/src/Bullet3Common/b3Vector3.cpp +++ b/src/Bullet3Common/b3Vector3.cpp @@ -1,16 +1,16 @@ /* Copyright (c) 2011-213 Apple Inc. 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. 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. - + This source version has been altered. */ @@ -47,35 +47,35 @@ long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, fl float4 vvec = _mm_loadu_ps( vec ); float4 vHi = b3CastiTo128f(_mm_shuffle_epi32( b3CastfTo128i( vvec), 0xaa )); /// zzzz float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy - + long maxIndex = -1L; - + size_t segment = 0; 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; float4 max; // Faster loop without cleanup code for full tiles - for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 ) + for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 ) { max = dotMax; - - for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 ) + + for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 ) { // do four dot products at a time. Carefully avoid touching the w element. float4 v0 = vertices[0]; float4 v1 = vertices[1]; float4 v2 = vertices[2]; float4 v3 = vertices[3]; vertices += 4; - + float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 - + lo0 = lo0*vLo; lo1 = lo1*vLo; float4 z = _mm_shuffle_ps(hi0, hi1, 0x88); @@ -86,17 +86,17 @@ long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, fl x = x+z; stack_array[index] = x; max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan - + v0 = vertices[0]; v1 = vertices[1]; v2 = vertices[2]; v3 = vertices[3]; vertices += 4; - + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 - + lo0 = lo0*vLo; lo1 = lo1*vLo; z = _mm_shuffle_ps(hi0, hi1, 0x88); @@ -107,17 +107,17 @@ long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, fl x = x+z; stack_array[index+1] = x; max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan - + v0 = vertices[0]; v1 = vertices[1]; v2 = vertices[2]; v3 = vertices[3]; vertices += 4; - + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 - + lo0 = lo0*vLo; lo1 = lo1*vLo; z = _mm_shuffle_ps(hi0, hi1, 0x88); @@ -128,17 +128,17 @@ long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, fl x = x+z; stack_array[index+2] = x; max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan - + v0 = vertices[0]; v1 = vertices[1]; v2 = vertices[2]; v3 = vertices[3]; vertices += 4; - + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 - + lo0 = lo0*vLo; lo1 = lo1*vLo; z = _mm_shuffle_ps(hi0, hi1, 0x88); @@ -149,20 +149,20 @@ long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, fl x = x+z; stack_array[index+3] = x; max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan - + // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way. } - + // If we found a new max if( 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(max, dotMax))) - { + { // copy the new max across all lanes of our max accumulator max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0x4e)); max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0xb1)); - + dotMax = max; - - // find first occurrence of that max + + // find first occurrence of that max size_t test; for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], max))); index++ ) // local_count must be a multiple of 4 {} @@ -170,29 +170,29 @@ long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, fl maxIndex = 4*index + segment + indexTable[test]; } } - + // account for work we've already done count -= segment; - + // Deal with the last < STACK_ARRAY_COUNT vectors max = dotMax; index = 0; - - + + if( b3Unlikely( count > 16) ) { - for( ; index + 4 <= count / 4; index+=4 ) + for( ; index + 4 <= count / 4; index+=4 ) { // do four dot products at a time. Carefully avoid touching the w element. float4 v0 = vertices[0]; float4 v1 = vertices[1]; float4 v2 = vertices[2]; float4 v3 = vertices[3]; vertices += 4; - + float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 - + lo0 = lo0*vLo; lo1 = lo1*vLo; float4 z = _mm_shuffle_ps(hi0, hi1, 0x88); @@ -203,17 +203,17 @@ long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, fl x = x+z; stack_array[index] = x; max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan - + v0 = vertices[0]; v1 = vertices[1]; v2 = vertices[2]; v3 = vertices[3]; vertices += 4; - + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 - + lo0 = lo0*vLo; lo1 = lo1*vLo; z = _mm_shuffle_ps(hi0, hi1, 0x88); @@ -224,17 +224,17 @@ long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, fl x = x+z; stack_array[index+1] = x; max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan - + v0 = vertices[0]; v1 = vertices[1]; v2 = vertices[2]; v3 = vertices[3]; vertices += 4; - + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 - + lo0 = lo0*vLo; lo1 = lo1*vLo; z = _mm_shuffle_ps(hi0, hi1, 0x88); @@ -245,17 +245,17 @@ long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, fl x = x+z; stack_array[index+2] = x; max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan - + v0 = vertices[0]; v1 = vertices[1]; v2 = vertices[2]; v3 = vertices[3]; vertices += 4; - + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 - + lo0 = lo0*vLo; lo1 = lo1*vLo; z = _mm_shuffle_ps(hi0, hi1, 0x88); @@ -266,11 +266,11 @@ long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, fl x = x+z; stack_array[index+3] = x; max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan - + // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way. } } - + size_t localCount = (count & -4L) - 4*index; if( localCount ) { @@ -314,19 +314,19 @@ long b3_maxdot_large( const float *vv, const float *vec, unsigned long count, fl index += localCount/4; #else { - for( unsigned int i=0; i 16) ) { - for( ; index + 4 <= count / 4; index+=4 ) + for( ; index + 4 <= count / 4; index+=4 ) { // do four dot products at a time. Carefully avoid touching the w element. float4 v0 = vertices[0]; float4 v1 = vertices[1]; float4 v2 = vertices[2]; float4 v3 = vertices[3]; vertices += 4; - + float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 - + lo0 = lo0*vLo; lo1 = lo1*vLo; float4 z = _mm_shuffle_ps(hi0, hi1, 0x88); @@ -589,17 +589,17 @@ long b3_mindot_large( const float *vv, const float *vec, unsigned long count, fl x = x+z; stack_array[index] = x; min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan - + v0 = vertices[0]; v1 = vertices[1]; v2 = vertices[2]; v3 = vertices[3]; vertices += 4; - + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 - + lo0 = lo0*vLo; lo1 = lo1*vLo; z = _mm_shuffle_ps(hi0, hi1, 0x88); @@ -610,17 +610,17 @@ long b3_mindot_large( const float *vv, const float *vec, unsigned long count, fl x = x+z; stack_array[index+1] = x; min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan - + v0 = vertices[0]; v1 = vertices[1]; v2 = vertices[2]; v3 = vertices[3]; vertices += 4; - + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 - + lo0 = lo0*vLo; lo1 = lo1*vLo; z = _mm_shuffle_ps(hi0, hi1, 0x88); @@ -631,17 +631,17 @@ long b3_mindot_large( const float *vv, const float *vec, unsigned long count, fl x = x+z; stack_array[index+2] = x; min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan - + v0 = vertices[0]; v1 = vertices[1]; v2 = vertices[2]; v3 = vertices[3]; vertices += 4; - + lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3 - + lo0 = lo0*vLo; lo1 = lo1*vLo; z = _mm_shuffle_ps(hi0, hi1, 0x88); @@ -652,22 +652,22 @@ long b3_mindot_large( const float *vv, const float *vec, unsigned long count, fl x = x+z; stack_array[index+3] = x; min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan - + // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way. } } - + size_t localCount = (count & -4L) - 4*index; if( localCount ) { - - + + #ifdef __APPLE__ vertices += localCount; // counter the offset float4 t0, t1, t2, t3, t4; size_t byteIndex = -(localCount) * sizeof(float); float4 * sap = &stack_array[index + localCount / 4]; - + asm volatile ( ".align 4 \n\ 0: movaps %[min], %[t2] // move min out of the way to avoid propagating NaNs in min \n\ @@ -702,19 +702,19 @@ long b3_mindot_large( const float *vv, const float *vec, unsigned long count, fl index += localCount/4; #else { - for( unsigned int i=0; i Date: Wed, 5 Nov 2014 08:58:24 -0800 Subject: [PATCH 2/2] fix MSVC 2013 compilation (std::min needs #include add example use of GJK+MPR in VoronoiFractureDemo --- Demos/VoronoiFractureDemo/CMakeLists.txt | 6 + .../VoronoiFractureDemo.cpp | 47 ++- .../VoronoiFractureDemo/VoronoiFractureDemo.h | 2 + .../btConvexConvexMprAlgorithm.cpp | 288 ++++++++++++++++++ .../btConvexConvexMprAlgorithm.h | 87 ++++++ Demos/VoronoiFractureDemo/main.cpp | 2 +- .../dynamics/fem/fem_add_plasticity_force.h | 4 +- 7 files changed, 429 insertions(+), 7 deletions(-) create mode 100644 Demos/VoronoiFractureDemo/btConvexConvexMprAlgorithm.cpp create mode 100644 Demos/VoronoiFractureDemo/btConvexConvexMprAlgorithm.h diff --git a/Demos/VoronoiFractureDemo/CMakeLists.txt b/Demos/VoronoiFractureDemo/CMakeLists.txt index 8b1a10963..2abff4ece 100644 --- a/Demos/VoronoiFractureDemo/CMakeLists.txt +++ b/Demos/VoronoiFractureDemo/CMakeLists.txt @@ -29,6 +29,8 @@ ADD_EXECUTABLE(AppVoronoiFractureDemo main.cpp VoronoiFractureDemo.cpp VoronoiFractureDemo.h + btConvexConvexMprAlgorithm.cpp + btConvexConvexMprAlgorithm.h ${BULLET_PHYSICS_SOURCE_DIR}/build3/bullet.rc ) ELSE() @@ -36,6 +38,8 @@ ELSE() main.cpp VoronoiFractureDemo.cpp VoronoiFractureDemo.h + btConvexConvexMprAlgorithm.cpp + btConvexConvexMprAlgorithm.h ) ENDIF() @@ -57,6 +61,8 @@ ELSE (USE_GLUT) Win32VoronoiFractureDemo.cpp VoronoiFractureDemo.cpp VoronoiFractureDemo.h + btConvexConvexMprAlgorithm.cpp + btConvexConvexMprAlgorithm.h ${BULLET_PHYSICS_SOURCE_DIR}/build3/bullet.rc ) diff --git a/Demos/VoronoiFractureDemo/VoronoiFractureDemo.cpp b/Demos/VoronoiFractureDemo/VoronoiFractureDemo.cpp index d920a6dff..19cf7ddd2 100644 --- a/Demos/VoronoiFractureDemo/VoronoiFractureDemo.cpp +++ b/Demos/VoronoiFractureDemo/VoronoiFractureDemo.cpp @@ -25,20 +25,23 @@ Voronoi fracture and shatter code and demo copyright (c) 2011 Alain Ducharme //maximum number of objects (and allow user to shoot additional boxes) #define MAX_PROXIES (2048) -#define BREAKING_THRESHOLD 2 +#define BREAKING_THRESHOLD 3 #define CONVEX_MARGIN 0.04 +static int useMpr = 0; #include "VoronoiFractureDemo.h" #include "GlutStuff.h" ///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files. #include "btBulletDynamicsCommon.h" - +#include "GLDebugFont.h" #include //printf debugging #include "GLDebugDrawer.h" static GLDebugDrawer sDebugDraw; static bool useGenericConstraint = false; +#include "btConvexConvexMprAlgorithm.h" + void VoronoiFractureDemo::attachFixedConstraints() { @@ -493,13 +496,13 @@ void VoronoiFractureDemo::clientMoveAndDisplay() ///step the simulation if (m_dynamicsWorld) { - m_dynamicsWorld->stepSimulation(ms / 1000000.f); + m_dynamicsWorld->stepSimulation(1. / 60., 0);// ms / 1000000.f); //optional but useful: debug drawing m_dynamicsWorld->debugDrawWorld(); } renderme(); - + glFlush(); swapBuffers(); @@ -520,9 +523,30 @@ void VoronoiFractureDemo::displayCallback(void) { swapBuffers(); } +void VoronoiFractureDemo::renderme() +{ + DemoApplication::renderme(); + char buf[124]; + + int lineWidth = 200; + int xStart = m_glutScreenWidth - lineWidth; + + if (useMpr) + { + sprintf(buf, "Using GJK+MPR"); + } + else + { + sprintf(buf, "Using GJK+EPA"); + } + GLDebugDrawString(xStart, 20, buf); + +} + void VoronoiFractureDemo::initPhysics() { + srand(13); useGenericConstraint = !useGenericConstraint; printf("useGenericConstraint = %d\n", useGenericConstraint); @@ -538,7 +562,22 @@ void VoronoiFractureDemo::initPhysics() ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + useMpr = 1 - useMpr; + if (useMpr) + { + printf("using GJK+MPR convex-convex collision detection\n"); + btConvexConvexMprAlgorithm::CreateFunc* cf = new btConvexConvexMprAlgorithm::CreateFunc; + m_dispatcher->registerCollisionCreateFunc(CONVEX_HULL_SHAPE_PROXYTYPE, CONVEX_HULL_SHAPE_PROXYTYPE, cf); + m_dispatcher->registerCollisionCreateFunc(CONVEX_HULL_SHAPE_PROXYTYPE, BOX_SHAPE_PROXYTYPE, cf); + m_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE, CONVEX_HULL_SHAPE_PROXYTYPE, cf); + } + else + { + printf("using default (GJK+EPA) convex-convex collision detection\n"); + } + m_broadphase = new btDbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) diff --git a/Demos/VoronoiFractureDemo/VoronoiFractureDemo.h b/Demos/VoronoiFractureDemo/VoronoiFractureDemo.h index a21737426..3c36819be 100644 --- a/Demos/VoronoiFractureDemo/VoronoiFractureDemo.h +++ b/Demos/VoronoiFractureDemo/VoronoiFractureDemo.h @@ -68,6 +68,8 @@ class VoronoiFractureDemo : public PlatformDemoApplication void exitPhysics(); + virtual void renderme(); + void getVerticesInsidePlanes(const btAlignedObjectArray& planes, btAlignedObjectArray& verticesOut, std::set& planeIndicesOut); void voronoiBBShatter(const btAlignedObjectArray& points, const btVector3& bbmin, const btVector3& bbmax, const btQuaternion& bbq, const btVector3& bbt, btScalar matDensity); void voronoiConvexHullShatter(const btAlignedObjectArray& points, const btAlignedObjectArray& verts, const btQuaternion& bbq, const btVector3& bbt, btScalar matDensity); diff --git a/Demos/VoronoiFractureDemo/btConvexConvexMprAlgorithm.cpp b/Demos/VoronoiFractureDemo/btConvexConvexMprAlgorithm.cpp new file mode 100644 index 000000000..e14a0e67d --- /dev/null +++ b/Demos/VoronoiFractureDemo/btConvexConvexMprAlgorithm.cpp @@ -0,0 +1,288 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2014 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btConvexConvexMprAlgorithm.h" + +//#include +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +#include "BulletCollision/CollisionShapes/btTriangleShape.h" + + + +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" + +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" + + + +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" + +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h" +#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" + +#include "BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa3.h" +#include "BulletCollision/NarrowPhaseCollision/btMprPenetration.h" + +//this is just an internal debug variable to switch between GJK+MPR or GJK+EPA +bool gUseMprCollisionFunction = true; + +btConvexConvexMprAlgorithm::CreateFunc::CreateFunc() +{ + +} + +btConvexConvexMprAlgorithm::CreateFunc::~CreateFunc() +{ +} + +btConvexConvexMprAlgorithm::btConvexConvexMprAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) +: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap), +m_ownManifold (false), +m_manifoldPtr(mf) +{ + (void)body0Wrap; + (void)body1Wrap; +} + + + + +btConvexConvexMprAlgorithm::~btConvexConvexMprAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + + +btVector3 btBulletShapeSupportFunc(const void* shapeAptr, const btVector3& dir, bool includeMargin) +{ + btConvexShape* shape = (btConvexShape*) shapeAptr; + if (includeMargin) + { + return shape->localGetSupportingVertex(dir); + } + + return shape->localGetSupportingVertexWithoutMargin(dir); +} + +btVector3 btBulletShapeCenterFunc(const void* shapeAptr) +{ + return btVector3(0,0,0); +} + + +struct btMprConvexWrap +{ + const btConvexShape* m_convex; + btTransform m_worldTrans; + inline btScalar getMargin() const + { + return m_convex->getMargin(); + } + inline btVector3 getObjectCenterInWorld() const + { + return m_worldTrans.getOrigin(); + } + inline const btTransform& getWorldTransform() const + { + return m_worldTrans; + } + inline btVector3 getLocalSupportWithMargin(const btVector3& dir) const + { + return m_convex->localGetSupportingVertex(dir); + } + inline btVector3 getLocalSupportWithoutMargin(const btVector3& dir) const + { + return m_convex->localGetSupportingVertexWithoutMargin(dir); + } +}; + +struct btMyDistanceInfo +{ + btVector3 m_pointOnA; + btVector3 m_pointOnB; + btVector3 m_normalBtoA; + btScalar m_distance; +}; + +// +// Convex-Convex collision algorithm +// +void btConvexConvexMprAlgorithm ::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + if (!m_manifoldPtr) + { + //swapped? + m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()); + m_ownManifold = true; + } + resultOut->setPersistentManifold(m_manifoldPtr); + + //comment-out next line to test multi-contact generation + //resultOut->getPersistentManifold()->clearManifold(); + + + const btConvexShape* min0 = static_cast(body0Wrap->getCollisionShape()); + const btConvexShape* min1 = static_cast(body1Wrap->getCollisionShape()); + + btVector3 normalOnB; + btVector3 pointOnBWorld; + + btGjkPairDetector::ClosestPointInput input; + + btVoronoiSimplexSolver vs; + btGjkEpaPenetrationDepthSolver epa; + + + if (gUseMprCollisionFunction) + { + + btMprConvexWrap a,b; + a.m_worldTrans = body0Wrap->getWorldTransform(); + b.m_worldTrans = body1Wrap->getWorldTransform(); + a.m_convex = (const btConvexShape*)body0Wrap->getCollisionShape(); + b.m_convex = (const btConvexShape*)body1Wrap->getCollisionShape(); + btVoronoiSimplexSolver simplexSolver; + simplexSolver.reset(); + btGjkCollisionDescription colDesc; + btMyDistanceInfo distInfo; + int res = btComputeGjkDistance(a,b,colDesc,&distInfo); + if (res==0) + { + //printf("use GJK results in distance %f\n",distInfo.m_distance); + } else + { + btMprCollisionDescription mprDesc; + res = btComputeMprPenetration(a,b,mprDesc, &distInfo); + + //printf("use MPR results in distance %f\n",distInfo.m_distance); + + } + if (res == 0) + { +#if 0 + printf("Dist=%f,normalOnB[%f,%f,%f],pA=[%f,%f,%f],pB[%f,%f,%f]\n", + distInfo.m_distance, distInfo.m_normalBtoA[0], distInfo.m_normalBtoA[1], distInfo.m_normalBtoA[2], + distInfo.m_pointOnA[0], distInfo.m_pointOnA[1], distInfo.m_pointOnA[2], + distInfo.m_pointOnB[0], distInfo.m_pointOnB[1], distInfo.m_pointOnB[2]); +#endif + + if (distInfo.m_distance<=0) + { + resultOut->addContactPoint(distInfo.m_normalBtoA, distInfo.m_pointOnB, distInfo.m_distance); + } + //ASSERT_EQ(0,result); + //ASSERT_NEAR(btFabs(btScalar(i-z))-btScalar(j)-ssd.m_radiusB, distInfo.m_distance, abs_error); + //btVector3 computedA = distInfo.m_pointOnB+distInfo.m_distance*distInfo.m_normalBtoA; + //ASSERT_NEAR(computedA.x(),distInfo.m_pointOnA.x(),abs_error); + //ASSERT_NEAR(computedA.y(),distInfo.m_pointOnA.y(),abs_error); + //ASSERT_NEAR(computedA.z(),distInfo.m_pointOnA.z(),abs_error); + } + + +#if 0 + btCollisionDescription colDesc; + colDesc.m_objA = min0; + colDesc.m_objB = min1; + colDesc.m_localSupportFuncA = &btBulletShapeSupportFunc; + colDesc.m_localSupportFuncB = &btBulletShapeSupportFunc; + colDesc.m_localOriginFuncA = &btBulletShapeCenterFunc; + colDesc.m_localOriginFuncB = &btBulletShapeCenterFunc; + + colDesc.m_transformA = body0Wrap->getWorldTransform(); + colDesc.m_transformB = body1Wrap->getWorldTransform(); + colDesc.m_marginA = body0Wrap->getCollisionShape()->getMargin(); + colDesc.m_marginB = body1Wrap->getCollisionShape()->getMargin(); + btDistanceInfo distInfo; + //int result = btComputeGjkEpaPenetration(colDesc, &distInfo); + //int result = btComputeGjkEpaPenetration2(colDesc, &distInfo); + int result = btComputeMprPenetration(colDesc, &distInfo); + + if (result==0) + { + resultOut->addContactPoint(distInfo.m_normalBtoA,distInfo.m_pointOnB,distInfo.m_distance); + } + + //bool res = b3MprPenetration(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,convexData,collidable2,cpuVertices,sepAxis,hasSepAxis,depthOut,dirOut,posOut); + + /*btCollisionDescription colDesc; + btDistanceInfo distInfo; + int btComputeGjkEpaPenetration(min0, min1, &colDesc, &distInfo); + */ +#endif + } else + { + + btGjkPairDetector gjkPairDetector(min0,min1,&vs,&epa);//m_simplexSolver,m_pdSolver); + //TODO: if (dispatchInfo.m_useContinuous) + gjkPairDetector.setMinkowskiA(min0); + gjkPairDetector.setMinkowskiB(min1); + + { + //if (dispatchInfo.m_convexMaxDistanceUseCPT) + //{ + // input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold(); + //} else + //{ + input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); + // } + + input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; + } + + input.m_transformA = body0Wrap->getWorldTransform(); + input.m_transformB = body1Wrap->getWorldTransform(); + + + gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + } + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + +} + + +btScalar btConvexConvexMprAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + btAssert(0); + return 0; +} + diff --git a/Demos/VoronoiFractureDemo/btConvexConvexMprAlgorithm.h b/Demos/VoronoiFractureDemo/btConvexConvexMprAlgorithm.h new file mode 100644 index 000000000..6edbdccae --- /dev/null +++ b/Demos/VoronoiFractureDemo/btConvexConvexMprAlgorithm.h @@ -0,0 +1,87 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONVEX_CONVEX_MPR_ALGORITHM_H +#define BT_CONVEX_CONVEX_MPR_ALGORITHM_H + +#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil + +class btConvexPenetrationDepthSolver; + +///Enabling USE_SEPDISTANCE_UTIL2 requires 100% reliable distance computation. However, when using large size ratios GJK can be imprecise +///so the distance is not conservative. In that case, enabling this USE_SEPDISTANCE_UTIL2 would result in failing/missing collisions. +///Either improve GJK for large size ratios (testing a 100 units versus a 0.1 unit object) or only enable the util +///for certain pairs that have a small size ratio + +///The convexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations between two convex objects. +///Multiple contact points are calculated by perturbing the orientation of the smallest object orthogonal to the separating normal. +///This idea was described by Gino van den Bergen in this forum topic http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=4&t=288&p=888#p888 +class btConvexConvexMprAlgorithm : public btActivatingCollisionAlgorithm +{ + + + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + ///cache separating vector to speedup collision detection + +public: + + btConvexConvexMprAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap); + + virtual ~btConvexConvexMprAlgorithm(); + + virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + ///should we use m_ownManifold to avoid adding duplicates? + if (m_manifoldPtr && m_ownManifold) + manifoldArray.push_back(m_manifoldPtr); + } + +const btPersistentManifold* getManifold() + { + return m_manifoldPtr; + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + + + + CreateFunc(); + + virtual ~CreateFunc(); + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexMprAlgorithm)); + return new(mem) btConvexConvexMprAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap); + } + }; + + +}; + +#endif //BT_CONVEX_CONVEX_MPR_ALGORITHM_H diff --git a/Demos/VoronoiFractureDemo/main.cpp b/Demos/VoronoiFractureDemo/main.cpp index e1f7a9d76..9da8fe59e 100644 --- a/Demos/VoronoiFractureDemo/main.cpp +++ b/Demos/VoronoiFractureDemo/main.cpp @@ -25,7 +25,7 @@ subject to the following restrictions: int main(int argc,char** argv) { - + VoronoiFractureDemo ccdDemo; ccdDemo.initPhysics(); diff --git a/Demos3/FiniteElementMethod/OpenTissue/dynamics/fem/fem_add_plasticity_force.h b/Demos3/FiniteElementMethod/OpenTissue/dynamics/fem/fem_add_plasticity_force.h index 78ad78e31..12097a692 100644 --- a/Demos3/FiniteElementMethod/OpenTissue/dynamics/fem/fem_add_plasticity_force.h +++ b/Demos3/FiniteElementMethod/OpenTissue/dynamics/fem/fem_add_plasticity_force.h @@ -8,7 +8,7 @@ // OTTL is licensed under zlib: http://opensource.org/licenses/zlib-license.php // #include - +#include //std::min namespace OpenTissue { namespace fem @@ -22,7 +22,7 @@ namespace OpenTissue { using std::min; - using std::sqrt; + using std::sqrt; typedef typename tetrahedron_type::vector3_type vector3_type;