Merge pull request #2193 from John3/bullet_2_87

bullet 2.87 update
This commit is contained in:
Areloch 2018-04-30 23:35:50 -05:00 committed by GitHub
commit cd0bc17bfe
155 changed files with 6111 additions and 4396 deletions

View file

@ -2,17 +2,21 @@ Bullet Physics is created by Erwin Coumans with contributions from the following
AMD
Apple
Yunfei Bai
Steve Baker
Gino van den Bergen
Jeff Bingham
Nicola Candussi
Erin Catto
Lawrence Chai
Erwin Coumans
Christer Ericson
Disney Animation
Benjamin Ellenberger
Christer Ericson
Google
Dirk Gregorius
Marcus Hennix
Jasmine Hsu
MBSim Development Team
Takahiro Harada
Simon Hobbs
@ -20,6 +24,7 @@ John Hsu
Ole Kniemeyer
Jay Lee
Francisco Leon
lunkhound
Vsevolod Klementjev
Phil Knight
John McCutchan
@ -32,9 +37,9 @@ Russel Smith
Sony
Jakub Stephien
Marten Svanfeldt
Jie Tan
Pierre Terdiman
Steven Thompson
Tamas Umenhoffer
Yunfei Bai
If your name is missing, please send an email to erwin.coumans@gmail.com or file an issue at http://github.com/bulletphysics/bullet3

View file

@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 2.4.3)
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
cmake_policy(SET CMP0017 NEW)
#this line has to appear before 'PROJECT' in order to be able to disable incremental linking
SET(MSVC_INCREMENTAL_DEFAULT ON)
PROJECT(BULLET_PHYSICS)
SET(BULLET_VERSION 2.85)
FILE (STRINGS "VERSION" BULLET_VERSION)
IF(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
@ -15,7 +15,6 @@ IF(COMMAND cmake_policy)
endif(POLICY CMP0042)
ENDIF(COMMAND cmake_policy)
IF (NOT CMAKE_BUILD_TYPE)
# SET(CMAKE_BUILD_TYPE "Debug")
SET(CMAKE_BUILD_TYPE "Release")
@ -27,8 +26,33 @@ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
OPTION(USE_DOUBLE_PRECISION "Use double precision" OFF)
OPTION(USE_GRAPHICAL_BENCHMARK "Use Graphical Benchmark" ON)
OPTION(BUILD_SHARED_LIBS "Use shared libraries" OFF)
OPTION(USE_SOFT_BODY_MULTI_BODY_DYNAMICS_WORLD "Use btSoftMultiBodyDynamicsWorld" OFF)
OPTION(BULLET2_USE_THREAD_LOCKS "Build Bullet 2 libraries with mutex locking around certain operations" OFF)
OPTION(USE_SOFT_BODY_MULTI_BODY_DYNAMICS_WORLD "Use btSoftMultiBodyDynamicsWorld" OFF)
OPTION(BULLET2_USE_THREAD_LOCKS "Build Bullet 2 libraries with mutex locking around certain operations (required for multi-threading)" OFF)
IF (BULLET2_USE_THREAD_LOCKS)
OPTION(BULLET2_USE_OPEN_MP_MULTITHREADING "Build Bullet 2 with support for multi-threading with OpenMP (requires a compiler with OpenMP support)" OFF)
OPTION(BULLET2_USE_TBB_MULTITHREADING "Build Bullet 2 with support for multi-threading with Intel Threading Building Blocks (requires the TBB library to be already installed)" OFF)
IF (MSVC)
OPTION(BULLET2_USE_PPL_MULTITHREADING "Build Bullet 2 with support for multi-threading with Microsoft Parallel Patterns Library (requires MSVC compiler)" OFF)
ENDIF (MSVC)
ENDIF (BULLET2_USE_THREAD_LOCKS)
IF(NOT WIN32)
SET(DL ${CMAKE_DL_LIBS})
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
MESSAGE("Linux")
SET(OSDEF -D_LINUX)
ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux")
IF(APPLE)
MESSAGE("Apple")
SET(OSDEF -D_DARWIN)
ELSE(APPLE)
MESSAGE("BSD?")
SET(OSDEF -D_BSD)
ENDIF(APPLE)
ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
ENDIF(NOT WIN32)
OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF)
OPTION(USE_CUSTOM_VECTOR_MATH "Use custom vectormath library" OFF)
@ -85,15 +109,60 @@ IF(MSVC)
ADD_DEFINITIONS(-D_WIN64)
ELSE()
OPTION(USE_MSVC_SSE "Use MSVC /arch:sse option" ON)
option(USE_MSVC_SSE2 "Compile your program with SSE2 instructions" ON)
IF (USE_MSVC_SSE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:SSE")
ENDIF()
IF (USE_MSVC_SSE2)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:SSE2")
ENDIF()
ENDIF()
option(USE_MSVC_AVX "Compile your program with AVX instructions" OFF)
IF(USE_MSVC_AVX)
add_definitions(/arch:AVX)
ENDIF()
OPTION(USE_MSVC_FAST_FLOATINGPOINT "Use MSVC /fp:fast option" ON)
IF (USE_MSVC_FAST_FLOATINGPOINT)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:fast")
ENDIF()
OPTION(USE_MSVC_STRING_POOLING "Use MSVC /GF string pooling option" ON)
IF (USE_MSVC_STRING_POOLING)
SET(CMAKE_C_FLAGS "/GF ${CMAKE_C_FLAGS}")
SET(CMAKE_CXX_FLAGS "/GF ${CMAKE_CXX_FLAGS}")
ENDIF()
OPTION(USE_MSVC_FUNCTION_LEVEL_LINKING "Use MSVC /Gy function level linking option" ON)
IF(USE_MSVC_FUNCTION_LEVEL_LINKING)
SET(CMAKE_C_FLAGS "/Gy ${CMAKE_C_FLAGS}")
SET(CMAKE_CXX_FLAGS "/Gy ${CMAKE_CXX_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /OPT:REF")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /OPT:REF")
ENDIF(USE_MSVC_FUNCTION_LEVEL_LINKING)
OPTION(USE_MSVC_EXEPTIONS "Use MSVC C++ exceptions option" OFF)
OPTION(USE_MSVC_COMDAT_FOLDING "Use MSVC /OPT:ICF COMDAT folding option" ON)
IF(USE_MSVC_COMDAT_FOLDING)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /OPT:ICF")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /OPT:ICF")
ENDIF()
OPTION(USE_MSVC_DISABLE_RTTI "Use MSVC /GR- disabled RTTI flags option" ON)
IF(USE_MSVC_DISABLE_RTTI)
STRING(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) # Disable RTTI
SET(CMAKE_C_FLAGS "/GR- ${CMAKE_C_FLAGS}")
SET(CMAKE_CXX_FLAGS "/GR- ${CMAKE_CXX_FLAGS}")
ENDIF(USE_MSVC_DISABLE_RTTI)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244 /wd4267")
ENDIF(MSVC)
@ -163,6 +232,30 @@ IF(BULLET2_USE_THREAD_LOCKS)
ENDIF (NOT MSVC)
ENDIF (BULLET2_USE_THREAD_LOCKS)
IF (BULLET2_USE_OPEN_MP_MULTITHREADING)
ADD_DEFINITIONS("-DBT_USE_OPENMP=1")
IF (MSVC)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp")
ELSE (MSVC)
# GCC, Clang
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
ENDIF (MSVC)
ENDIF (BULLET2_USE_OPEN_MP_MULTITHREADING)
IF (BULLET2_USE_TBB_MULTITHREADING)
SET (BULLET2_TBB_INCLUDE_DIR "not found" CACHE PATH "Directory for Intel TBB includes.")
SET (BULLET2_TBB_LIB_DIR "not found" CACHE PATH "Directory for Intel TBB libraries.")
find_library(TBB_LIBRARY tbb PATHS ${BULLET2_TBB_LIB_DIR})
find_library(TBBMALLOC_LIBRARY tbbmalloc PATHS ${BULLET2_TBB_LIB_DIR})
ADD_DEFINITIONS("-DBT_USE_TBB=1")
INCLUDE_DIRECTORIES( ${BULLET2_TBB_INCLUDE_DIR} )
LINK_LIBRARIES( ${TBB_LIBRARY} ${TBBMALLOC_LIBRARY} )
ENDIF (BULLET2_USE_TBB_MULTITHREADING)
IF (BULLET2_USE_PPL_MULTITHREADING)
ADD_DEFINITIONS("-DBT_USE_PPL=1")
ENDIF (BULLET2_USE_PPL_MULTITHREADING)
IF (WIN32)
OPTION(USE_GLUT "Use Glut" ON)
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
@ -208,19 +301,40 @@ IF (APPLE)
ENDIF()
OPTION(BUILD_BULLET3 "Set when you want to build Bullet 3" ON)
# Optional Python configuration
# builds pybullet automatically if all the requirements are met
SET(PYTHON_VERSION_PYBULLET "" CACHE STRING "Python version pybullet will use.")
SET(Python_ADDITIONAL_VERSIONS 3 3.6 3.5 3.4 3.3 3.2 3.1 3.0 2.7 2.7.12 2.7.10 2.7.3 )
SET_PROPERTY(CACHE PYTHON_VERSION_PYBULLET PROPERTY STRINGS ${Python_ADDITIONAL_VERSIONS})
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/build3/cmake ${CMAKE_MODULE_PATH})
OPTION(EXACT_PYTHON_VERSION "Require Python and match PYTHON_VERSION_PYBULLET exactly, e.g. 2.7.12" OFF)
IF(EXACT_PYTHON_VERSION)
set(EXACT_PYTHON_VERSION_FLAG EXACT REQUIRED)
ENDIF(EXACT_PYTHON_VERSION)
# first find the python interpreter
FIND_PACKAGE(PythonInterp ${PYTHON_VERSION_PYBULLET} ${EXACT_PYTHON_VERSION_FLAG})
# python library should exactly match that of the interpreter
FIND_PACKAGE(PythonLibs ${PYTHON_VERSION_STRING} EXACT)
SET(DEFAULT_BUILD_PYBULLET OFF)
IF(PYTHONLIBS_FOUND)
SET(DEFAULT_BUILD_PYBULLET ON)
ENDIF(PYTHONLIBS_FOUND)
OPTION(BUILD_PYBULLET "Set when you want to build pybullet (Python bindings for Bullet)" ${DEFAULT_BUILD_PYBULLET})
OPTION(BUILD_PYBULLET "Set when you want to build pybullet (experimental Python bindings for Bullet)" OFF)
OPTION(BUILD_ENET "Set when you want to build apps with enet UDP networking support" ON)
OPTION(BUILD_CLSOCKET "Set when you want to build apps with enet TCP networking support" ON)
IF(BUILD_PYBULLET)
FIND_PACKAGE(PythonLibs)
OPTION(BUILD_PYBULLET_NUMPY "Set when you want to build pybullet with NumPy support" OFF)
OPTION(BUILD_PYBULLET_ENET "Set when you want to build pybullet with enet UDP networking support" ON)
IF(BUILD_PYBULLET_NUMPY)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR}/build3/cmake)
OPTION(BUILD_PYBULLET_CLSOCKET "Set when you want to build pybullet with enet TCP networking support" ON)
OPTION(BUILD_PYBULLET_MAC_USE_PYTHON_FRAMEWORK "Set when you want to use the Python Framework on Mac" OFF)
IF(BUILD_PYBULLET_NUMPY)
#include(FindNumPy)
FIND_PACKAGE(NumPy)
if (PYTHON_NUMPY_FOUND)
@ -230,13 +344,25 @@ IF(BUILD_PYBULLET)
message("NumPy not found")
endif()
ENDIF()
OPTION(BUILD_PYBULLET "Set when you want to build pybullet (experimental Python bindings for Bullet)" OFF)
IF(WIN32)
SET(BUILD_SHARED_LIBS OFF CACHE BOOL "Shared Libs" FORCE)
ELSE(WIN32)
SET(BUILD_SHARED_LIBS ON CACHE BOOL "Shared Libs" FORCE)
ENDIF(WIN32)
IF(APPLE)
OPTION(BUILD_PYBULLET_MAC_USE_PYTHON_FRAMEWORK "Set when you want to use the Python Framework on Mac" ON)
IF(NOT BUILD_PYBULLET_MAC_USE_PYTHON_FRAMEWORK)
add_definitions(-DB3_NO_PYTHON_FRAMEWORK)
ENDIF(NOT BUILD_PYBULLET_MAC_USE_PYTHON_FRAMEWORK)
OPTION(BUILD_PYBULLET_SHOW_PY_VERSION "Set when you want to show the PY_MAJOR_VERSION and PY_MAJOR_VERSION using #pragme message." OFF)
IF(BUILD_PYBULLET_SHOW_PY_VERSION)
add_definitions(-DB3_DUMP_PYTHON_VERSION)
ENDIF()
ENDIF(APPLE)
ENDIF(BUILD_PYBULLET)
IF(BUILD_BULLET3)
@ -272,14 +398,6 @@ IF(BUILD_BULLET2_DEMOS)
SUBDIRS(examples)
ENDIF()
IF (BULLET2_USE_THREAD_LOCKS)
OPTION(BULLET2_MULTITHREADED_OPEN_MP_DEMO "Build Bullet 2 MultithreadedDemo using OpenMP (requires a compiler with OpenMP support)" OFF)
OPTION(BULLET2_MULTITHREADED_TBB_DEMO "Build Bullet 2 MultithreadedDemo using Intel Threading Building Blocks (requires the TBB library to be already installed)" OFF)
IF (MSVC)
OPTION(BULLET2_MULTITHREADED_PPL_DEMO "Build Bullet 2 MultithreadedDemo using Microsoft Parallel Patterns Library (requires MSVC compiler)" OFF)
ENDIF (MSVC)
ENDIF (BULLET2_USE_THREAD_LOCKS)
ENDIF(BUILD_BULLET2_DEMOS)
@ -290,7 +408,6 @@ IF(BUILD_EXTRAS)
ENDIF(BUILD_EXTRAS)
#Maya Dynamica plugin is moved to http://dynamica.googlecode.com
SUBDIRS(src)
@ -305,7 +422,15 @@ ELSE()
ENDIF()
ENDIF()
IF(INSTALL_LIBS)
#INSTALL of other files requires CMake 2.6
IF(BUILD_EXTRAS)
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
OPTION(INSTALL_EXTRA_LIBS "Set when you want extra libraries installed" ON)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
ENDIF(BUILD_EXTRAS)
SET (LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
SET (LIB_DESTINATION "lib${LIB_SUFFIX}" CACHE STRING "Library directory name")
## the following are directories where stuff will be installed to
@ -319,12 +444,8 @@ IF(INSTALL_LIBS)
DESTINATION
${PKGCONFIG_INSTALL_PREFIX})
ENDIF(NOT MSVC)
ENDIF(INSTALL_LIBS)
ENDIF()
#INSTALL of other files requires CMake 2.6
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
OPTION(INSTALL_EXTRA_LIBS "Set when you want extra libraries installed" OFF)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
OPTION(BUILD_UNIT_TESTS "Build Unit Tests" ON)
@ -335,9 +456,8 @@ ENDIF()
set (BULLET_CONFIG_CMAKE_PATH lib${LIB_SUFFIX}/cmake/bullet )
list (APPEND BULLET_LIBRARIES LinearMath)
IF(BUILD_BULLET3)
list (APPEND BULLET_LIBRARIES BulletInverseDynamics)
ENDIF(BUILD_BULLET3)
list (APPEND BULLET_LIBRARIES Bullet3Common)
list (APPEND BULLET_LIBRARIES BulletInverseDynamics)
list (APPEND BULLET_LIBRARIES BulletCollision)
list (APPEND BULLET_LIBRARIES BulletDynamics)
list (APPEND BULLET_LIBRARIES BulletSoftBody)
@ -346,7 +466,11 @@ configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/BulletConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/BulletConfig.cmake
@ONLY ESCAPE_QUOTES
)
install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/UseBullet.cmake
OPTION(INSTALL_CMAKE_FILES "Install generated CMake files" ON)
IF (INSTALL_CMAKE_FILES)
install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/UseBullet.cmake
${CMAKE_CURRENT_BINARY_DIR}/BulletConfig.cmake
DESTINATION ${BULLET_CONFIG_CMAKE_PATH}
)
ENDIF (INSTALL_CMAKE_FILES)

View file

@ -49,36 +49,48 @@ All source code files are licensed under the permissive zlib license
**Windows**
Click on build_visual_studio.bat and open build3/vs2010/0MySolution.sln
Click on build_visual_studio_vr_pybullet_double.bat and open build3/vs2010/0MySolution.sln
When asked, convert the projects to a newer version of Visual Studio.
If you installed Python in the C:\ root directory, the batch file should find it automatically.
Otherwise, edit this batch file to choose where Python include/lib directories are located.
**Windows Virtual Reality sandbox for HTC Vive and Oculus Rift**
Click on build_visual_studio_vr_pybullet_double.bat and open build3/vs2010/0MySolution.sln
Edit this batch file to choose where Python include/lib directories are located.
Build and run the App_SharedMemoryPhysics_VR project, preferably in Release/optimized build.
You can connect from Python pybullet to the sandbox using:
```
import pybullet as p
p.connect(p.SHARED_MEMORY)
p.connect(p.SHARED_MEMORY) #or (p.TCP, "localhost", 6667) or (p.UDP, "192.168.86.10",1234)
```
**Linux and Mac OSX gnu make**
Make sure cmake is installed (sudo apt-get install cmake, brew install cmake, or https://cmake.org)
In a terminal type:
cd build3
./build_cmake_pybullet_double.sh
This script will invoke cmake and build in the build_cmake directory. You can find pybullet in Bullet/examples/pybullet.
The BulletExampleBrowser binary will be in Bullet/examples/ExampleBrowser.
You can also build Bullet using premake. There are premake executables in the build3 folder.
Depending on your system (Linux 32bit, 64bit or Mac OSX) use one of the following lines
./premake4_linux gmake
./premake4_linux64 gmake
./premake4_osx gmake
Using premake:
```
cd build3
./premake4_linux gmake --double
./premake4_linux64 gmake --double
./premake4_osx gmake --double --enable_pybullet
```
Then
```
cd gmake
make
```
Note that on Linux, you need to use cmake to build pybullet, since the compiler has issues of mixing shared and static libraries.
**Mac OSX Xcode**

View file

@ -1 +1 @@
2.85
2.87

File diff suppressed because it is too large Load diff

View file

@ -41,6 +41,10 @@ struct btBroadphaseRayCallback : public btBroadphaseAabbCallback
btScalar m_lambda_max;
virtual ~btBroadphaseRayCallback() {}
protected:
btBroadphaseRayCallback() {}
};
#include "LinearMath/btVector3.h"
@ -53,7 +57,7 @@ class btBroadphaseInterface
public:
virtual ~btBroadphaseInterface() {}
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0;
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher) =0;
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0;
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0;

View file

@ -15,3 +15,4 @@ subject to the following restrictions:
#include "btBroadphaseProxy.h"
BT_NOT_EMPTY_FILE // fix warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library

View file

@ -101,10 +101,10 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
//Usually the client btCollisionObject or Rigidbody class
void* m_clientObject;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
void* m_multiSapParentProxy;
int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
int m_collisionFilterGroup;
int m_collisionFilterMask;
int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
btVector3 m_aabbMin;
btVector3 m_aabbMax;
@ -115,18 +115,17 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
}
//used for memory pools
btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0)
btBroadphaseProxy() :m_clientObject(0)
{
}
btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0)
btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr, int collisionFilterGroup, int collisionFilterMask)
:m_clientObject(userPtr),
m_collisionFilterGroup(collisionFilterGroup),
m_collisionFilterMask(collisionFilterMask),
m_aabbMin(aabbMin),
m_aabbMax(aabbMax)
{
m_multiSapParentProxy = multiSapParentProxy;
}

View file

@ -229,25 +229,60 @@ static void fetchleaves(btDbvt* pdbvt,
}
//
static void split( const tNodeArray& leaves,
tNodeArray& left,
tNodeArray& right,
static bool leftOfAxis( const btDbvtNode* node,
const btVector3& org,
const btVector3& axis)
{
return btDot(axis, node->volume.Center() - org) <= 0;
}
// Partitions leaves such that leaves[0, n) are on the
// left of axis, and leaves[n, count) are on the right
// of axis. returns N.
static int split( btDbvtNode** leaves,
int count,
const btVector3& org,
const btVector3& axis)
{
left.resize(0);
right.resize(0);
for(int i=0,ni=leaves.size();i<ni;++i)
int begin=0;
int end=count;
for(;;)
{
if(btDot(axis,leaves[i]->volume.Center()-org)<0)
left.push_back(leaves[i]);
else
right.push_back(leaves[i]);
while(begin!=end && leftOfAxis(leaves[begin],org,axis))
{
++begin;
}
if(begin==end)
{
break;
}
while(begin!=end && !leftOfAxis(leaves[end-1],org,axis))
{
--end;
}
if(begin==end)
{
break;
}
// swap out of place nodes
--end;
btDbvtNode* temp=leaves[begin];
leaves[begin]=leaves[end];
leaves[end]=temp;
++begin;
}
return begin;
}
//
static btDbvtVolume bounds( const tNodeArray& leaves)
static btDbvtVolume bounds( btDbvtNode** leaves,
int count)
{
#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
@ -257,7 +292,7 @@ static btDbvtVolume bounds( const tNodeArray& leaves)
#else
btDbvtVolume volume=leaves[0]->volume;
#endif
for(int i=1,ni=leaves.size();i<ni;++i)
for(int i=1,ni=count;i<ni;++i)
{
Merge(volume,leaves[i]->volume,volume);
}
@ -266,15 +301,16 @@ static btDbvtVolume bounds( const tNodeArray& leaves)
//
static void bottomup( btDbvt* pdbvt,
tNodeArray& leaves)
btDbvtNode** leaves,
int count)
{
while(leaves.size()>1)
while(count>1)
{
btScalar minsize=SIMD_INFINITY;
int minidx[2]={-1,-1};
for(int i=0;i<leaves.size();++i)
for(int i=0;i<count;++i)
{
for(int j=i+1;j<leaves.size();++j)
for(int j=i+1;j<count;++j)
{
const btScalar sz=size(merge(leaves[i]->volume,leaves[j]->volume));
if(sz<minsize)
@ -292,31 +328,33 @@ static void bottomup( btDbvt* pdbvt,
n[0]->parent = p;
n[1]->parent = p;
leaves[minidx[0]] = p;
leaves.swap(minidx[1],leaves.size()-1);
leaves.pop_back();
leaves[minidx[1]] = leaves[count-1];
--count;
}
}
//
static btDbvtNode* topdown(btDbvt* pdbvt,
tNodeArray& leaves,
btDbvtNode** leaves,
int count,
int bu_treshold)
{
static const btVector3 axis[]={btVector3(1,0,0),
btVector3(0,1,0),
btVector3(0,0,1)};
if(leaves.size()>1)
btAssert(bu_treshold>2);
if(count>1)
{
if(leaves.size()>bu_treshold)
if(count>bu_treshold)
{
const btDbvtVolume vol=bounds(leaves);
const btDbvtVolume vol=bounds(leaves,count);
const btVector3 org=vol.Center();
tNodeArray sets[2];
int partition;
int bestaxis=-1;
int bestmidp=leaves.size();
int bestmidp=count;
int splitcount[3][2]={{0,0},{0,0},{0,0}};
int i;
for( i=0;i<leaves.size();++i)
for( i=0;i<count;++i)
{
const btVector3 x=leaves[i]->volume.Center()-org;
for(int j=0;j<3;++j)
@ -338,29 +376,23 @@ static btDbvtNode* topdown(btDbvt* pdbvt,
}
if(bestaxis>=0)
{
sets[0].reserve(splitcount[bestaxis][0]);
sets[1].reserve(splitcount[bestaxis][1]);
split(leaves,sets[0],sets[1],org,axis[bestaxis]);
partition=split(leaves,count,org,axis[bestaxis]);
btAssert(partition!=0 && partition!=count);
}
else
{
sets[0].reserve(leaves.size()/2+1);
sets[1].reserve(leaves.size()/2);
for(int i=0,ni=leaves.size();i<ni;++i)
{
sets[i&1].push_back(leaves[i]);
}
partition=count/2+1;
}
btDbvtNode* node=createnode(pdbvt,0,vol,0);
node->childs[0]=topdown(pdbvt,sets[0],bu_treshold);
node->childs[1]=topdown(pdbvt,sets[1],bu_treshold);
node->childs[0]=topdown(pdbvt,&leaves[0],partition,bu_treshold);
node->childs[1]=topdown(pdbvt,&leaves[partition],count-partition,bu_treshold);
node->childs[0]->parent=node;
node->childs[1]->parent=node;
return(node);
}
else
{
bottomup(pdbvt,leaves);
bottomup(pdbvt,leaves,count);
return(leaves[0]);
}
}
@ -444,7 +476,7 @@ void btDbvt::optimizeBottomUp()
tNodeArray leaves;
leaves.reserve(m_leaves);
fetchleaves(this,m_root,leaves);
bottomup(this,leaves);
bottomup(this,&leaves[0],leaves.size());
m_root=leaves[0];
}
}
@ -457,7 +489,7 @@ void btDbvt::optimizeTopDown(int bu_treshold)
tNodeArray leaves;
leaves.reserve(m_leaves);
fetchleaves(this,m_root,leaves);
m_root=topdown(this,leaves,bu_treshold);
m_root=topdown(this,&leaves[0],leaves.size(),bu_treshold);
}
}

View file

@ -942,7 +942,13 @@ inline void btDbvt::collideTV( const btDbvtNode* root,
ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol);
btAlignedObjectArray<const btDbvtNode*> stack;
stack.resize(0);
#ifndef BT_DISABLE_STACK_TEMP_MEMORY
char tempmemory[SIMPLE_STACKSIZE*sizeof(const btDbvtNode*)];
stack.initializeFromBuffer(tempmemory, 0, SIMPLE_STACKSIZE);
#else
stack.reserve(SIMPLE_STACKSIZE);
#endif //BT_DISABLE_STACK_TEMP_MEMORY
stack.push_back(root);
do {
const btDbvtNode* n=stack[stack.size()-1];
@ -1078,7 +1084,12 @@ inline void btDbvt::rayTest( const btDbvtNode* root,
int depth=1;
int treshold=DOUBLE_STACKSIZE-2;
char tempmemory[DOUBLE_STACKSIZE * sizeof(const btDbvtNode*)];
#ifndef BT_DISABLE_STACK_TEMP_MEMORY
stack.initializeFromBuffer(tempmemory, DOUBLE_STACKSIZE, DOUBLE_STACKSIZE);
#else//BT_DISABLE_STACK_TEMP_MEMORY
stack.resize(DOUBLE_STACKSIZE);
#endif //BT_DISABLE_STACK_TEMP_MEMORY
stack[0]=root;
btVector3 bounds[2];
do {

View file

@ -168,10 +168,9 @@ btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin,
const btVector3& aabbMax,
int /*shapeType*/,
void* userPtr,
short int collisionFilterGroup,
short int collisionFilterMask,
btDispatcher* /*dispatcher*/,
void* /*multiSapProxy*/)
int collisionFilterGroup,
int collisionFilterMask,
btDispatcher* /*dispatcher*/)
{
btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( aabbMin,aabbMax,userPtr,
collisionFilterGroup,
@ -545,7 +544,9 @@ void btDbvtBroadphase::collide(btDispatcher* dispatcher)
btDbvtProxy* current=m_stageRoots[m_stageCurrent];
if(current)
{
#if DBVT_BP_ACCURATESLEEPING
btDbvtTreeCollider collider(this);
#endif
do {
btDbvtProxy* next=current->links[1];
listremove(current,m_stageRoots[current->stage]);

View file

@ -47,7 +47,7 @@ struct btDbvtProxy : btBroadphaseProxy
btDbvtProxy* links[2];
int stage;
/* ctor */
btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr, int collisionFilterGroup, int collisionFilterMask) :
btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
{
links[0]=links[1]=0;
@ -105,7 +105,7 @@ struct btDbvtBroadphase : btBroadphaseInterface
void optimize();
/* btBroadphaseInterface Implementation */
btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask,btDispatcher* dispatcher);
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));

View file

@ -1,489 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btMultiSapBroadphase.h"
#include "btSimpleBroadphase.h"
#include "LinearMath/btAabbUtil2.h"
#include "btQuantizedBvh.h"
/// btSapBroadphaseArray m_sapBroadphases;
/// btOverlappingPairCache* m_overlappingPairs;
extern int gOverlappingPairs;
/*
class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache
{
public:
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy);
}
};
*/
btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache)
:m_overlappingPairs(pairCache),
m_optimizedAabbTree(0),
m_ownsPairCache(false),
m_invalidPair(0)
{
if (!m_overlappingPairs)
{
m_ownsPairCache = true;
void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16);
m_overlappingPairs = new (mem)btSortedOverlappingPairCache();
}
struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
{
virtual ~btMultiSapOverlapFilterCallback()
{}
// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
{
btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy;
btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy;
bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0;
collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask);
return collides;
}
};
void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16);
m_filterCallback = new (mem)btMultiSapOverlapFilterCallback();
m_overlappingPairs->setOverlapFilterCallback(m_filterCallback);
// mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16);
// m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs);
}
btMultiSapBroadphase::~btMultiSapBroadphase()
{
if (m_ownsPairCache)
{
m_overlappingPairs->~btOverlappingPairCache();
btAlignedFree(m_overlappingPairs);
}
}
void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
{
m_optimizedAabbTree = new btQuantizedBvh();
m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax);
QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray();
for (int i=0;i<m_sapBroadphases.size();i++)
{
btQuantizedBvhNode node;
btVector3 aabbMin,aabbMax;
m_sapBroadphases[i]->getBroadphaseAabb(aabbMin,aabbMax);
m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
int partId = 0;
node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
nodes.push_back(node);
}
m_optimizedAabbTree->buildInternal();
}
btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/)
{
//void* ignoreMe -> we could think of recursive multi-sap, if someone is interested
void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
m_multiSapProxies.push_back(proxy);
///this should deal with inserting/removal into child broadphases
setAabb(proxy,aabbMin,aabbMax,dispatcher);
return proxy;
}
void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
{
///not yet
btAssert(0);
}
void btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase)
{
void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16);
btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy;
bridgeProxyRef->m_childProxy = childProxy;
bridgeProxyRef->m_childBroadphase = childBroadphase;
parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef);
}
bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax);
bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax)
{
return
amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() &&
amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() &&
amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ();
}
void btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
{
btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
aabbMin = multiProxy->m_aabbMin;
aabbMax = multiProxy->m_aabbMax;
}
void btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
{
for (int i=0;i<m_multiSapProxies.size();i++)
{
rayCallback.process(m_multiSapProxies[i]);
}
}
//#include <stdio.h>
void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
{
btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
multiProxy->m_aabbMin = aabbMin;
multiProxy->m_aabbMax = aabbMax;
// bool fullyContained = false;
// bool alreadyInSimple = false;
struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
btMultiSapBroadphase* m_multiSap;
btMultiSapProxy* m_multiProxy;
btDispatcher* m_dispatcher;
MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
:m_multiSap(multiSap),
m_multiProxy(multiProxy),
m_dispatcher(dispatcher)
{
}
virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
{
btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
int containingBroadphaseIndex = -1;
//already found?
for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++)
{
if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
{
containingBroadphaseIndex = i;
break;
}
}
if (containingBroadphaseIndex<0)
{
//add it
btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy);
m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
}
}
};
MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher);
if (m_optimizedAabbTree)
m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
int i;
for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
{
btVector3 worldAabbMin,worldAabbMax;
multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
if (!overlapsBroadphase)
{
//remove it now
btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
multiProxy->m_bridgeProxies.pop_back();
}
}
/*
if (1)
{
//find broadphase that contain this multiProxy
int numChildBroadphases = getBroadphaseArray().size();
for (int i=0;i<numChildBroadphases;i++)
{
btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
btVector3 worldAabbMin,worldAabbMax;
childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
// fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
int containingBroadphaseIndex = -1;
//if already contains this
for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
{
if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
{
containingBroadphaseIndex = i;
}
alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
}
if (overlapsBroadphase)
{
if (containingBroadphaseIndex<0)
{
btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
childProxy->m_multiSapParentProxy = multiProxy;
addToChildBroadphase(multiProxy,childProxy,childBroadphase);
}
} else
{
if (containingBroadphaseIndex>=0)
{
//remove
btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
multiProxy->m_bridgeProxies.pop_back();
}
}
}
///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
if (0)//!multiProxy->m_bridgeProxies.size())
{
///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
///this is needed to be able to calculate the aabb overlap
btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
childProxy->m_multiSapParentProxy = multiProxy;
addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
}
}
if (!multiProxy->m_bridgeProxies.size())
{
///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
///this is needed to be able to calculate the aabb overlap
btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
childProxy->m_multiSapParentProxy = multiProxy;
addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
}
*/
//update
for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
{
btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
}
}
bool stopUpdating=false;
class btMultiSapBroadphasePairSortPredicate
{
public:
bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 ) const
{
btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
return aProxy0 > bProxy0 ||
(aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
(aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm);
}
};
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{
// m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
{
btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
// quicksort(overlappingPairArray,0,overlappingPairArray.size());
overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
// overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
int i;
btBroadphasePair previousPair;
previousPair.m_pProxy0 = 0;
previousPair.m_pProxy1 = 0;
previousPair.m_algorithm = 0;
for (i=0;i<overlappingPairArray.size();i++)
{
btBroadphasePair& pair = overlappingPairArray[i];
btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
previousPair = pair;
bool needsRemoval = false;
if (!isDuplicate)
{
bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
if (hasOverlap)
{
needsRemoval = false;//callback->processOverlap(pair);
} else
{
needsRemoval = true;
}
} else
{
//remove duplicate
needsRemoval = true;
//should have no algorithm
btAssert(!pair.m_algorithm);
}
if (needsRemoval)
{
getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher);
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
// m_overlappingPairArray.pop_back();
pair.m_pProxy0 = 0;
pair.m_pProxy1 = 0;
m_invalidPair++;
gOverlappingPairs--;
}
}
///if you don't like to skip the invalid pairs in the array, execute following code:
#define CLEAN_INVALID_PAIRS 1
#ifdef CLEAN_INVALID_PAIRS
//perform a sort, to sort 'invalid' pairs to the end
//overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
#endif//CLEAN_INVALID_PAIRS
//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
}
}
bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1)
{
btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax,
multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax);
}
void btMultiSapBroadphase::printStats()
{
/* printf("---------------------------------\n");
printf("btMultiSapBroadphase.h\n");
printf("numHandles = %d\n",m_multiSapProxies.size());
//find broadphase that contain this multiProxy
int numChildBroadphases = getBroadphaseArray().size();
for (int i=0;i<numChildBroadphases;i++)
{
btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
childBroadphase->printStats();
}
*/
}
void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher)
{
// not yet
}

View file

@ -1,151 +0,0 @@
/*
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_MULTI_SAP_BROADPHASE
#define BT_MULTI_SAP_BROADPHASE
#include "btBroadphaseInterface.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "btOverlappingPairCache.h"
class btBroadphaseInterface;
class btSimpleBroadphase;
typedef btAlignedObjectArray<btBroadphaseInterface*> btSapBroadphaseArray;
///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead.
///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases.
///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time.
///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy.
///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328
///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329
class btMultiSapBroadphase :public btBroadphaseInterface
{
btSapBroadphaseArray m_sapBroadphases;
btSimpleBroadphase* m_simpleBroadphase;
btOverlappingPairCache* m_overlappingPairs;
class btQuantizedBvh* m_optimizedAabbTree;
bool m_ownsPairCache;
btOverlapFilterCallback* m_filterCallback;
int m_invalidPair;
struct btBridgeProxy
{
btBroadphaseProxy* m_childProxy;
btBroadphaseInterface* m_childBroadphase;
};
public:
struct btMultiSapProxy : public btBroadphaseProxy
{
///array with all the entries that this proxy belongs to
btAlignedObjectArray<btBridgeProxy*> m_bridgeProxies;
btVector3 m_aabbMin;
btVector3 m_aabbMax;
int m_shapeType;
/* void* m_userPtr;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
*/
btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask)
:btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask),
m_aabbMin(aabbMin),
m_aabbMax(aabbMax),
m_shapeType(shapeType)
{
m_multiSapParentProxy =this;
}
};
protected:
btAlignedObjectArray<btMultiSapProxy*> m_multiSapProxies;
public:
btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0);
btSapBroadphaseArray& getBroadphaseArray()
{
return m_sapBroadphases;
}
const btSapBroadphaseArray& getBroadphaseArray() const
{
return m_sapBroadphases;
}
virtual ~btMultiSapBroadphase();
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase);
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
virtual btOverlappingPairCache* getOverlappingPairCache()
{
return m_overlappingPairs;
}
virtual const btOverlappingPairCache* getOverlappingPairCache() const
{
return m_overlappingPairs;
}
///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
///will add some transform later
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
{
aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
}
void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
virtual void printStats();
void quicksort (btBroadphasePairArray& a, int lo, int hi);
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
};
#endif //BT_MULTI_SAP_BROADPHASE

View file

@ -90,7 +90,8 @@ public:
};
/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
class btHashedOverlappingPairCache : public btOverlappingPairCache
ATTRIBUTE_ALIGNED16(class) btHashedOverlappingPairCache : public btOverlappingPairCache
{
btBroadphasePairArray m_overlappingPairArray;
btOverlapFilterCallback* m_overlapFilterCallback;
@ -103,6 +104,8 @@ protected:
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btHashedOverlappingPairCache();
virtual ~btHashedOverlappingPairCache();
@ -212,10 +215,9 @@ private:
*/
SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
{
int key = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16));
unsigned int key = proxyId1 | (proxyId2 << 16);
// Thomas Wang's hash
key += ~(key << 15);
@ -224,13 +226,11 @@ private:
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return static_cast<unsigned int>(key);
return key;
}
SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
{
int proxyId1 = proxy0->getUid();

View file

@ -23,6 +23,9 @@ struct btBroadphasePair;
///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
class btOverlappingPairCallback
{
protected:
btOverlappingPairCallback() {}
public:
virtual ~btOverlappingPairCallback()
{

View file

@ -1336,6 +1336,8 @@ const char* btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer
memPtr->m_escapeIndex = m_contiguousNodes[i].m_escapeIndex;
memPtr->m_subPart = m_contiguousNodes[i].m_subPart;
memPtr->m_triangleIndex = m_contiguousNodes[i].m_triangleIndex;
// Fill padding with zeros to appease msan.
memset(memPtr->m_pad, 0, sizeof(memPtr->m_pad));
}
serializer->finalizeChunk(chunk,"btOptimizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_contiguousNodes[0]);
}

View file

@ -169,7 +169,7 @@ typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase.
///It is used by the btBvhTriangleMeshShape as midphase.
///It is recommended to use quantization for better performance and lower memory requirements.
ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
{

View file

@ -84,7 +84,7 @@ btSimpleBroadphase::~btSimpleBroadphase()
}
btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy)
btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr , int collisionFilterGroup, int collisionFilterMask, btDispatcher* /*dispatcher*/)
{
if (m_numHandles >= m_maxHandles)
{
@ -94,7 +94,7 @@ btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin,
btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]);
int newHandleIndex = allocHandle();
btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy);
btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask);
return proxy;
}

View file

@ -29,8 +29,8 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy
btSimpleBroadphaseProxy() {};
btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy)
:btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy)
btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr, int collisionFilterGroup, int collisionFilterMask)
:btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask)
{
(void)shapeType;
}
@ -127,7 +127,7 @@ public:
static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1);
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr , int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);

View file

@ -7,7 +7,6 @@ SET(BulletCollision_SRCS
BroadphaseCollision/btDbvt.cpp
BroadphaseCollision/btDbvtBroadphase.cpp
BroadphaseCollision/btDispatcher.cpp
BroadphaseCollision/btMultiSapBroadphase.cpp
BroadphaseCollision/btOverlappingPairCache.cpp
BroadphaseCollision/btQuantizedBvh.cpp
BroadphaseCollision/btSimpleBroadphase.cpp
@ -16,6 +15,7 @@ SET(BulletCollision_SRCS
CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
CollisionDispatch/btBoxBoxDetector.cpp
CollisionDispatch/btCollisionDispatcher.cpp
CollisionDispatch/btCollisionDispatcherMt.cpp
CollisionDispatch/btCollisionObject.cpp
CollisionDispatch/btCollisionWorld.cpp
CollisionDispatch/btCollisionWorldImporter.cpp
@ -103,6 +103,7 @@ SET(Root_HDRS
../btBulletCollisionCommon.h
)
SET(BroadphaseCollision_HDRS
BroadphaseCollision/btAxisSweep3Internal.h
BroadphaseCollision/btAxisSweep3.h
BroadphaseCollision/btBroadphaseInterface.h
BroadphaseCollision/btBroadphaseProxy.h
@ -110,7 +111,6 @@ SET(BroadphaseCollision_HDRS
BroadphaseCollision/btDbvt.h
BroadphaseCollision/btDbvtBroadphase.h
BroadphaseCollision/btDispatcher.h
BroadphaseCollision/btMultiSapBroadphase.h
BroadphaseCollision/btOverlappingPairCache.h
BroadphaseCollision/btOverlappingPairCallback.h
BroadphaseCollision/btQuantizedBvh.h
@ -124,6 +124,7 @@ SET(CollisionDispatch_HDRS
CollisionDispatch/btCollisionConfiguration.h
CollisionDispatch/btCollisionCreateFunc.h
CollisionDispatch/btCollisionDispatcher.h
CollisionDispatch/btCollisionDispatcherMt.h
CollisionDispatch/btCollisionObject.h
CollisionDispatch/btCollisionObjectWrapper.h
CollisionDispatch/btCollisionWorld.h
@ -191,12 +192,15 @@ SET(CollisionShapes_HDRS
SET(Gimpact_HDRS
Gimpact/btBoxCollision.h
Gimpact/btClipPolygon.h
Gimpact/btContactProcessingStructs.h
Gimpact/btContactProcessing.h
Gimpact/btGenericPoolAllocator.h
Gimpact/btGeometryOperations.h
Gimpact/btGImpactBvhStructs.h
Gimpact/btGImpactBvh.h
Gimpact/btGImpactCollisionAlgorithm.h
Gimpact/btGImpactMassUtil.h
Gimpact/btGImpactQuantizedBvhStructs.h
Gimpact/btGImpactQuantizedBvh.h
Gimpact/btGImpactShape.h
Gimpact/btQuantization.h

View file

@ -100,45 +100,54 @@ bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &po
btScalar radiusWithThreshold = radius + contactBreakingThreshold;
btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
normal.safeNormalize();
btVector3 p1ToCentre = sphereCenter - vertices[0];
btScalar distanceFromPlane = p1ToCentre.dot(normal);
if (distanceFromPlane < btScalar(0.))
{
//triangle facing the other way
distanceFromPlane *= btScalar(-1.);
normal *= btScalar(-1.);
}
bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
// Check for contact / intersection
btScalar l2 = normal.length2();
bool hasContact = false;
btVector3 contactPoint;
if (isInsideContactPlane) {
if (facecontains(sphereCenter,vertices,normal)) {
// Inside the contact wedge - touches a point on the shell plane
hasContact = true;
contactPoint = sphereCenter - normal*distanceFromPlane;
} else {
// Could be inside one of the contact capsules
btScalar contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;
btVector3 nearestOnEdge;
for (int i = 0; i < m_triangle->getNumEdges(); i++) {
btVector3 pa;
btVector3 pb;
m_triangle->getEdge(i,pa,pb);
btScalar distanceSqr = SegmentSqrDistance(pa,pb,sphereCenter, nearestOnEdge);
if (distanceSqr < contactCapsuleRadiusSqr) {
// Yep, we're inside a capsule
hasContact = true;
contactPoint = nearestOnEdge;
if (l2 >= SIMD_EPSILON*SIMD_EPSILON)
{
normal /= btSqrt(l2);
btVector3 p1ToCentre = sphereCenter - vertices[0];
btScalar distanceFromPlane = p1ToCentre.dot(normal);
if (distanceFromPlane < btScalar(0.))
{
//triangle facing the other way
distanceFromPlane *= btScalar(-1.);
normal *= btScalar(-1.);
}
bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
// Check for contact / intersection
if (isInsideContactPlane) {
if (facecontains(sphereCenter, vertices, normal)) {
// Inside the contact wedge - touches a point on the shell plane
hasContact = true;
contactPoint = sphereCenter - normal*distanceFromPlane;
}
else {
// Could be inside one of the contact capsules
btScalar contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;
btVector3 nearestOnEdge;
for (int i = 0; i < m_triangle->getNumEdges(); i++) {
btVector3 pa;
btVector3 pb;
m_triangle->getEdge(i, pa, pb);
btScalar distanceSqr = SegmentSqrDistance(pa, pb, sphereCenter, nearestOnEdge);
if (distanceSqr < contactCapsuleRadiusSqr) {
// Yep, we're inside a capsule
hasContact = true;
contactPoint = nearestOnEdge;
}
}
}
}
}

View file

@ -24,12 +24,13 @@ class btActivatingCollisionAlgorithm : public btCollisionAlgorithm
// btCollisionObject* m_colObj0;
// btCollisionObject* m_colObj1;
public:
protected:
btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci);
btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
public:
virtual ~btActivatingCollisionAlgorithm();
};

View file

@ -239,10 +239,7 @@ public:
virtual bool processOverlap(btBroadphasePair& pair)
{
BT_PROFILE("btCollisionDispatcher::processOverlap");
(*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
return false;
}
};

View file

@ -0,0 +1,164 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "btCollisionDispatcherMt.h"
#include "LinearMath/btQuickprof.h"
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "LinearMath/btPoolAllocator.h"
#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
btCollisionDispatcherMt::btCollisionDispatcherMt( btCollisionConfiguration* config, int grainSize )
: btCollisionDispatcher( config )
{
m_batchUpdating = false;
m_grainSize = grainSize; // iterations per task
}
btPersistentManifold* btCollisionDispatcherMt::getNewManifold( const btCollisionObject* body0, const btCollisionObject* body1 )
{
//optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
btScalar contactBreakingThreshold = ( m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD ) ?
btMin( body0->getCollisionShape()->getContactBreakingThreshold( gContactBreakingThreshold ), body1->getCollisionShape()->getContactBreakingThreshold( gContactBreakingThreshold ) )
: gContactBreakingThreshold;
btScalar contactProcessingThreshold = btMin( body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold() );
void* mem = m_persistentManifoldPoolAllocator->allocate( sizeof( btPersistentManifold ) );
if ( NULL == mem )
{
//we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
if ( ( m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION ) == 0 )
{
mem = btAlignedAlloc( sizeof( btPersistentManifold ), 16 );
}
else
{
btAssert( 0 );
//make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
return 0;
}
}
btPersistentManifold* manifold = new( mem ) btPersistentManifold( body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold );
if ( !m_batchUpdating )
{
// batch updater will update manifold pointers array after finishing, so
// only need to update array when not batch-updating
//btAssert( !btThreadsAreRunning() );
manifold->m_index1a = m_manifoldsPtr.size();
m_manifoldsPtr.push_back( manifold );
}
return manifold;
}
void btCollisionDispatcherMt::releaseManifold( btPersistentManifold* manifold )
{
clearManifold( manifold );
//btAssert( !btThreadsAreRunning() );
if ( !m_batchUpdating )
{
// batch updater will update manifold pointers array after finishing, so
// only need to update array when not batch-updating
int findIndex = manifold->m_index1a;
btAssert( findIndex < m_manifoldsPtr.size() );
m_manifoldsPtr.swap( findIndex, m_manifoldsPtr.size() - 1 );
m_manifoldsPtr[ findIndex ]->m_index1a = findIndex;
m_manifoldsPtr.pop_back();
}
manifold->~btPersistentManifold();
if ( m_persistentManifoldPoolAllocator->validPtr( manifold ) )
{
m_persistentManifoldPoolAllocator->freeMemory( manifold );
}
else
{
btAlignedFree( manifold );
}
}
struct CollisionDispatcherUpdater : public btIParallelForBody
{
btBroadphasePair* mPairArray;
btNearCallback mCallback;
btCollisionDispatcher* mDispatcher;
const btDispatcherInfo* mInfo;
CollisionDispatcherUpdater()
{
mPairArray = NULL;
mCallback = NULL;
mDispatcher = NULL;
mInfo = NULL;
}
void forLoop( int iBegin, int iEnd ) const
{
for ( int i = iBegin; i < iEnd; ++i )
{
btBroadphasePair* pair = &mPairArray[ i ];
mCallback( *pair, *mDispatcher, *mInfo );
}
}
};
void btCollisionDispatcherMt::dispatchAllCollisionPairs( btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher )
{
int pairCount = pairCache->getNumOverlappingPairs();
if ( pairCount == 0 )
{
return;
}
CollisionDispatcherUpdater updater;
updater.mCallback = getNearCallback();
updater.mPairArray = pairCache->getOverlappingPairArrayPtr();
updater.mDispatcher = this;
updater.mInfo = &info;
m_batchUpdating = true;
btParallelFor( 0, pairCount, m_grainSize, updater );
m_batchUpdating = false;
// reconstruct the manifolds array to ensure determinism
m_manifoldsPtr.resizeNoInitialize( 0 );
btBroadphasePair* pairs = pairCache->getOverlappingPairArrayPtr();
for ( int i = 0; i < pairCount; ++i )
{
if (btCollisionAlgorithm* algo = pairs[ i ].m_algorithm)
{
algo->getAllContactManifolds( m_manifoldsPtr );
}
}
// update the indices (used when releasing manifolds)
for ( int i = 0; i < m_manifoldsPtr.size(); ++i )
{
m_manifoldsPtr[ i ]->m_index1a = i;
}
}

View file

@ -0,0 +1,39 @@
/*
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_COLLISION_DISPATCHER_MT_H
#define BT_COLLISION_DISPATCHER_MT_H
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "LinearMath/btThreads.h"
class btCollisionDispatcherMt : public btCollisionDispatcher
{
public:
btCollisionDispatcherMt( btCollisionConfiguration* config, int grainSize = 40 );
virtual btPersistentManifold* getNewManifold( const btCollisionObject* body0, const btCollisionObject* body1 ) BT_OVERRIDE;
virtual void releaseManifold( btPersistentManifold* manifold ) BT_OVERRIDE;
virtual void dispatchAllCollisionPairs( btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher ) BT_OVERRIDE;
protected:
bool m_batchUpdating;
int m_grainSize;
};
#endif //BT_COLLISION_DISPATCHER_MT_H

View file

@ -18,9 +18,11 @@ subject to the following restrictions:
#include "LinearMath/btSerializer.h"
btCollisionObject::btCollisionObject()
: m_anisotropicFriction(1.f,1.f,1.f),
m_hasAnisotropicFriction(false),
m_contactProcessingThreshold(BT_LARGE_FLOAT),
: m_interpolationLinearVelocity(0.f, 0.f, 0.f),
m_interpolationAngularVelocity(0.f, 0.f, 0.f),
m_anisotropicFriction(1.f,1.f,1.f),
m_hasAnisotropicFriction(false),
m_contactProcessingThreshold(BT_LARGE_FLOAT),
m_broadphaseHandle(0),
m_collisionShape(0),
m_extensionPointer(0),
@ -48,6 +50,7 @@ btCollisionObject::btCollisionObject()
m_updateRevision(0)
{
m_worldTransform.setIdentity();
m_interpolationWorldTransform.setIdentity();
}
btCollisionObject::~btCollisionObject()
@ -112,6 +115,9 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
dataOut->m_checkCollideWith = m_checkCollideWith;
// Fill padding with zeros to appease msan.
memset(dataOut->m_padding, 0, sizeof(dataOut->m_padding));
return btCollisionObjectDataName;
}

View file

@ -139,6 +139,8 @@ public:
CF_DISABLE_SPU_COLLISION_PROCESSING = 64,//disable parallel/SPU processing
CF_HAS_CONTACT_STIFFNESS_DAMPING = 128,
CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR = 256,
CF_HAS_FRICTION_ANCHOR = 512,
CF_HAS_COLLISION_SOUND_TRIGGER = 1024
};
enum CollisionObjectTypes

View file

@ -108,7 +108,7 @@ btCollisionWorld::~btCollisionWorld()
void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask)
void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
{
btAssert(collisionObject);
@ -135,8 +135,7 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho
collisionObject,
collisionFilterGroup,
collisionFilterMask,
m_dispatcher1,0
)) ;
m_dispatcher1)) ;
@ -257,7 +256,7 @@ void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
int iObj = collisionObject->getWorldArrayIndex();
btAssert(iObj >= 0 && iObj < m_collisionObjects.size()); // trying to remove an object that was never added or already removed previously?
// btAssert(iObj >= 0 && iObj < m_collisionObjects.size()); // trying to remove an object that was never added or already removed previously?
if (iObj >= 0 && iObj < m_collisionObjects.size())
{
btAssert(collisionObject == m_collisionObjects[iObj]);
@ -1334,7 +1333,7 @@ void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const
// Draw a small simplex at the center of the object
if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawFrames)
{
getDebugDrawer()->drawTransform(worldTransform,1);
getDebugDrawer()->drawTransform(worldTransform,.1);
}
if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
@ -1515,6 +1514,8 @@ void btCollisionWorld::debugDrawWorld()
{
if (getDebugDrawer())
{
getDebugDrawer()->clearLines();
btIDebugDraw::DefaultColors defaultColors = getDebugDrawer()->getDefaultColors();
if ( getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)

View file

@ -205,8 +205,8 @@ public:
{
btScalar m_closestHitFraction;
const btCollisionObject* m_collisionObject;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
int m_collisionFilterGroup;
int m_collisionFilterMask;
//@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback.h. Apply any of the EFlags defined there on m_flags here to invoke.
unsigned int m_flags;
@ -340,8 +340,8 @@ public:
struct ConvexResultCallback
{
btScalar m_closestHitFraction;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
int m_collisionFilterGroup;
int m_collisionFilterMask;
ConvexResultCallback()
:m_closestHitFraction(btScalar(1.)),
@ -410,8 +410,8 @@ public:
///ContactResultCallback is used to report contact points
struct ContactResultCallback
{
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
int m_collisionFilterGroup;
int m_collisionFilterMask;
btScalar m_closestDistanceThreshold;
ContactResultCallback()
@ -483,7 +483,7 @@ public:
const btCollisionObjectWrapper* colObjWrap,
ConvexResultCallback& resultCallback, btScalar allowedPenetration);
virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter);
virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter);
btCollisionObjectArray& getCollisionObjectArray()
{

View file

@ -579,13 +579,13 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionS
btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData;
btCompoundShape* compoundShape = createCompoundShape();
btCompoundShapeChildData* childShapeDataArray = &compoundData->m_childShapePtr[0];
//btCompoundShapeChildData* childShapeDataArray = &compoundData->m_childShapePtr[0];
btAlignedObjectArray<btCollisionShape*> childShapes;
for (int i=0;i<compoundData->m_numChildShapes;i++)
{
btCompoundShapeChildData* ptr = &compoundData->m_childShapePtr[i];
//btCompoundShapeChildData* ptr = &compoundData->m_childShapePtr[i];
btCollisionShapeData* cd = compoundData->m_childShapePtr[i].m_childShape;

View file

@ -124,7 +124,6 @@ public:
btCollisionShape* getCollisionShapeByIndex(int index);
int getNumRigidBodies() const;
btCollisionObject* getRigidBodyByIndex(int index) const;
int getNumConstraints() const;
int getNumBvhs() const;
btOptimizedBvh* getBvhByIndex(int index) const;

View file

@ -24,6 +24,8 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
//USE_LOCAL_STACK will avoid most (often all) dynamic memory allocations due to resizing in processCollision and MycollideTT
#define USE_LOCAL_STACK 1
btShapePairCallback gCompoundCompoundChildShapePairCallback = 0;
@ -251,7 +253,12 @@ static inline void MycollideTT( const btDbvtNode* root0,
int depth=1;
int treshold=btDbvt::DOUBLE_STACKSIZE-4;
btAlignedObjectArray<btDbvt::sStkNN> stkStack;
#ifdef USE_LOCAL_STACK
ATTRIBUTE_ALIGNED16(btDbvt::sStkNN localStack[btDbvt::DOUBLE_STACKSIZE]);
stkStack.initializeFromBuffer(&localStack,btDbvt::DOUBLE_STACKSIZE,btDbvt::DOUBLE_STACKSIZE);
#else
stkStack.resize(btDbvt::DOUBLE_STACKSIZE);
#endif
stkStack[0]=btDbvt::sStkNN(root0,root1);
do {
btDbvt::sStkNN p=stkStack[--depth];
@ -329,6 +336,10 @@ void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionOb
{
int i;
btManifoldArray manifoldArray;
#ifdef USE_LOCAL_STACK
btPersistentManifold localManifolds[4];
manifoldArray.initializeFromBuffer(&localManifolds,0,4);
#endif
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
for (i=0;i<pairs.size();i++)
{

View file

@ -33,8 +33,6 @@ class btDispatcher;
class btCollisionObject;
class btCollisionShape;
typedef bool (*btShapePairCallback)(const btCollisionShape* pShape0, const btCollisionShape* pShape1);
extern btShapePairCallback gCompoundCompoundChildShapePairCallback;
/// btCompoundCompoundCollisionAlgorithm supports collision between two btCompoundCollisionShape shapes
class btCompoundCompoundCollisionAlgorithm : public btCompoundCollisionAlgorithm

View file

@ -30,8 +30,8 @@ subject to the following restrictions:
btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_isSwapped(isSwapped),
m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped)
m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped),
m_isSwapped(isSwapped)
{
}

View file

@ -16,7 +16,7 @@ subject to the following restrictions:
///Specialized capsule-capsule collision algorithm has been added for Bullet 2.75 release to increase ragdoll performance
///If you experience problems with capsule-capsule collision, try to define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER and report it in the Bullet forums
///with reproduction case
//define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1
//#define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1
//#define ZERO_MARGIN
#include "btConvexConvexAlgorithm.h"
@ -310,10 +310,10 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper*
#ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
{
//m_manifoldPtr->clearManifold();
btCapsuleShape* capsuleA = (btCapsuleShape*) min0;
btCapsuleShape* capsuleB = (btCapsuleShape*) min1;
// btVector3 localScalingA = capsuleA->getLocalScaling();
// btVector3 localScalingB = capsuleB->getLocalScaling();
btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
@ -329,6 +329,50 @@ void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper*
resultOut->refreshContactPoints();
return;
}
if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == SPHERE_SHAPE_PROXYTYPE))
{
//m_manifoldPtr->clearManifold();
btCapsuleShape* capsuleA = (btCapsuleShape*) min0;
btSphereShape* capsuleB = (btSphereShape*) min1;
btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(),
0.,capsuleB->getRadius(),capsuleA->getUpAxis(),1,
body0Wrap->getWorldTransform(),body1Wrap->getWorldTransform(),threshold);
if (dist<threshold)
{
btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);
}
resultOut->refreshContactPoints();
return;
}
if ((min0->getShapeType() == SPHERE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
{
//m_manifoldPtr->clearManifold();
btSphereShape* capsuleA = (btSphereShape*) min0;
btCapsuleShape* capsuleB = (btCapsuleShape*) min1;
btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,0.,capsuleA->getRadius(),
capsuleB->getHalfHeight(),capsuleB->getRadius(),1,capsuleB->getUpAxis(),
body0Wrap->getWorldTransform(),body1Wrap->getWorldTransform(),threshold);
if (dist<threshold)
{
btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);
}
resultOut->refreshContactPoints();
return;
}
#endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER

View file

@ -123,9 +123,9 @@ private:
SIMD_FORCE_INLINE unsigned int getHash(unsigned int indexA, unsigned int indexB)
SIMD_FORCE_INLINE unsigned int getHash(unsigned int indexA, unsigned int indexB)
{
int key = static_cast<int>(((unsigned int)indexA) | (((unsigned int)indexB) <<16));
unsigned int key = indexA | (indexB << 16);
// Thomas Wang's hash
key += ~(key << 15);
@ -134,7 +134,7 @@ private:
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return static_cast<unsigned int>(key);
return key;
}

View file

@ -111,6 +111,7 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
return;
bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
bool isNewCollision = m_manifoldPtr->getNumContacts() == 0;
btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
@ -145,7 +146,13 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
newPt.m_combinedContactStiffness1 = calculateCombinedContactStiffness(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
newPt.m_contactPointFlags |= BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING;
}
if ( (m_body0Wrap->getCollisionObject()->getCollisionFlags()& btCollisionObject::CF_HAS_FRICTION_ANCHOR) ||
(m_body1Wrap->getCollisionObject()->getCollisionFlags()& btCollisionObject::CF_HAS_FRICTION_ANCHOR))
{
newPt.m_contactPointFlags |= BT_CONTACT_FLAG_FRICTION_ANCHOR;
}
btPlaneSpace1(newPt.m_normalWorldOnB,newPt.m_lateralFrictionDir1,newPt.m_lateralFrictionDir2);
@ -187,5 +194,9 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
(*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1);
}
if (gContactStartedCallback && isNewCollision)
{
gContactStartedCallback(m_manifoldPtr);
}
}

View file

@ -103,11 +103,12 @@ public:
btScalar minDimension = boxHalfExtents.getX();
if (minDimension>boxHalfExtents.getY())
minDimension = boxHalfExtents.getY();
setSafeMargin(minDimension);
m_shapeType = BOX_2D_SHAPE_PROXYTYPE;
btVector3 margin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
setSafeMargin(minDimension);
};
virtual void setMargin(btScalar collisionMargin)

View file

@ -19,10 +19,10 @@ btBoxShape::btBoxShape( const btVector3& boxHalfExtents)
{
m_shapeType = BOX_SHAPE_PROXYTYPE;
setSafeMargin(boxHalfExtents);
btVector3 margin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
setSafeMargin(boxHalfExtents);
};

View file

@ -437,6 +437,9 @@ const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* se
trimeshData->m_triangleInfoMap = 0;
}
// Fill padding with zeros to appease msan.
memset(trimeshData->m_pad3, 0, sizeof(trimeshData->m_pad3));
return "btTriangleMeshShapeData";
}

View file

@ -16,11 +16,11 @@ subject to the following restrictions:
#include "btCapsuleShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
#include "LinearMath/btQuaternion.h"
btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape ()
{
m_collisionMargin = radius;
m_shapeType = CAPSULE_SHAPE_PROXYTYPE;
m_upAxis = 1;
m_implicitShapeDimensions.setValue(radius,0.5f*height,radius);
@ -48,14 +48,13 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter
btVector3 vtx;
btScalar newDot;
btScalar radius = getRadius();
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = getHalfHeight();
vtx = pos +vec*(radius) - vec * getMargin();
vtx = pos;
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
@ -67,7 +66,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter
btVector3 pos(0,0,0);
pos[getUpAxis()] = -getHalfHeight();
vtx = pos +vec*(radius) - vec * getMargin();
vtx = pos;
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
@ -84,8 +83,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter
{
btScalar radius = getRadius();
for (int j=0;j<numVectors;j++)
{
btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
@ -96,7 +94,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = getHalfHeight();
vtx = pos +vec*(radius) - vec * getMargin();
vtx = pos;
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
@ -107,7 +105,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInter
{
btVector3 pos(0,0,0);
pos[getUpAxis()] = -getHalfHeight();
vtx = pos +vec*(radius) - vec * getMargin();
vtx = pos;
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
@ -133,11 +131,9 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) con
btVector3 halfExtents(radius,radius,radius);
halfExtents[getUpAxis()]+=getHalfHeight();
btScalar margin = CONVEX_DISTANCE_MARGIN;
btScalar lx=btScalar(2.)*(halfExtents[0]+margin);
btScalar ly=btScalar(2.)*(halfExtents[1]+margin);
btScalar lz=btScalar(2.)*(halfExtents[2]+margin);
btScalar lx=btScalar(2.)*(halfExtents[0]);
btScalar ly=btScalar(2.)*(halfExtents[1]);
btScalar lz=btScalar(2.)*(halfExtents[2]);
const btScalar x2 = lx*lx;
const btScalar y2 = ly*ly;
const btScalar z2 = lz*lz;
@ -151,6 +147,7 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) con
btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height)
{
m_collisionMargin = radius;
m_upAxis = 0;
m_implicitShapeDimensions.setValue(0.5f*height, radius,radius);
}
@ -162,6 +159,7 @@ btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height)
btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height)
{
m_collisionMargin = radius;
m_upAxis = 2;
m_implicitShapeDimensions.setValue(radius,radius,0.5f*height);
}

View file

@ -48,21 +48,13 @@ public:
virtual void setMargin(btScalar collisionMargin)
{
//correct the m_implicitShapeDimensions for the margin
btVector3 oldMargin(getMargin(),getMargin(),getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
btConvexInternalShape::setMargin(collisionMargin);
btVector3 newMargin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
//don't override the margin for capsules, their entire radius == margin
}
virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
btVector3 halfExtents(getRadius(),getRadius(),getRadius());
halfExtents[m_upAxis] = getRadius() + getHalfHeight();
halfExtents += btVector3(getMargin(),getMargin(),getMargin());
btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
@ -94,14 +86,12 @@ public:
virtual void setLocalScaling(const btVector3& scaling)
{
btVector3 oldMargin(getMargin(),getMargin(),getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
btConvexInternalShape::setLocalScaling(scaling);
m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
btVector3 unScaledImplicitShapeDimensions = m_implicitShapeDimensions / m_localScaling;
btConvexInternalShape::setLocalScaling(scaling);
m_implicitShapeDimensions = (unScaledImplicitShapeDimensions * scaling);
//update m_collisionMargin, since entire radius==margin
int radiusAxis = (m_upAxis+2)%3;
m_collisionMargin = m_implicitShapeDimensions[radiusAxis];
}
virtual btVector3 getAnisotropicRollingFrictionDirection() const
@ -174,11 +164,17 @@ SIMD_FORCE_INLINE int btCapsuleShape::calculateSerializeBufferSize() const
SIMD_FORCE_INLINE const char* btCapsuleShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
btCapsuleShapeData* shapeData = (btCapsuleShapeData*) dataBuffer;
btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
shapeData->m_upAxis = m_upAxis;
// Fill padding with zeros to appease msan.
shapeData->m_padding[0] = 0;
shapeData->m_padding[1] = 0;
shapeData->m_padding[2] = 0;
shapeData->m_padding[3] = 0;
return "btCapsuleShapeData";
}

View file

@ -106,7 +106,10 @@ const char* btCollisionShape::serialize(void* dataBuffer, btSerializer* serializ
serializer->serializeName(name);
}
shapeData->m_shapeType = m_shapeType;
//shapeData->m_padding//??
// Fill padding with zeros to appease msan.
memset(shapeData->m_padding, 0, sizeof(shapeData->m_padding));
return "btCollisionShapeData";
}

View file

@ -168,11 +168,17 @@ SIMD_FORCE_INLINE int btConeShape::calculateSerializeBufferSize() const
SIMD_FORCE_INLINE const char* btConeShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
btConeShapeData* shapeData = (btConeShapeData*) dataBuffer;
btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
shapeData->m_upIndex = m_coneIndices[1];
// Fill padding with zeros to appease msan.
shapeData->m_padding[0] = 0;
shapeData->m_padding[1] = 0;
shapeData->m_padding[2] = 0;
shapeData->m_padding[3] = 0;
return "btConeShapeData";
}

View file

@ -211,7 +211,10 @@ const char* btConvexHullShape::serialize(void* dataBuffer, btSerializer* seriali
}
serializer->finalizeChunk(chunk,btVector3DataName,BT_ARRAY_CODE,(void*)&m_unscaledPoints[0]);
}
// Fill padding with zeros to appease msan.
memset(shapeData->m_padding3, 0, sizeof(shapeData->m_padding3));
return "btConvexHullShapeData";
}

View file

@ -172,6 +172,9 @@ SIMD_FORCE_INLINE const char* btConvexInternalShape::serialize(void* dataBuffer,
m_localScaling.serializeFloat(shapeData->m_localScaling);
shapeData->m_collisionMargin = float(m_collisionMargin);
// Fill padding with zeros to appease msan.
shapeData->m_padding = 0;
return "btConvexInternalShapeData";
}

View file

@ -230,14 +230,13 @@ btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btV
btScalar halfHeight = capsuleShape->getHalfHeight();
int capsuleUpAxis = capsuleShape->getUpAxis();
btScalar radius = capsuleShape->getRadius();
btVector3 supVec(0,0,0);
btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
btVector3 vec = vec0;
btScalar lenSqr = vec.length2();
if (lenSqr < btScalar(0.0001))
if (lenSqr < SIMD_EPSILON*SIMD_EPSILON)
{
vec.setValue(1,0,0);
} else
@ -251,8 +250,7 @@ btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btV
btVector3 pos(0,0,0);
pos[capsuleUpAxis] = halfHeight;
//vtx = pos +vec*(radius);
vtx = pos +vec*(radius) - vec * capsuleShape->getMarginNV();
vtx = pos;
newDot = vec.dot(vtx);
@ -266,8 +264,7 @@ btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btV
btVector3 pos(0,0,0);
pos[capsuleUpAxis] = -halfHeight;
//vtx = pos +vec*(radius);
vtx = pos +vec*(radius) - vec * capsuleShape->getMarginNV();
vtx = pos;
newDot = vec.dot(vtx);
if (newDot > maxDot)
{
@ -427,7 +424,6 @@ void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin,
btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius());
int m_upAxis = capsuleShape->getUpAxis();
halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight();
halfExtents += btVector3(capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual());
btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);

View file

@ -19,10 +19,11 @@ btCylinderShape::btCylinderShape (const btVector3& halfExtents)
:btConvexInternalShape(),
m_upAxis(1)
{
setSafeMargin(halfExtents);
btVector3 margin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = (halfExtents * m_localScaling) - margin;
setSafeMargin(halfExtents);
m_shapeType = CYLINDER_SHAPE_PROXYTYPE;
}

View file

@ -199,11 +199,17 @@ SIMD_FORCE_INLINE int btCylinderShape::calculateSerializeBufferSize() const
SIMD_FORCE_INLINE const char* btCylinderShape::serialize(void* dataBuffer, btSerializer* serializer) const
{
btCylinderShapeData* shapeData = (btCylinderShapeData*) dataBuffer;
btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
shapeData->m_upAxis = m_upAxis;
// Fill padding with zeros to appease msan.
shapeData->m_padding[0] = 0;
shapeData->m_padding[1] = 0;
shapeData->m_padding[2] = 0;
shapeData->m_padding[3] = 0;
return "btCylinderShapeData";
}

View file

@ -55,6 +55,23 @@ btScalar btMinkowskiSumShape::getMargin() const
void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
(void)mass;
btAssert(0);
inertia.setValue(0,0,0);
//inertia of the AABB of the Minkowski sum
btTransform identity;
identity.setIdentity();
btVector3 aabbMin,aabbMax;
getAabb(identity,aabbMin,aabbMax);
btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
btScalar margin = getMargin();
btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
const btScalar x2 = lx*lx;
const btScalar y2 = ly*ly;
const btScalar z2 = lz*lz;
const btScalar scaledmass = mass * btScalar(0.08333333);
inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
}

View file

@ -175,7 +175,10 @@ const char* btMultiSphereShape::serialize(void* dataBuffer, btSerializer* serial
}
serializer->finalizeChunk(chunk,"btPositionAndRadius",BT_ARRAY_CODE,(void*)&m_localPositionArray[0]);
}
// Fill padding with zeros to appease msan.
memset(shapeData->m_padding, 0, sizeof(shapeData->m_padding));
return "btMultiSphereShapeData";
}

View file

@ -93,10 +93,12 @@ protected:
aabbMax = m_localAabbMax;
}
public:
protected:
btPolyhedralConvexAabbCachingShape();
public:
inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const
{

View file

@ -29,8 +29,11 @@ public:
btSphereShape (btScalar radius) : btConvexInternalShape ()
{
m_shapeType = SPHERE_SHAPE_PROXYTYPE;
m_localScaling.setValue(1.0, 1.0, 1.0);
m_implicitShapeDimensions.setZero();
m_implicitShapeDimensions.setX(radius);
m_collisionMargin = radius;
m_padding = 0;
}
virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;

View file

@ -94,7 +94,13 @@ SIMD_FORCE_INLINE const char* btStaticPlaneShape::serialize(void* dataBuffer, bt
m_localScaling.serializeFloat(planeData->m_localScaling);
m_planeNormal.serializeFloat(planeData->m_planeNormal);
planeData->m_planeConstant = float(m_planeConstant);
// Fill padding with zeros to appease msan.
planeData->m_pad[0] = 0;
planeData->m_pad[1] = 0;
planeData->m_pad[2] = 0;
planeData->m_pad[3] = 0;
return "btStaticPlaneShapeData";
}

View file

@ -293,6 +293,9 @@ const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* s
tmpIndices[gfxindex].m_values[0] = tri_indices[0];
tmpIndices[gfxindex].m_values[1] = tri_indices[1];
tmpIndices[gfxindex].m_values[2] = tri_indices[2];
// Fill padding with zeros to appease msan.
tmpIndices[gfxindex].m_pad[0] = 0;
tmpIndices[gfxindex].m_pad[1] = 0;
}
serializer->finalizeChunk(chunk,"btShortIntIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
}
@ -311,6 +314,8 @@ const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* s
tmpIndices[gfxindex].m_values[0] = tri_indices[0];
tmpIndices[gfxindex].m_values[1] = tri_indices[1];
tmpIndices[gfxindex].m_values[2] = tri_indices[2];
// Fill padding with zeros to appease msan.
tmpIndices[gfxindex].m_pad = 0;
}
serializer->finalizeChunk(chunk,"btCharIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
}
@ -375,6 +380,8 @@ const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* s
serializer->finalizeChunk(chunk,"btMeshPartData",BT_ARRAY_CODE,chunk->m_oldPtr);
}
// Fill padding with zeros to appease msan.
memset(trimeshData->m_padding, 0, sizeof(trimeshData->m_padding));
m_scaling.serializeFloat(trimeshData->m_scaling);
return "btStridingMeshInterfaceData";

View file

@ -195,6 +195,13 @@ SIMD_FORCE_INLINE const char* btTriangleInfoMap::serialize(void* dataBuffer, btS
serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*) &m_keyArray[0]);
}
// Fill padding with zeros to appease msan.
tmapData->m_padding[0] = 0;
tmapData->m_padding[1] = 0;
tmapData->m_padding[2] = 0;
tmapData->m_padding[3] = 0;
return "btTriangleInfoMapData";
}

View file

@ -5,6 +5,22 @@
#include "btGImpactShape.h"
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
ATTRIBUTE_ALIGNED16(class) btCompoundFromGimpactShape : public btCompoundShape
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
virtual ~btCompoundFromGimpactShape()
{
/*delete all the btBU_Simplex1to4 ChildShapes*/
for (int i = 0; i < m_children.size(); i++)
{
delete m_children[i].m_childShape;
}
}
};
struct MyCallback : public btTriangleRaycastCallback
{
int m_ignorePart;
@ -77,7 +93,7 @@ struct MyCallback : public btTriangleRaycastCallback
btCompoundShape* btCreateCompoundFromGimpactShape(const btGImpactMeshShape* gimpactMesh, btScalar depth)
{
btCompoundShape* colShape = new btCompoundShape();
btCompoundShape* colShape = new btCompoundFromGimpactShape();
btTransform tr;
tr.setIdentity();
@ -90,4 +106,4 @@ btCompoundShape* btCreateCompoundFromGimpactShape(const btGImpactMeshShape* gimp
return colShape;
}
#endif //BT_COMPOUND_FROM_GIMPACT
#endif //BT_COMPOUND_FROM_GIMPACT

View file

@ -27,86 +27,7 @@ subject to the following restrictions:
#include "LinearMath/btTransform.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "btTriangleShapeEx.h"
/**
Configuration var for applying interpolation of contact normals
*/
#define NORMAL_CONTACT_AVERAGE 1
#define CONTACT_DIFF_EPSILON 0.00001f
///The GIM_CONTACT is an internal GIMPACT structure, similar to btManifoldPoint.
///@todo: remove and replace GIM_CONTACT by btManifoldPoint.
class GIM_CONTACT
{
public:
btVector3 m_point;
btVector3 m_normal;
btScalar m_depth;//Positive value indicates interpenetration
btScalar m_distance;//Padding not for use
int m_feature1;//Face number
int m_feature2;//Face number
public:
GIM_CONTACT()
{
}
GIM_CONTACT(const GIM_CONTACT & contact):
m_point(contact.m_point),
m_normal(contact.m_normal),
m_depth(contact.m_depth),
m_feature1(contact.m_feature1),
m_feature2(contact.m_feature2)
{
}
GIM_CONTACT(const btVector3 &point,const btVector3 & normal,
btScalar depth, int feature1, int feature2):
m_point(point),
m_normal(normal),
m_depth(depth),
m_feature1(feature1),
m_feature2(feature2)
{
}
//! Calcs key for coord classification
SIMD_FORCE_INLINE unsigned int calc_key_contact() const
{
int _coords[] = {
(int)(m_point[0]*1000.0f+1.0f),
(int)(m_point[1]*1333.0f),
(int)(m_point[2]*2133.0f+3.0f)};
unsigned int _hash=0;
unsigned int *_uitmp = (unsigned int *)(&_coords[0]);
_hash = *_uitmp;
_uitmp++;
_hash += (*_uitmp)<<4;
_uitmp++;
_hash += (*_uitmp)<<8;
return _hash;
}
SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,int normal_count)
{
btVector3 vec_sum(m_normal);
for(int i=0;i<normal_count;i++)
{
vec_sum += normals[i];
}
btScalar vec_sum_len = vec_sum.length2();
if(vec_sum_len <CONTACT_DIFF_EPSILON) return;
//GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
m_normal = vec_sum/btSqrt(vec_sum_len);
}
};
#include "btContactProcessingStructs.h"
class btContactArray:public btAlignedObjectArray<GIM_CONTACT>
{
@ -141,5 +62,4 @@ public:
void merge_contacts_unique(const btContactArray & contacts);
};
#endif // GIM_CONTACT_H_INCLUDED

View file

@ -0,0 +1,109 @@
#ifndef BT_CONTACT_H_STRUCTS_INCLUDED
#define BT_CONTACT_H_STRUCTS_INCLUDED
/*! \file gim_contact.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.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 "LinearMath/btTransform.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "btTriangleShapeEx.h"
/**
Configuration var for applying interpolation of contact normals
*/
#define NORMAL_CONTACT_AVERAGE 1
#define CONTACT_DIFF_EPSILON 0.00001f
///The GIM_CONTACT is an internal GIMPACT structure, similar to btManifoldPoint.
///@todo: remove and replace GIM_CONTACT by btManifoldPoint.
class GIM_CONTACT
{
public:
btVector3 m_point;
btVector3 m_normal;
btScalar m_depth;//Positive value indicates interpenetration
btScalar m_distance;//Padding not for use
int m_feature1;//Face number
int m_feature2;//Face number
public:
GIM_CONTACT()
{
}
GIM_CONTACT(const GIM_CONTACT & contact):
m_point(contact.m_point),
m_normal(contact.m_normal),
m_depth(contact.m_depth),
m_feature1(contact.m_feature1),
m_feature2(contact.m_feature2)
{
}
GIM_CONTACT(const btVector3 &point,const btVector3 & normal,
btScalar depth, int feature1, int feature2):
m_point(point),
m_normal(normal),
m_depth(depth),
m_feature1(feature1),
m_feature2(feature2)
{
}
//! Calcs key for coord classification
SIMD_FORCE_INLINE unsigned int calc_key_contact() const
{
int _coords[] = {
(int)(m_point[0]*1000.0f+1.0f),
(int)(m_point[1]*1333.0f),
(int)(m_point[2]*2133.0f+3.0f)};
unsigned int _hash=0;
unsigned int *_uitmp = (unsigned int *)(&_coords[0]);
_hash = *_uitmp;
_uitmp++;
_hash += (*_uitmp)<<4;
_uitmp++;
_hash += (*_uitmp)<<8;
return _hash;
}
SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,int normal_count)
{
btVector3 vec_sum(m_normal);
for(int i=0;i<normal_count;i++)
{
vec_sum += normals[i];
}
btScalar vec_sum_len = vec_sum.length2();
if(vec_sum_len <CONTACT_DIFF_EPSILON) return;
//GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
m_normal = vec_sum/btSqrt(vec_sum_len);
}
};
#endif // BT_CONTACT_H_STRUCTS_INCLUDED

View file

@ -29,31 +29,7 @@ subject to the following restrictions:
#include "btBoxCollision.h"
#include "btTriangleShapeEx.h"
//! Overlapping pair
struct GIM_PAIR
{
int m_index1;
int m_index2;
GIM_PAIR()
{}
GIM_PAIR(const GIM_PAIR & p)
{
m_index1 = p.m_index1;
m_index2 = p.m_index2;
}
GIM_PAIR(int index1, int index2)
{
m_index1 = index1;
m_index2 = index2;
}
};
#include "btGImpactBvhStructs.h"
//! A pairset array
class btPairSet: public btAlignedObjectArray<GIM_PAIR>
@ -74,59 +50,6 @@ public:
}
};
///GIM_BVH_DATA is an internal GIMPACT collision structure to contain axis aligned bounding box
struct GIM_BVH_DATA
{
btAABB m_bound;
int m_data;
};
//! Node Structure for trees
class GIM_BVH_TREE_NODE
{
public:
btAABB m_bound;
protected:
int m_escapeIndexOrDataIndex;
public:
GIM_BVH_TREE_NODE()
{
m_escapeIndexOrDataIndex = 0;
}
SIMD_FORCE_INLINE bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
return (m_escapeIndexOrDataIndex>=0);
}
SIMD_FORCE_INLINE int getEscapeIndex() const
{
//btAssert(m_escapeIndexOrDataIndex < 0);
return -m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setEscapeIndex(int index)
{
m_escapeIndexOrDataIndex = -index;
}
SIMD_FORCE_INLINE int getDataIndex() const
{
//btAssert(m_escapeIndexOrDataIndex >= 0);
return m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setDataIndex(int index)
{
m_escapeIndexOrDataIndex = index;
}
};
class GIM_BVH_DATA_ARRAY:public btAlignedObjectArray<GIM_BVH_DATA>
{
};
@ -392,5 +315,4 @@ public:
btPairSet & collision_pairs);
};
#endif // GIM_BOXPRUNING_H_INCLUDED

View file

@ -0,0 +1,105 @@
#ifndef GIM_BOX_SET_STRUCT_H_INCLUDED
#define GIM_BOX_SET_STRUCT_H_INCLUDED
/*! \file gim_box_set.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.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 "LinearMath/btAlignedObjectArray.h"
#include "btBoxCollision.h"
#include "btTriangleShapeEx.h"
//! Overlapping pair
struct GIM_PAIR
{
int m_index1;
int m_index2;
GIM_PAIR()
{}
GIM_PAIR(const GIM_PAIR & p)
{
m_index1 = p.m_index1;
m_index2 = p.m_index2;
}
GIM_PAIR(int index1, int index2)
{
m_index1 = index1;
m_index2 = index2;
}
};
///GIM_BVH_DATA is an internal GIMPACT collision structure to contain axis aligned bounding box
struct GIM_BVH_DATA
{
btAABB m_bound;
int m_data;
};
//! Node Structure for trees
class GIM_BVH_TREE_NODE
{
public:
btAABB m_bound;
protected:
int m_escapeIndexOrDataIndex;
public:
GIM_BVH_TREE_NODE()
{
m_escapeIndexOrDataIndex = 0;
}
SIMD_FORCE_INLINE bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
return (m_escapeIndexOrDataIndex>=0);
}
SIMD_FORCE_INLINE int getEscapeIndex() const
{
//btAssert(m_escapeIndexOrDataIndex < 0);
return -m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setEscapeIndex(int index)
{
m_escapeIndexOrDataIndex = -index;
}
SIMD_FORCE_INLINE int getDataIndex() const
{
//btAssert(m_escapeIndexOrDataIndex >= 0);
return m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setDataIndex(int index)
{
m_escapeIndexOrDataIndex = index;
}
};
#endif // GIM_BOXPRUNING_H_INCLUDED

View file

@ -26,73 +26,7 @@ subject to the following restrictions:
#include "btGImpactBvh.h"
#include "btQuantization.h"
///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
ATTRIBUTE_ALIGNED16 (struct) BT_QUANTIZED_BVH_NODE
{
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes
int m_escapeIndexOrDataIndex;
BT_QUANTIZED_BVH_NODE()
{
m_escapeIndexOrDataIndex = 0;
}
SIMD_FORCE_INLINE bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
return (m_escapeIndexOrDataIndex>=0);
}
SIMD_FORCE_INLINE int getEscapeIndex() const
{
//btAssert(m_escapeIndexOrDataIndex < 0);
return -m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setEscapeIndex(int index)
{
m_escapeIndexOrDataIndex = -index;
}
SIMD_FORCE_INLINE int getDataIndex() const
{
//btAssert(m_escapeIndexOrDataIndex >= 0);
return m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setDataIndex(int index)
{
m_escapeIndexOrDataIndex = index;
}
SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
unsigned short * quantizedMin,unsigned short * quantizedMax) const
{
if(m_quantizedAabbMin[0] > quantizedMax[0] ||
m_quantizedAabbMax[0] < quantizedMin[0] ||
m_quantizedAabbMin[1] > quantizedMax[1] ||
m_quantizedAabbMax[1] < quantizedMin[1] ||
m_quantizedAabbMin[2] > quantizedMax[2] ||
m_quantizedAabbMax[2] < quantizedMin[2])
{
return false;
}
return true;
}
};
#include "btGImpactQuantizedBvhStructs.h"
class GIM_QUANTIZED_BVH_NODE_ARRAY:public btAlignedObjectArray<BT_QUANTIZED_BVH_NODE>
{
@ -368,5 +302,4 @@ public:
btPairSet & collision_pairs);
};
#endif // GIM_BOXPRUNING_H_INCLUDED

View file

@ -0,0 +1,91 @@
#ifndef GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
#define GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
/*! \file btGImpactQuantizedBvh.h
\author Francisco Leon Najera
*/
/*
This source file is part of GIMPACT Library.
For the latest info, see http://gimpact.sourceforge.net/
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
email: projectileman@yahoo.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 "btGImpactBvh.h"
#include "btQuantization.h"
///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
ATTRIBUTE_ALIGNED16 (struct) BT_QUANTIZED_BVH_NODE
{
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes
int m_escapeIndexOrDataIndex;
BT_QUANTIZED_BVH_NODE()
{
m_escapeIndexOrDataIndex = 0;
}
SIMD_FORCE_INLINE bool isLeafNode() const
{
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
return (m_escapeIndexOrDataIndex>=0);
}
SIMD_FORCE_INLINE int getEscapeIndex() const
{
//btAssert(m_escapeIndexOrDataIndex < 0);
return -m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setEscapeIndex(int index)
{
m_escapeIndexOrDataIndex = -index;
}
SIMD_FORCE_INLINE int getDataIndex() const
{
//btAssert(m_escapeIndexOrDataIndex >= 0);
return m_escapeIndexOrDataIndex;
}
SIMD_FORCE_INLINE void setDataIndex(int index)
{
m_escapeIndexOrDataIndex = index;
}
SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
unsigned short * quantizedMin,unsigned short * quantizedMax) const
{
if(m_quantizedAabbMin[0] > quantizedMax[0] ||
m_quantizedAabbMax[0] < quantizedMin[0] ||
m_quantizedAabbMin[1] > quantizedMax[1] ||
m_quantizedAabbMax[1] < quantizedMin[1] ||
m_quantizedAabbMin[2] > quantizedMax[2] ||
m_quantizedAabbMax[2] < quantizedMin[2])
{
return false;
}
return true;
}
};
#endif // GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED

View file

@ -228,7 +228,7 @@ public:
inline void push_back_memcpy(const T & obj)
{
this->growingCheck();
irr_simd_memcpy(&m_data[m_size],&obj,sizeof(T));
gim_simd_memcpy(&m_data[m_size],&obj,sizeof(T));
m_size++;
}

View file

@ -41,10 +41,13 @@ email: projectileman@yahoo.com
#ifndef PLANEDIREPSILON
#define PLANEDIREPSILON 0.0000001f
#define PARALELENORMALS 0.000001f
#endif
#ifndef PARALELENORMALS
#define PARALELENORMALS 0.000001f
#endif
#define TRIANGLE_NORMAL(v1,v2,v3,n)\
{\

View file

@ -97,6 +97,8 @@ email: projectileman@yahoo.com
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
//}
#ifndef TEST_CROSS_EDGE_BOX_MCR
#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
{\
const btScalar dir0 = -edge[i_dir_0];\
@ -113,6 +115,7 @@ email: projectileman@yahoo.com
if(pmin>rad || -rad>pmax) return false;\
}\
#endif
#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
{\
@ -190,8 +193,9 @@ public:
}
};
#ifndef BOX_PLANE_EPSILON
#define BOX_PLANE_EPSILON 0.000001f
#endif
//! Axis aligned box
class GIM_AABB
@ -571,7 +575,7 @@ public:
}
};
#ifndef BT_BOX_COLLISION_H_INCLUDED
//! Compairison of transformation objects
SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
{
@ -582,6 +586,7 @@ SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btT
if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
return true;
}
#endif

View file

@ -40,8 +40,15 @@ email: projectileman@yahoo.com
/**
Configuration var for applying interpolation of contact normals
*/
#ifndef NORMAL_CONTACT_AVERAGE
#define NORMAL_CONTACT_AVERAGE 1
#endif
#ifndef CONTACT_DIFF_EPSILON
#define CONTACT_DIFF_EPSILON 0.00001f
#endif
#ifndef BT_CONTACT_H_STRUCTS_INCLUDED
/// Structure for collision results
///Functions for managing and sorting contacts resulting from a collision query.
@ -121,6 +128,7 @@ public:
};
#endif
class gim_contact_array:public gim_array<GIM_CONTACT>
{

View file

@ -38,8 +38,9 @@ email: projectileman@yahoo.com
#ifndef MAX_TRI_CLIPPING
#define MAX_TRI_CLIPPING 16
#endif
//! Structure for collision
struct GIM_TRIANGLE_CONTACT_DATA

View file

@ -67,10 +67,12 @@ struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result
btVector3 m_closestPointInB;
btScalar m_distance; //negative means penetration !
protected:
btStorageResult() : m_distance(btScalar(BT_LARGE_FLOAT))
{
}
public:
virtual ~btStorageResult() {};
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)

View file

@ -41,6 +41,7 @@ enum btContactPointFlags
BT_CONTACT_FLAG_HAS_CONTACT_CFM=2,
BT_CONTACT_FLAG_HAS_CONTACT_ERP=4,
BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING = 8,
BT_CONTACT_FLAG_FRICTION_ANCHOR = 16,
};
/// ManifoldContactPoint collects and maintains persistent contactpoints.

View file

@ -21,6 +21,8 @@ subject to the following restrictions:
btScalar gContactBreakingThreshold = btScalar(0.02);
ContactDestroyedCallback gContactDestroyedCallback = 0;
ContactProcessedCallback gContactProcessedCallback = 0;
ContactStartedCallback gContactStartedCallback = 0;
ContactEndedCallback gContactEndedCallback = 0;
///gContactCalcArea3Points will approximate the convex hull area using 3 points
///when setting it to false, it will use 4 points to compute the area: it is more accurate but slower
bool gContactCalcArea3Points = true;
@ -279,6 +281,7 @@ void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btT
removeContactPoint(i);
} else
{
//todo: friction anchor may require the contact to be around a bit longer
//contact also becomes invalid when relative movement orthogonal to normal exceeds margin
projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;

View file

@ -28,10 +28,18 @@ struct btCollisionResult;
///maximum contact breaking and merging threshold
extern btScalar gContactBreakingThreshold;
#ifndef SWIG
class btPersistentManifold;
typedef bool (*ContactDestroyedCallback)(void* userPersistentData);
typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1);
typedef void (*ContactStartedCallback)(btPersistentManifold* const &manifold);
typedef void (*ContactEndedCallback)(btPersistentManifold* const &manifold);
extern ContactDestroyedCallback gContactDestroyedCallback;
extern ContactProcessedCallback gContactProcessedCallback;
extern ContactStartedCallback gContactStartedCallback;
extern ContactEndedCallback gContactEndedCallback;
#endif //SWIG
//the enum starts at 1024 to avoid type conflicts with btTypedConstraint
enum btContactManifoldTypes
@ -51,8 +59,8 @@ enum btContactManifoldTypes
///note that some pairs of objects might have more then one contact manifold.
ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject
//ATTRIBUTE_ALIGNED16( class) btPersistentManifold : public btTypedObject
//ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject
ATTRIBUTE_ALIGNED16( class) btPersistentManifold : public btTypedObject
{
btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE];
@ -171,40 +179,60 @@ public:
btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0);
m_cachedPoints--;
if (gContactEndedCallback && m_cachedPoints == 0)
{
gContactEndedCallback(this);
}
}
void replaceContactPoint(const btManifoldPoint& newPoint,int insertIndex)
void replaceContactPoint(const btManifoldPoint& newPoint, int insertIndex)
{
btAssert(validContactDistance(newPoint));
#define MAINTAIN_PERSISTENCY 1
#ifdef MAINTAIN_PERSISTENCY
int lifeTime = m_pointCache[insertIndex].getLifeTime();
btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse;
btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1;
btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2;
// bool isLateralFrictionInitialized = m_pointCache[insertIndex].m_lateralFrictionInitialized;
btAssert(lifeTime>=0);
void* cache = m_pointCache[insertIndex].m_userPersistentData;
m_pointCache[insertIndex] = newPoint;
m_pointCache[insertIndex].m_userPersistentData = cache;
m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse;
m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
int lifeTime = m_pointCache[insertIndex].getLifeTime();
btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse;
btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1;
btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2;
bool replacePoint = true;
///we keep existing contact points for friction anchors
///if the friction force is within the Coulomb friction cone
if (newPoint.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
{
// printf("appliedImpulse=%f\n", appliedImpulse);
// printf("appliedLateralImpulse1=%f\n", appliedLateralImpulse1);
// printf("appliedLateralImpulse2=%f\n", appliedLateralImpulse2);
// printf("mu = %f\n", m_pointCache[insertIndex].m_combinedFriction);
btScalar mu = m_pointCache[insertIndex].m_combinedFriction;
btScalar eps = 0; //we could allow to enlarge or shrink the tolerance to check against the friction cone a bit, say 1e-7
btScalar a = appliedLateralImpulse1 * appliedLateralImpulse1 + appliedLateralImpulse2 * appliedLateralImpulse2;
btScalar b = eps + mu * appliedImpulse;
b = b * b;
replacePoint = (a) > (b);
}
if (replacePoint)
{
btAssert(lifeTime >= 0);
void* cache = m_pointCache[insertIndex].m_userPersistentData;
m_pointCache[insertIndex] = newPoint;
m_pointCache[insertIndex].m_userPersistentData = cache;
m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse;
m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
}
m_pointCache[insertIndex].m_lifeTime = lifeTime;
#else
clearUserCache(m_pointCache[insertIndex]);
m_pointCache[insertIndex] = newPoint;
#endif
}
bool validContactDistance(const btManifoldPoint& pt) const
{
return pt.m_distance1 <= getContactBreakingThreshold();
@ -220,6 +248,11 @@ public:
{
clearUserCache(m_pointCache[i]);
}
if (gContactEndedCallback && m_cachedPoints)
{
gContactEndedCallback(this);
}
m_cachedPoints = 0;
}

View file

@ -37,6 +37,7 @@ SET(BulletDynamics_SRCS
Featherstone/btMultiBodyFixedConstraint.cpp
Featherstone/btMultiBodySliderConstraint.cpp
Featherstone/btMultiBodyJointMotor.cpp
Featherstone/btMultiBodyGearConstraint.cpp
MLCPSolvers/btDantzigLCP.cpp
MLCPSolvers/btMLCPSolver.cpp
MLCPSolvers/btLemkeAlgorithm.cpp
@ -98,6 +99,7 @@ SET(Featherstone_HDRS
Featherstone/btMultiBodyFixedConstraint.h
Featherstone/btMultiBodySliderConstraint.h
Featherstone/btMultiBodyJointMotor.h
Featherstone/btMultiBodyGearConstraint.h
)
SET(MLCPSolvers_HDRS

View file

@ -137,8 +137,6 @@ btKinematicCharacterController::btKinematicCharacterController (btPairCachingGho
m_ghostObject = ghostObject;
m_up.setValue(0.0f, 0.0f, 1.0f);
m_jumpAxis.setValue(0.0f, 0.0f, 1.0f);
setUp(up);
setStepHeight(stepHeight);
m_addedMargin = 0.02;
m_walkDirection.setValue(0.0,0.0,0.0);
m_AngVel.setValue(0.0, 0.0, 0.0);
@ -156,13 +154,16 @@ btKinematicCharacterController::btKinematicCharacterController (btPairCachingGho
m_wasOnGround = false;
m_wasJumping = false;
m_interpolateUp = true;
setMaxSlope(btRadians(45.0));
m_currentStepOffset = 0.0;
m_maxPenetrationDepth = 0.2;
full_drop = false;
bounce_fix = false;
m_linearDamping = btScalar(0.0);
m_angularDamping = btScalar(0.0);
setUp(up);
setStepHeight(stepHeight);
setMaxSlope(btRadians(45.0));
}
btKinematicCharacterController::~btKinematicCharacterController ()
@ -559,7 +560,7 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld
break;
}
if (m_ghostObject->hasContactResponse() && (callback.hasHit() && needsCollision(m_ghostObject, callback.m_hitCollisionObject)) || runonce == true)
if ((m_ghostObject->hasContactResponse() && (callback.hasHit() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))) || runonce == true)
{
// we dropped a fraction of the height -> hit floor
btScalar fraction = (m_currentPosition.getY() - callback.m_hitPointWorld.getY()) / 2;
@ -657,7 +658,7 @@ void btKinematicCharacterController::setLinearVelocity(const btVector3& velocity
if (c != 0)
{
//there is a component in walkdirection for vertical velocity
btVector3 upComponent = m_up * (sinf(SIMD_HALF_PI - acosf(c)) * m_walkDirection.length());
btVector3 upComponent = m_up * (btSin(SIMD_HALF_PI - btAcos(c)) * m_walkDirection.length());
m_walkDirection -= upComponent;
m_verticalVelocity = (c < 0.0f ? -1 : 1) * upComponent.length();
@ -751,7 +752,7 @@ void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWo
m_wasOnGround = onGround();
//btVector3 lvel = m_walkDirection;
btScalar c = 0.0f;
//btScalar c = 0.0f;
if (m_walkDirection.length2() > 0)
{

View file

@ -642,7 +642,7 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
btTransform trDeltaAB = trB * trPose * trA.inverse();
btQuaternion qDeltaAB = trDeltaAB.getRotation();
btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z());
float swingAxisLen2 = swingAxis.length2();
btScalar swingAxisLen2 = swingAxis.length2();
if(btFuzzyZero(swingAxisLen2))
{
return;
@ -903,7 +903,7 @@ btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btSc
// a^2 b^2
// Do the math and it should be clear.
float swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1)
btScalar swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1)
if (fabs(xEllipse) > SIMD_EPSILON)
{
btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse);

View file

@ -260,7 +260,7 @@ public:
inline int getSolveSwingLimit()
{
return m_solveTwistLimit;
return m_solveSwingLimit;
}
inline btScalar getTwistLimitSign()

View file

@ -28,11 +28,13 @@ protected:
btPersistentManifold m_contactManifold;
public:
protected:
btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB);
public:
void setContactManifold(btPersistentManifold* contactManifold);
btPersistentManifold* getContactManifold()

View file

@ -43,10 +43,13 @@ struct btContactSolverInfoData
btScalar m_restitution;
int m_numIterations;
btScalar m_maxErrorReduction;
btScalar m_sor;
btScalar m_erp;//used as Baumgarte factor
btScalar m_erp2;//used in Split Impulse
btScalar m_globalCfm;//constraint force mixing
btScalar m_sor;//successive over-relaxation term
btScalar m_erp;//error reduction for non-contact constraints
btScalar m_erp2;//error reduction for contact constraints
btScalar m_globalCfm;//constraint force mixing for contacts and non-contacts
btScalar m_frictionERP;//error reduction for friction constraints
btScalar m_frictionCFM;//constraint force mixing for friction constraints
int m_splitImpulse;
btScalar m_splitImpulsePenetrationThreshold;
btScalar m_splitImpulseTurnErp;
@ -59,6 +62,7 @@ struct btContactSolverInfoData
btScalar m_maxGyroscopicForce;
btScalar m_singleAxisRollingFrictionThreshold;
btScalar m_leastSquaresResidualThreshold;
btScalar m_restitutionVelocityThreshold;
};
@ -79,6 +83,8 @@ struct btContactSolverInfo : public btContactSolverInfoData
m_erp = btScalar(0.2);
m_erp2 = btScalar(0.2);
m_globalCfm = btScalar(0.);
m_frictionERP = btScalar(0.2);//positional friction 'anchors' are disabled by default
m_frictionCFM = btScalar(0.);
m_sor = btScalar(1.);
m_splitImpulse = true;
m_splitImpulsePenetrationThreshold = -.04f;
@ -92,6 +98,7 @@ struct btContactSolverInfo : public btContactSolverInfoData
m_maxGyroscopicForce = 100.f; ///it is only used for 'explicit' version of gyroscopic force
m_singleAxisRollingFrictionThreshold = 1e30f;///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows.
m_leastSquaresResidualThreshold = 0.f;
m_restitutionVelocityThreshold = 0.2f;//if the relative velocity is below this threshold, there is zero restitution
}
};

View file

@ -141,6 +141,14 @@ SIMD_FORCE_INLINE const char* btGearConstraint::serialize(void* dataBuffer, btSe
gear->m_ratio = m_ratio;
// Fill padding with zeros to appease msan.
#ifndef BT_USE_DOUBLE_PRECISION
gear->m_padding[0] = 0;
gear->m_padding[1] = 0;
gear->m_padding[2] = 0;
gear->m_padding[3] = 0;
#endif
return btGearConstraintDataName;
}

View file

@ -776,7 +776,7 @@ int btGeneric6DofConstraint::get_limit_motor_info2(
btConstraintInfo2 *info, int row, btVector3& ax1, int rotational,int rotAllowed)
{
int srow = row * info->rowskip;
int powered = limot->m_enableMotor;
bool powered = limot->m_enableMotor;
int limit = limot->m_currentLimit;
if (powered || limit)
{ // if the joint is powered, or has joint limits, add in the extra row
@ -840,7 +840,7 @@ int btGeneric6DofConstraint::get_limit_motor_info2(
}
// if we're limited low and high simultaneously, the joint motor is
// ineffective
if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = 0;
if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false;
info->m_constraintError[srow] = btScalar(0.f);
if (powered)
{

View file

@ -729,6 +729,21 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
if (limot->m_enableMotor && limot->m_servoMotor)
{
btScalar error = limot->m_currentPosition - limot->m_servoTarget;
btScalar curServoTarget = limot->m_servoTarget;
if (rotational)
{
if (error > SIMD_PI)
{
error -= SIMD_2_PI;
curServoTarget +=SIMD_2_PI;
}
if (error < -SIMD_PI)
{
error += SIMD_2_PI;
curServoTarget -=SIMD_2_PI;
}
}
calculateJacobi(limot,transA,transB,info,srow,ax1,rotational,rotAllowed);
btScalar targetvelocity = error<0 ? -limot->m_targetVelocity : limot->m_targetVelocity;
btScalar tag_vel = -targetvelocity;
@ -739,13 +754,13 @@ int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
btScalar hiLimit;
if(limot->m_loLimit > limot->m_hiLimit)
{
lowLimit = error > 0 ? limot->m_servoTarget : -SIMD_INFINITY;
hiLimit = error < 0 ? limot->m_servoTarget : SIMD_INFINITY;
lowLimit = error > 0 ? curServoTarget : -SIMD_INFINITY;
hiLimit = error < 0 ? curServoTarget : SIMD_INFINITY;
}
else
{
lowLimit = error > 0 && limot->m_servoTarget>limot->m_loLimit ? limot->m_servoTarget : limot->m_loLimit;
hiLimit = error < 0 && limot->m_servoTarget<limot->m_hiLimit ? limot->m_servoTarget : limot->m_hiLimit;
lowLimit = error > 0 && curServoTarget>limot->m_loLimit ? curServoTarget : limot->m_loLimit;
hiLimit = error < 0 && curServoTarget<limot->m_hiLimit ? curServoTarget : limot->m_hiLimit;
}
mot_fact = getMotorFactor(limot->m_currentPosition, lowLimit, hiLimit, tag_vel, info->fps * limot->m_motorERP);
}
@ -998,13 +1013,49 @@ void btGeneric6DofSpring2Constraint::setTargetVelocity(int index, btScalar veloc
m_angularLimits[index - 3].m_targetVelocity = velocity;
}
void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar target)
void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOrg)
{
btAssert((index >= 0) && (index < 6));
if (index<3)
m_linearLimits.m_servoTarget[index] = target;
{
m_linearLimits.m_servoTarget[index] = targetOrg;
}
else
{
//wrap between -PI and PI, see also
//https://stackoverflow.com/questions/4633177/c-how-to-wrap-a-float-to-the-interval-pi-pi
btScalar target = targetOrg+SIMD_PI;
if (1)
{
btScalar m = target - SIMD_2_PI * floor(target/SIMD_2_PI);
// handle boundary cases resulted from floating-point cut off:
{
if (m>=SIMD_2_PI)
{
target = 0;
} else
{
if (m<0 )
{
if (SIMD_2_PI+m == SIMD_2_PI)
target = 0;
else
target = SIMD_2_PI+m;
}
else
{
target = m;
}
}
}
target -= SIMD_PI;
}
m_angularLimits[index - 3].m_servoTarget = target;
}
}
void btGeneric6DofSpring2Constraint::setMaxMotorForce(int index, btScalar force)

View file

@ -664,6 +664,11 @@ SIMD_FORCE_INLINE const char* btGeneric6DofSpring2Constraint::serialize(void* da
dof->m_rotateOrder = m_rotateOrder;
dof->m_padding1[0] = 0;
dof->m_padding1[1] = 0;
dof->m_padding1[2] = 0;
dof->m_padding1[3] = 0;
return btGeneric6DofSpring2ConstraintDataName;
}

View file

@ -556,12 +556,8 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf
}
// if the hinge has joint limits or motor, add in the extra row
int powered = 0;
if(getEnableAngularMotor())
{
powered = 1;
}
if(limit || powered)
bool powered = getEnableAngularMotor();
if(limit || powered)
{
nrow++;
srow = nrow * info->rowskip;
@ -577,7 +573,7 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf
btScalar histop = getUpperLimit();
if(limit && (lostop == histop))
{ // the joint motor is ineffective
powered = 0;
powered = false;
}
info->m_constraintError[srow] = btScalar(0.0f);
btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp;
@ -951,12 +947,8 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info
}
// if the hinge has joint limits or motor, add in the extra row
int powered = 0;
if(getEnableAngularMotor())
{
powered = 1;
}
if(limit || powered)
bool powered = getEnableAngularMotor();
if(limit || powered)
{
nrow++;
srow = nrow * info->rowskip;
@ -972,7 +964,7 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info
btScalar histop = getUpperLimit();
if(limit && (lostop == histop))
{ // the joint motor is ineffective
powered = 0;
powered = false;
}
info->m_constraintError[srow] = btScalar(0.0f);
btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp;

View file

@ -314,7 +314,7 @@ public:
{
return m_enableAngularMotor;
}
inline btScalar getMotorTargetVelosity()
inline btScalar getMotorTargetVelocity()
{
return m_motorTargetVelocity;
}
@ -489,6 +489,14 @@ SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btS
hingeData->m_relaxationFactor = float(m_relaxationFactor);
#endif
// Fill padding with zeros to appease msan.
#ifdef BT_USE_DOUBLE_PRECISION
hingeData->m_padding1[0] = 0;
hingeData->m_padding1[1] = 0;
hingeData->m_padding1[2] = 0;
hingeData->m_padding1[3] = 0;
#endif
return btHingeConstraintDataName;
}

View file

@ -78,20 +78,6 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
btScalar deltaflengthsqr = 0;
if (infoGlobal.m_solverMode & SOLVER_SIMD)
{
for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
{
btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
if (iteration < constraint.m_overrideNumSolverIterations)
{
btScalar deltaf = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
m_deltafNC[j] = deltaf;
deltaflengthsqr += deltaf * deltaf;
}
}
} else
{
for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
{
@ -141,7 +127,6 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
if (infoGlobal.m_solverMode & SOLVER_SIMD)
{
if (iteration< infoGlobal.m_numIterations)
@ -158,7 +143,7 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
}
}
///solve all contact constraints using SIMD, if available
///solve all contact constraints
if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
{
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
@ -170,7 +155,7 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
btScalar deltaf = resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
m_deltafC[c] = deltaf;
deltaflengthsqr += deltaf*deltaf;
totalImpulse = solveManifold.m_appliedImpulse;
@ -186,7 +171,7 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
btScalar deltaf = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
m_deltafCF[c*multiplier] = deltaf;
deltaflengthsqr += deltaf*deltaf;
} else {
@ -203,7 +188,7 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
btScalar deltaf = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
m_deltafCF[c*multiplier+1] = deltaf;
deltaflengthsqr += deltaf*deltaf;
} else {
@ -223,7 +208,6 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
for (j=0;j<numPoolConstraints;j++)
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
//resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
m_deltafC[j] = deltaf;
deltaflengthsqr += deltaf*deltaf;
@ -231,7 +215,7 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
///solve all friction constraints, using SIMD, if available
///solve all friction constraints
int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
for (j=0;j<numFrictionPoolConstraints;j++)
@ -244,7 +228,6 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
//resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
m_deltafCF[j] = deltaf;
deltaflengthsqr += deltaf*deltaf;
@ -252,10 +235,11 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
m_deltafCF[j] = 0;
}
}
}
{
int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
for (j=0;j<numRollingFrictionPoolConstraints;j++)
for (int j=0;j<numRollingFrictionPoolConstraints;j++)
{
btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
@ -269,87 +253,19 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
btScalar deltaf = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
m_deltafCRF[j] = deltaf;
deltaflengthsqr += deltaf*deltaf;
} else {
m_deltafCRF[j] = 0;
}
}
}
}
}
} else
{
if (iteration< infoGlobal.m_numIterations)
{
for (int j=0;j<numConstraints;j++)
{
if (constraints[j]->isEnabled())
{
int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(),infoGlobal.m_timeStep);
int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep);
btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep);
}
}
///solve all contact constraints
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
for (int j=0;j<numPoolConstraints;j++)
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
m_deltafC[j] = deltaf;
deltaflengthsqr += deltaf*deltaf;
}
///solve all friction constraints
int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
for (int j=0;j<numFrictionPoolConstraints;j++)
{
btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
if (totalImpulse>btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
m_deltafCF[j] = deltaf;
deltaflengthsqr += deltaf*deltaf;
} else {
m_deltafCF[j] = 0;
}
}
int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
for (int j=0;j<numRollingFrictionPoolConstraints;j++)
{
btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
if (totalImpulse>btScalar(0))
{
btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
m_deltafCRF[j] = deltaf;
deltaflengthsqr += deltaf*deltaf;
} else {
m_deltafCRF[j] = 0;
}
}
}
}
@ -362,10 +278,7 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = m_deltafNC[j];
for (int j=0;j<m_tmpSolverContactConstraintPool.size();j++) m_pC[j] = m_deltafC[j];
for (int j=0;j<m_tmpSolverContactFrictionConstraintPool.size();j++) m_pCF[j] = m_deltafCF[j];
if ( (infoGlobal.m_solverMode & SOLVER_SIMD) ==0 || (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS) == 0 )
{
for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++) m_pCRF[j] = m_deltafCRF[j];
}
for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++) m_pCRF[j] = m_deltafCRF[j];
} else
{
// deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation
@ -374,9 +287,7 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++) m_pNC[j] = 0;
for (int j=0;j<m_tmpSolverContactConstraintPool.size();j++) m_pC[j] = 0;
for (int j=0;j<m_tmpSolverContactFrictionConstraintPool.size();j++) m_pCF[j] = 0;
if ( (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS) == 0 ) {
for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++) m_pCRF[j] = 0;
}
for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++) m_pCRF[j] = 0;
} else {
for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
{
@ -420,7 +331,7 @@ btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollision
body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,additionaldeltaimpulse);
}
}
if ( (infoGlobal.m_solverMode & SOLVER_SIMD) ==0 || (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS) == 0 ) {
{
for (int j=0;j<m_tmpSolverContactRollingFrictionConstraintPool.size();j++)
{
btSolverConstraint& constraint = m_tmpSolverContactRollingFrictionConstraintPool[j];

View file

@ -269,36 +269,28 @@ static btSimdScalar gResolveSingleConstraintRowLowerLimit_sse4_1_fma3(btSolverBo
btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
{
#ifdef USE_SIMD
return m_resolveSingleConstraintRowGeneric(body1, body2, c);
#else
return resolveSingleConstraintRowGeneric(body1,body2,c);
#endif
}
// Project Gauss Seidel or the equivalent Sequential Impulse
btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
{
return gResolveSingleConstraintRowGeneric_scalar_reference(body1, body2, c);
return m_resolveSingleConstraintRowGeneric(body1, body2, c);
}
btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
{
#ifdef USE_SIMD
return m_resolveSingleConstraintRowLowerLimit(body1, body2, c);
#else
return resolveSingleConstraintRowLowerLimit(body1,body2,c);
#endif
}
btSimdScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
{
return gResolveSingleConstraintRowLowerLimit_scalar_reference(body1,body2,c);
return m_resolveSingleConstraintRowLowerLimit(body1, body2, c);
}
btScalar btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFriendly(
static btSimdScalar gResolveSplitPenetrationImpulse_scalar_reference(
btSolverBody& body1,
btSolverBody& body2,
const btSolverConstraint& c)
@ -330,7 +322,7 @@ btScalar btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCach
return deltaImpulse;
}
btSimdScalar btSequentialImpulseConstraintSolver::resolveSplitPenetrationSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
static btSimdScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
{
#ifdef USE_SIMD
if (!c.m_rhsPenetration)
@ -362,32 +354,42 @@ btSimdScalar btSequentialImpulseConstraintSolver::resolveSplitPenetrationSIMD(bt
body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
return deltaImpulse;
#else
return resolveSplitPenetrationImpulseCacheFriendly(body1,body2,c);
return gResolveSplitPenetrationImpulse_scalar_reference(body1,body2,c);
#endif
}
btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
: m_resolveSingleConstraintRowGeneric(gResolveSingleConstraintRowGeneric_scalar_reference),
m_resolveSingleConstraintRowLowerLimit(gResolveSingleConstraintRowLowerLimit_scalar_reference),
m_btSeed2(0)
{
btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
{
m_btSeed2 = 0;
m_cachedSolverMode = 0;
setupSolverFunctions( false );
}
void btSequentialImpulseConstraintSolver::setupSolverFunctions( bool useSimd )
{
m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_scalar_reference;
m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_scalar_reference;
m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_scalar_reference;
if ( useSimd )
{
#ifdef USE_SIMD
m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse2;
m_resolveSingleConstraintRowLowerLimit=gResolveSingleConstraintRowLowerLimit_sse2;
#endif //USE_SIMD
m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse2;
m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse2;
m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_sse2;
#ifdef BT_ALLOW_SSE4
int cpuFeatures = btCpuFeatureUtility::getCpuFeatures();
if ((cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_FMA3) && (cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_SSE4_1))
{
m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse4_1_fma3;
m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
}
int cpuFeatures = btCpuFeatureUtility::getCpuFeatures();
if ((cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_FMA3) && (cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_SSE4_1))
{
m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse4_1_fma3;
m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
}
#endif//BT_ALLOW_SSE4
}
#endif //USE_SIMD
}
}
btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
{
@ -506,8 +508,12 @@ void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBod
btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution)
btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
{
//printf("rel_vel =%f\n", rel_vel);
if (btFabs(rel_vel)<velocityThreshold)
return 0.;
btScalar rest = restitution * -rel_vel;
return rest;
}
@ -534,7 +540,7 @@ void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionOb
void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
@ -612,7 +618,17 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr
btScalar velocityError = desiredVelocity - rel_vel;
btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
solverConstraint.m_rhs = velocityImpulse;
btScalar penetrationImpulse = btScalar(0);
if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
{
btScalar distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(normalAxis);
btScalar positionalError = -distance * infoGlobal.m_frictionERP/infoGlobal.m_timeStep;
penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
}
solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
solverConstraint.m_rhsPenetration = 0.f;
solverConstraint.m_cfm = cfmSlip;
solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
@ -621,12 +637,12 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr
}
}
btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
{
btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
solverConstraint.m_frictionIndex = frictionIndex;
setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
return solverConstraint;
}
@ -937,7 +953,7 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra
solverConstraint.m_friction = cp.m_combinedFriction;
restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution);
restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
if (restitution <= btScalar(0.))
{
restitution = 0.f;
@ -1100,8 +1116,6 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
int frictionIndex = m_tmpSolverContactConstraintPool.size();
btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
btRigidBody* rb0 = btRigidBody::upcast(colObj0);
btRigidBody* rb1 = btRigidBody::upcast(colObj1);
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
@ -1113,9 +1127,9 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
btVector3 vel1;// = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0);
btVector3 vel2;// = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
btVector3 vel1;
btVector3 vel2;
solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1,vel1);
solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2,vel2 );
@ -1126,8 +1140,6 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
// const btVector3& pos1 = cp.getPositionWorldOnA();
// const btVector3& pos2 = cp.getPositionWorldOnB();
/////setup the friction constraints
@ -1172,6 +1184,7 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
///this will give a conveyor belt effect
///
if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags&BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
{
cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
@ -1181,7 +1194,7 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
cp.m_lateralFrictionDir1 *= 1.f/btSqrt(lat_rel_vel);
applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,infoGlobal);
if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
@ -1189,7 +1202,7 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
cp.m_lateralFrictionDir2.normalize();//??
applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal);
}
} else
@ -1198,13 +1211,13 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal);
}
@ -1216,10 +1229,10 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
} else
{
addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,cp.m_contactMotion1, cp.m_frictionCFM);
addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, cp.m_contactMotion2, cp.m_frictionCFM);
addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
}
setFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
@ -1251,6 +1264,14 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
BT_PROFILE("solveGroupCacheFriendlySetup");
(void)debugDrawer;
// if solver mode has changed,
if ( infoGlobal.m_solverMode != m_cachedSolverMode )
{
// update solver functions to use SIMD or non-SIMD
bool useSimd = !!( infoGlobal.m_solverMode & SOLVER_SIMD );
setupSolverFunctions( useSimd );
m_cachedSolverMode = infoGlobal.m_solverMode;
}
m_maxOverrideNumSolverIterations = 0;
#ifdef BT_ADDITIONAL_DEBUG
@ -1530,7 +1551,8 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
btScalar fsum = btFabs(sum);
btAssert(fsum > SIMD_EPSILON);
solverConstraint.m_jacDiagABInv = fsum>SIMD_EPSILON?btScalar(1.)/sum : 0.f;
btScalar sorRelaxation = 1.f;//todo: get from globalInfo?
solverConstraint.m_jacDiagABInv = fsum>SIMD_EPSILON?sorRelaxation/sum : 0.f;
}
@ -1646,145 +1668,6 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
}
}
if (infoGlobal.m_solverMode & SOLVER_SIMD)
{
///solve all joint constraints, using SIMD, if available
for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
{
btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
if (iteration < constraint.m_overrideNumSolverIterations)
{
btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
leastSquaresResidual += residual*residual;
}
}
if (iteration< infoGlobal.m_numIterations)
{
for (int j=0;j<numConstraints;j++)
{
if (constraints[j]->isEnabled())
{
int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(),infoGlobal.m_timeStep);
int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep);
btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep);
}
}
///solve all contact constraints using SIMD, if available
if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
{
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1;
for (int c=0;c<numPoolConstraints;c++)
{
btScalar totalImpulse =0;
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
btScalar residual = resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
totalImpulse = solveManifold.m_appliedImpulse;
}
bool applyFriction = true;
if (applyFriction)
{
{
btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier]];
if (totalImpulse>btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
}
}
if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
{
btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier+1]];
if (totalImpulse>btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
}
}
}
}
}
else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
{
//solve the friction constraints after all contact constraints, don't interleave them
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int j;
for (j=0;j<numPoolConstraints;j++)
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
btScalar residual = resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
}
///solve all friction constraints, using SIMD, if available
int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
for (j=0;j<numFrictionPoolConstraints;j++)
{
btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
if (totalImpulse>btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
}
}
int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
for (j=0;j<numRollingFrictionPoolConstraints;j++)
{
btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
if (totalImpulse>btScalar(0))
{
btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
btScalar residual = resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
leastSquaresResidual += residual*residual;
}
}
}
}
} else
{
//non-SIMD version
///solve all joint constraints
for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
{
@ -1809,51 +1692,116 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep);
}
}
///solve all contact constraints
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
for (int j=0;j<numPoolConstraints;j++)
if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
}
///solve all friction constraints
int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
for (int j=0;j<numFrictionPoolConstraints;j++)
{
btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1;
if (totalImpulse>btScalar(0))
for (int c=0;c<numPoolConstraints;c++)
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
btScalar totalImpulse =0;
btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
totalImpulse = solveManifold.m_appliedImpulse;
}
bool applyFriction = true;
if (applyFriction)
{
{
btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier]];
if (totalImpulse>btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
}
}
if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
{
btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier+1]];
if (totalImpulse>btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
}
}
}
}
}
else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
{
//solve the friction constraints after all contact constraints, don't interleave them
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int j;
for (j=0;j<numPoolConstraints;j++)
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
}
///solve all friction constraints
int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
for (j=0;j<numFrictionPoolConstraints;j++)
{
btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
if (totalImpulse>btScalar(0))
{
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
}
}
}
int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
for (int j=0;j<numRollingFrictionPoolConstraints;j++)
{
btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
if (totalImpulse>btScalar(0))
int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
for (int j=0;j<numRollingFrictionPoolConstraints;j++)
{
btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
if (totalImpulse>btScalar(0))
{
btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
leastSquaresResidual += residual*residual;
rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
leastSquaresResidual += residual*residual;
}
}
}
}
}
return leastSquaresResidual;
}
@ -1863,7 +1811,6 @@ void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIte
int iteration;
if (infoGlobal.m_splitImpulse)
{
if (infoGlobal.m_solverMode & SOLVER_SIMD)
{
for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
{
@ -1875,7 +1822,7 @@ void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIte
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
btScalar residual = resolveSplitPenetrationSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
}
}
@ -1887,32 +1834,7 @@ void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIte
break;
}
}
}
else
{
for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
{
btScalar leastSquaresResidual = 0.f;
{
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int j;
for (j=0;j<numPoolConstraints;j++)
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
btScalar residual = resolveSplitPenetrationImpulseCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
leastSquaresResidual += residual*residual;
}
if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration>=(infoGlobal.m_numIterations-1))
{
#ifdef VERBOSE_RESIDUAL_PRINTF
printf("residual = %f at iteration #%d\n",leastSquaresResidual,iteration);
#endif
break;
}
}
}
}
}
}
}

View file

@ -56,12 +56,16 @@ protected:
btSingleConstraintRowSolver m_resolveSingleConstraintRowGeneric;
btSingleConstraintRowSolver m_resolveSingleConstraintRowLowerLimit;
btSingleConstraintRowSolver m_resolveSplitPenetrationImpulse;
int m_cachedSolverMode; // used to check if SOLVER_SIMD flag has been changed
void setupSolverFunctions( bool useSimd );
btScalar m_leastSquaresResidual;
void setupFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,
btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,
btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation,
const btContactSolverInfo& infoGlobal,
btScalar desiredVelocity=0., btScalar cfmSlip=0.);
void setupTorsionalFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,
@ -69,7 +73,7 @@ protected:
btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation,
btScalar desiredVelocity=0., btScalar cfmSlip=0.);
btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0., btScalar cfmSlip=0.);
btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity=0., btScalar cfmSlip=0.);
btSolverConstraint& addTorsionalFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,btScalar torsionalFriction, const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0, btScalar cfmSlip=0.f);
@ -85,20 +89,22 @@ protected:
unsigned long m_btSeed2;
btScalar restitutionCurve(btScalar rel_vel, btScalar restitution);
btScalar restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold);
virtual void convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
void convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal);
btSimdScalar resolveSplitPenetrationSIMD(
btSolverBody& bodyA,btSolverBody& bodyB,
const btSolverConstraint& contactConstraint);
btSimdScalar resolveSplitPenetrationSIMD(btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint)
{
return m_resolveSplitPenetrationImpulse( bodyA, bodyB, contactConstraint );
}
btScalar resolveSplitPenetrationImpulseCacheFriendly(
btSolverBody& bodyA,btSolverBody& bodyB,
const btSolverConstraint& contactConstraint);
btSimdScalar resolveSplitPenetrationImpulseCacheFriendly(btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint)
{
return m_resolveSplitPenetrationImpulse( bodyA, bodyB, contactConstraint );
}
//internal method
int getOrInitSolverBody(btCollisionObject& body,btScalar timeStep);
@ -108,6 +114,10 @@ protected:
btSimdScalar resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
btSimdScalar resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
btSimdScalar resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
btSimdScalar resolveSplitPenetrationImpulse(btSolverBody& bodyA,btSolverBody& bodyB, const btSolverConstraint& contactConstraint)
{
return m_resolveSplitPenetrationImpulse( bodyA, bodyB, contactConstraint );
}
protected:

View file

@ -364,7 +364,6 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
int srow;
btScalar limit_err;
int limit;
int powered;
// next two rows.
// we want: velA + wA x relA == velB + wB x relB ... but this would
@ -470,13 +469,9 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
limit_err = getLinDepth() * signFact;
limit = (limit_err > btScalar(0.0)) ? 2 : 1;
}
powered = 0;
if(getPoweredLinMotor())
{
powered = 1;
}
bool powered = getPoweredLinMotor();
// if the slider has joint limits or motor, add in the extra row
if (limit || powered)
if (limit || powered)
{
nrow++;
srow = nrow * info->rowskip;
@ -524,7 +519,7 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
btScalar histop = getUpperLinLimit();
if(limit && (lostop == histop))
{ // the joint motor is ineffective
powered = 0;
powered = false;
}
info->m_constraintError[srow] = 0.;
info->m_lowerLimit[srow] = 0.;
@ -609,12 +604,8 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
limit = (limit_err > btScalar(0.0)) ? 1 : 2;
}
// if the slider has joint limits, add in the extra row
powered = 0;
if(getPoweredAngMotor())
{
powered = 1;
}
if(limit || powered)
powered = getPoweredAngMotor();
if(limit || powered)
{
nrow++;
srow = nrow * info->rowskip;
@ -630,7 +621,7 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
btScalar histop = getUpperAngLimit();
if(limit && (lostop == histop))
{ // the joint motor is ineffective
powered = 0;
powered = false;
}
currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp;
if(powered)

View file

@ -19,7 +19,7 @@ subject to the following restrictions:
#include "LinearMath/btSerializer.h"
#define DEFAULT_DEBUGDRAW_SIZE btScalar(0.3f)
#define DEFAULT_DEBUGDRAW_SIZE btScalar(0.05f)
btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA)
:btTypedObject(type),

View file

@ -374,7 +374,7 @@ void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
void btDiscreteDynamicsWorld::synchronizeMotionStates()
{
BT_PROFILE("synchronizeMotionStates");
// BT_PROFILE("synchronizeMotionStates");
if (m_synchronizeAllMotionStates)
{
//iterate over all collision objects
@ -402,7 +402,6 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps,
{
startProfiling(timeStep);
BT_PROFILE("stepSimulation");
int numSimulationSubSteps = 0;
@ -539,7 +538,7 @@ btVector3 btDiscreteDynamicsWorld::getGravity () const
return m_gravity;
}
void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask)
void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
{
btCollisionWorld::addCollisionObject(collisionObject,collisionFilterGroup,collisionFilterMask);
}
@ -578,14 +577,14 @@ void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body)
}
bool isDynamic = !(body->isStaticObject() || body->isKinematicObject());
short collisionFilterGroup = isDynamic? short(btBroadphaseProxy::DefaultFilter) : short(btBroadphaseProxy::StaticFilter);
short collisionFilterMask = isDynamic? short(btBroadphaseProxy::AllFilter) : short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
int collisionFilterGroup = isDynamic? int(btBroadphaseProxy::DefaultFilter) : int(btBroadphaseProxy::StaticFilter);
int collisionFilterMask = isDynamic? int(btBroadphaseProxy::AllFilter) : int(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
addCollisionObject(body,collisionFilterGroup,collisionFilterMask);
}
}
void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask)
void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
{
if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
{
@ -1512,6 +1511,9 @@ void btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serialize
worldInfo->m_solverInfo.m_splitImpulse = getSolverInfo().m_splitImpulse;
// Fill padding with zeros to appease msan.
memset(worldInfo->m_solverInfo.m_padding, 0, sizeof(worldInfo->m_solverInfo.m_padding));
#ifdef BT_USE_DOUBLE_PRECISION
const char* structType = "btDynamicsWorldDoubleData";
#else//BT_USE_DOUBLE_PRECISION

View file

@ -144,11 +144,11 @@ public:
virtual btVector3 getGravity () const;
virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::StaticFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup=btBroadphaseProxy::StaticFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
virtual void addRigidBody(btRigidBody* body);
virtual void addRigidBody(btRigidBody* body, short group, short mask);
virtual void addRigidBody(btRigidBody* body, int group, int mask);
virtual void removeRigidBody(btRigidBody* body);

View file

@ -108,8 +108,108 @@ struct InplaceSolverIslandCallbackMt : public btSimulationIslandManagerMt::Islan
};
///
/// btConstraintSolverPoolMt
///
btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
btConstraintSolverPoolMt::ThreadSolver* btConstraintSolverPoolMt::getAndLockThreadSolver()
{
int i = 0;
#if BT_THREADSAFE
i = btGetCurrentThreadIndex() % m_solvers.size();
#endif // #if BT_THREADSAFE
while ( true )
{
ThreadSolver& solver = m_solvers[ i ];
if ( solver.mutex.tryLock() )
{
return &solver;
}
// failed, try the next one
i = ( i + 1 ) % m_solvers.size();
}
return NULL;
}
void btConstraintSolverPoolMt::init( btConstraintSolver** solvers, int numSolvers )
{
m_solverType = BT_SEQUENTIAL_IMPULSE_SOLVER;
m_solvers.resize( numSolvers );
for ( int i = 0; i < numSolvers; ++i )
{
m_solvers[ i ].solver = solvers[ i ];
}
if ( numSolvers > 0 )
{
m_solverType = solvers[ 0 ]->getSolverType();
}
}
// create the solvers for me
btConstraintSolverPoolMt::btConstraintSolverPoolMt( int numSolvers )
{
btAlignedObjectArray<btConstraintSolver*> solvers;
solvers.reserve( numSolvers );
for ( int i = 0; i < numSolvers; ++i )
{
btConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
solvers.push_back( solver );
}
init( &solvers[ 0 ], numSolvers );
}
// pass in fully constructed solvers (destructor will delete them)
btConstraintSolverPoolMt::btConstraintSolverPoolMt( btConstraintSolver** solvers, int numSolvers )
{
init( solvers, numSolvers );
}
btConstraintSolverPoolMt::~btConstraintSolverPoolMt()
{
// delete all solvers
for ( int i = 0; i < m_solvers.size(); ++i )
{
ThreadSolver& solver = m_solvers[ i ];
delete solver.solver;
solver.solver = NULL;
}
}
///solve a group of constraints
btScalar btConstraintSolverPoolMt::solveGroup( btCollisionObject** bodies,
int numBodies,
btPersistentManifold** manifolds,
int numManifolds,
btTypedConstraint** constraints,
int numConstraints,
const btContactSolverInfo& info,
btIDebugDraw* debugDrawer,
btDispatcher* dispatcher
)
{
ThreadSolver* ts = getAndLockThreadSolver();
ts->solver->solveGroup( bodies, numBodies, manifolds, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher );
ts->mutex.unlock();
return 0.0f;
}
void btConstraintSolverPoolMt::reset()
{
for ( int i = 0; i < m_solvers.size(); ++i )
{
ThreadSolver& solver = m_solvers[ i ];
solver.mutex.lock();
solver.solver->reset();
solver.mutex.unlock();
}
}
///
/// btDiscreteDynamicsWorldMt
///
btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolverPoolMt* constraintSolver, btCollisionConfiguration* collisionConfiguration)
: btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
{
if (m_ownsIslandManager)
@ -124,8 +224,8 @@ btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,bt
{
void* mem = btAlignedAlloc(sizeof(btSimulationIslandManagerMt),16);
btSimulationIslandManagerMt* im = new (mem) btSimulationIslandManagerMt();
m_islandManager = im;
im->setMinimumSolverBatchSize( m_solverInfo.m_minimumSolverBatchSize );
m_islandManager = im;
}
}
@ -145,7 +245,7 @@ btDiscreteDynamicsWorldMt::~btDiscreteDynamicsWorldMt()
}
void btDiscreteDynamicsWorldMt::solveConstraints(btContactSolverInfo& solverInfo)
void btDiscreteDynamicsWorldMt::solveConstraints(btContactSolverInfo& solverInfo)
{
BT_PROFILE("solveConstraints");
@ -160,3 +260,68 @@ void btDiscreteDynamicsWorldMt::solveConstraints(btContactSolverInfo& solverInfo
}
struct UpdaterUnconstrainedMotion : public btIParallelForBody
{
btScalar timeStep;
btRigidBody** rigidBodies;
void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
{
for ( int i = iBegin; i < iEnd; ++i )
{
btRigidBody* body = rigidBodies[ i ];
if ( !body->isStaticOrKinematicObject() )
{
//don't integrate/update velocities here, it happens in the constraint solver
body->applyDamping( timeStep );
body->predictIntegratedTransform( timeStep, body->getInterpolationWorldTransform() );
}
}
}
};
void btDiscreteDynamicsWorldMt::predictUnconstraintMotion( btScalar timeStep )
{
BT_PROFILE( "predictUnconstraintMotion" );
if ( m_nonStaticRigidBodies.size() > 0 )
{
UpdaterUnconstrainedMotion update;
update.timeStep = timeStep;
update.rigidBodies = &m_nonStaticRigidBodies[ 0 ];
int grainSize = 50; // num of iterations per task for task scheduler
btParallelFor( 0, m_nonStaticRigidBodies.size(), grainSize, update );
}
}
void btDiscreteDynamicsWorldMt::createPredictiveContacts( btScalar timeStep )
{
BT_PROFILE( "createPredictiveContacts" );
releasePredictiveContacts();
if ( m_nonStaticRigidBodies.size() > 0 )
{
UpdaterCreatePredictiveContacts update;
update.world = this;
update.timeStep = timeStep;
update.rigidBodies = &m_nonStaticRigidBodies[ 0 ];
int grainSize = 50; // num of iterations per task for task scheduler
btParallelFor( 0, m_nonStaticRigidBodies.size(), grainSize, update );
}
}
void btDiscreteDynamicsWorldMt::integrateTransforms( btScalar timeStep )
{
BT_PROFILE( "integrateTransforms" );
if ( m_nonStaticRigidBodies.size() > 0 )
{
UpdaterIntegrateTransforms update;
update.world = this;
update.timeStep = timeStep;
update.rigidBodies = &m_nonStaticRigidBodies[ 0 ];
int grainSize = 50; // num of iterations per task for task scheduler
btParallelFor( 0, m_nonStaticRigidBodies.size(), grainSize, update );
}
}

View file

@ -18,24 +18,116 @@ subject to the following restrictions:
#define BT_DISCRETE_DYNAMICS_WORLD_MT_H
#include "btDiscreteDynamicsWorld.h"
#include "btSimulationIslandManagerMt.h"
#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
struct InplaceSolverIslandCallbackMt;
///
/// btConstraintSolverPoolMt - masquerades as a constraint solver, but really it is a threadsafe pool of them.
///
/// Each solver in the pool is protected by a mutex. When solveGroup is called from a thread,
/// the pool looks for a solver that isn't being used by another thread, locks it, and dispatches the
/// call to the solver.
/// So long as there are at least as many solvers as there are hardware threads, it should never need to
/// spin wait.
///
class btConstraintSolverPoolMt : public btConstraintSolver
{
public:
// create the solvers for me
explicit btConstraintSolverPoolMt( int numSolvers );
// pass in fully constructed solvers (destructor will delete them)
btConstraintSolverPoolMt( btConstraintSolver** solvers, int numSolvers );
virtual ~btConstraintSolverPoolMt();
///solve a group of constraints
virtual btScalar solveGroup( btCollisionObject** bodies,
int numBodies,
btPersistentManifold** manifolds,
int numManifolds,
btTypedConstraint** constraints,
int numConstraints,
const btContactSolverInfo& info,
btIDebugDraw* debugDrawer,
btDispatcher* dispatcher
) BT_OVERRIDE;
virtual void reset() BT_OVERRIDE;
virtual btConstraintSolverType getSolverType() const BT_OVERRIDE { return m_solverType; }
private:
const static size_t kCacheLineSize = 128;
struct ThreadSolver
{
btConstraintSolver* solver;
btSpinMutex mutex;
char _cachelinePadding[ kCacheLineSize - sizeof( btSpinMutex ) - sizeof( void* ) ]; // keep mutexes from sharing a cache line
};
btAlignedObjectArray<ThreadSolver> m_solvers;
btConstraintSolverType m_solverType;
ThreadSolver* getAndLockThreadSolver();
void init( btConstraintSolver** solvers, int numSolvers );
};
///
/// btDiscreteDynamicsWorldMt -- a version of DiscreteDynamicsWorld with some minor changes to support
/// solving simulation islands on multiple threads.
///
/// Should function exactly like btDiscreteDynamicsWorld.
/// Also 3 methods that iterate over all of the rigidbodies can run in parallel:
/// - predictUnconstraintMotion
/// - integrateTransforms
/// - createPredictiveContacts
///
ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorldMt : public btDiscreteDynamicsWorld
{
protected:
InplaceSolverIslandCallbackMt* m_solverIslandCallbackMt;
virtual void solveConstraints(btContactSolverInfo& solverInfo);
virtual void solveConstraints(btContactSolverInfo& solverInfo) BT_OVERRIDE;
virtual void predictUnconstraintMotion( btScalar timeStep ) BT_OVERRIDE;
struct UpdaterCreatePredictiveContacts : public btIParallelForBody
{
btScalar timeStep;
btRigidBody** rigidBodies;
btDiscreteDynamicsWorldMt* world;
void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
{
world->createPredictiveContactsInternal( &rigidBodies[ iBegin ], iEnd - iBegin, timeStep );
}
};
virtual void createPredictiveContacts( btScalar timeStep ) BT_OVERRIDE;
struct UpdaterIntegrateTransforms : public btIParallelForBody
{
btScalar timeStep;
btRigidBody** rigidBodies;
btDiscreteDynamicsWorldMt* world;
void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
{
world->integrateTransformsInternal( &rigidBodies[ iBegin ], iEnd - iBegin, timeStep );
}
};
virtual void integrateTransforms( btScalar timeStep ) BT_OVERRIDE;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,
btBroadphaseInterface* pairCache,
btConstraintSolverPoolMt* constraintSolver, // Note this should be a solver-pool for multi-threading
btCollisionConfiguration* collisionConfiguration
);
virtual ~btDiscreteDynamicsWorldMt();
};

View file

@ -89,7 +89,7 @@ public:
virtual void addRigidBody(btRigidBody* body) = 0;
virtual void addRigidBody(btRigidBody* body, short group, short mask) = 0;
virtual void addRigidBody(btRigidBody* body, int group, int mask) = 0;
virtual void removeRigidBody(btRigidBody* body) = 0;
@ -135,6 +135,11 @@ public:
return m_solverInfo;
}
const btContactSolverInfo& getSolverInfo() const
{
return m_solverInfo;
}
///obsolete, use addAction instead.
virtual void addVehicle(btActionInterface* vehicle) {(void)vehicle;}

View file

@ -507,6 +507,11 @@ const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* seriali
rbd->m_linearSleepingThreshold=m_linearSleepingThreshold;
rbd->m_angularSleepingThreshold = m_angularSleepingThreshold;
// Fill padding with zeros to appease msan.
#ifdef BT_USE_DOUBLE_PRECISION
memset(rbd->m_padding, 0, sizeof(rbd->m_padding));
#endif
return btRigidBodyDataName;
}

View file

@ -155,7 +155,7 @@ void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body)
}
}
void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask)
void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
{
body->setGravity(m_gravity);

View file

@ -56,7 +56,7 @@ public:
virtual void addRigidBody(btRigidBody* body);
virtual void addRigidBody(btRigidBody* body, short group, short mask);
virtual void addRigidBody(btRigidBody* body, int group, int mask);
virtual void removeRigidBody(btRigidBody* body);

View file

@ -15,6 +15,7 @@ subject to the following restrictions:
#include "LinearMath/btScalar.h"
#include "LinearMath/btThreads.h"
#include "btSimulationIslandManagerMt.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
@ -44,7 +45,7 @@ btSimulationIslandManagerMt::btSimulationIslandManagerMt()
{
m_minimumSolverBatchSize = calcBatchCost(0, 128, 0);
m_batchIslandMinBodyCount = 32;
m_islandDispatch = defaultIslandDispatch;
m_islandDispatch = parallelIslandDispatch;
m_batchIsland = NULL;
}
@ -545,8 +546,9 @@ void btSimulationIslandManagerMt::mergeIslands()
}
void btSimulationIslandManagerMt::defaultIslandDispatch( btAlignedObjectArray<Island*>* islandsPtr, IslandCallback* callback )
void btSimulationIslandManagerMt::serialIslandDispatch( btAlignedObjectArray<Island*>* islandsPtr, IslandCallback* callback )
{
BT_PROFILE( "serialIslandDispatch" );
// serial dispatch
btAlignedObjectArray<Island*>& islands = *islandsPtr;
for ( int i = 0; i < islands.size(); ++i )
@ -565,6 +567,41 @@ void btSimulationIslandManagerMt::defaultIslandDispatch( btAlignedObjectArray<Is
}
}
struct UpdateIslandDispatcher : public btIParallelForBody
{
btAlignedObjectArray<btSimulationIslandManagerMt::Island*>* islandsPtr;
btSimulationIslandManagerMt::IslandCallback* callback;
void forLoop( int iBegin, int iEnd ) const BT_OVERRIDE
{
for ( int i = iBegin; i < iEnd; ++i )
{
btSimulationIslandManagerMt::Island* island = ( *islandsPtr )[ i ];
btPersistentManifold** manifolds = island->manifoldArray.size() ? &island->manifoldArray[ 0 ] : NULL;
btTypedConstraint** constraintsPtr = island->constraintArray.size() ? &island->constraintArray[ 0 ] : NULL;
callback->processIsland( &island->bodyArray[ 0 ],
island->bodyArray.size(),
manifolds,
island->manifoldArray.size(),
constraintsPtr,
island->constraintArray.size(),
island->id
);
}
}
};
void btSimulationIslandManagerMt::parallelIslandDispatch( btAlignedObjectArray<Island*>* islandsPtr, IslandCallback* callback )
{
BT_PROFILE( "parallelIslandDispatch" );
int grainSize = 1; // iterations per task
UpdateIslandDispatcher dispatcher;
dispatcher.islandsPtr = islandsPtr;
dispatcher.callback = callback;
btParallelFor( 0, islandsPtr->size(), grainSize, dispatcher );
}
///@todo: this is random access, it can be walked 'cache friendly'!
void btSimulationIslandManagerMt::buildAndProcessIslands( btDispatcher* dispatcher,
btCollisionWorld* collisionWorld,

Some files were not shown because too many files have changed in this diff Show more