diff --git a/SConstruct b/SConstruct
index 4c3bbf8fad7..356f116e290 100644
--- a/SConstruct
+++ b/SConstruct
@@ -241,6 +241,13 @@ if len(B.quickdebug) > 0 and printdebug != 0:
for l in B.quickdebug:
print "\t" + l
+# remove stdc++ from LLIBS if we are building a statc linked CXXFLAGS
+if env['WITH_BF_STATICCXX']:
+ if 'stdc++' in env['LLIBS']:
+ env['LLIBS'] = env['LLIBS'].replace('stdc++', ' ')
+ else:
+ print '\tcould not remove stdc++ library from LLIBS, WITH_BF_STATICCXX may not work for your platform'
+
# check target for blenderplayer. Set WITH_BF_PLAYER if found on cmdline
if 'blenderplayer' in B.targets:
env['WITH_BF_PLAYER'] = True
@@ -248,6 +255,19 @@ if 'blenderplayer' in B.targets:
if 'blendernogame' in B.targets:
env['WITH_BF_GAMEENGINE'] = False
+if 'blenderlite' in B.targets:
+ env['WITH_BF_GAMEENGINE'] = False
+ env['WITH_BF_OPENAL'] = False
+ env['WITH_BF_OPENEXR'] = False
+ env['WITH_BF_ICONV'] = False
+ env['WITH_BF_INTERNATIONAL'] = False
+ env['WITH_BF_OPENJPEG'] = False
+ env['WITH_BF_FFMPEG'] = False
+ env['WITH_BF_QUICKTIME'] = False
+ env['WITH_BF_YAFRAY'] = False
+ env['WITH_BF_REDCODE'] = False
+ env['WITH_BF_FTGL'] = False
+
# lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir
#B.root_build_dir = B.arguments.get('BF_BUILDDIR', '..'+os.sep+'build'+os.sep+platform+os.sep)
B.root_build_dir = env['BF_BUILDDIR']
@@ -488,6 +508,10 @@ if not env['WITH_BF_GAMEENGINE']:
blendernogame = env.Alias('blendernogame', B.program_list)
Depends(blendernogame,installtarget)
+if 'blenderlite' in B.targets:
+ blenderlite = env.Alias('blenderlite', B.program_list)
+ Depends(blenderlite,installtarget)
+
Depends(nsiscmd, allinstall)
Default(B.program_list)
diff --git a/blenderplayer/CMakeLists.txt b/blenderplayer/CMakeLists.txt
index e32390466c7..9786b7e61b2 100644
--- a/blenderplayer/CMakeLists.txt
+++ b/blenderplayer/CMakeLists.txt
@@ -86,6 +86,7 @@ IF(UNIX)
bf_oglrasterizer
bf_expressions
bf_scenegraph
+ bf_IK
bf_moto
bf_soundsystem
bf_kernel
diff --git a/config/darwin-config.py b/config/darwin-config.py
index 48455d2ce8c..0eb275dcaf4 100644
--- a/config/darwin-config.py
+++ b/config/darwin-config.py
@@ -87,10 +87,18 @@ if MAC_PROC == 'powerpc':
BF_OPENAL = '#../lib/darwin-8.0.0-powerpc/openal'
else :
BF_OPENAL = LIBDIR + '/openal'
-
+
+WITH_BF_STATICOPENAL = 'false'
BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'openal'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
+
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_CXX = '/usr'
+WITH_BF_STATICCXX = 'false'
+BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
WITH_BF_SDL = 'true'
BF_SDL = LIBDIR + '/sdl' #$(shell sdl-config --prefix)
@@ -102,10 +110,13 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true'
+WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '${LCGDIR}/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread'
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
WITH_BF_DDS = 'true'
diff --git a/config/linux2-config.py b/config/linux2-config.py
index 332af28977f..9f8f75446d8 100644
--- a/config/linux2-config.py
+++ b/config/linux2-config.py
@@ -6,18 +6,28 @@ BF_VERSE_INCLUDE = "#extern/verse/dist"
BF_PYTHON = '/usr'
BF_PYTHON_VERSION = '2.5'
+WITH_BF_STATICPYTHON = 'false'
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'
BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_VERSION+'/config/libpython'+BF_PYTHON_VERSION+'.a'
BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic']
+BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/libpython${BF_PYTHON_VERSION}.a'
WITH_BF_OPENAL = 'true'
+WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = '/usr'
BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'openal'
+BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
+
# some distros have a separate libalut
# if you get linker complaints, you need to uncomment the line below
# BF_OPENAL_LIB = 'openal alut'
+# BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a ${BF_OPENAL}/lib/libalut.a'
+
+BF_CXX = '/usr'
+WITH_BF_STATICCXX = 'false'
+BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
WITH_BF_SDL = 'true'
BF_SDL = '/usr' #$(shell sdl-config --prefix)
@@ -28,14 +38,17 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true'
+WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '/usr'
# when compiling with your own openexr lib you might need to set...
# BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR ${BF_OPENEXR}/include'
BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = 'Half IlmImf Iex Imath '
+BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
# BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
+
WITH_BF_DDS = 'true'
WITH_BF_JPEG = 'true'
diff --git a/config/linuxcross-config.py b/config/linuxcross-config.py
index e6c4e8769b4..9d58512151b 100644
--- a/config/linuxcross-config.py
+++ b/config/linuxcross-config.py
@@ -14,10 +14,18 @@ BF_PYTHON_LIB = 'python25'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib'
WITH_BF_OPENAL = 'true'
+WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = LIBDIR + '/openal'
BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'openal_static'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
+
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_CXX = '/usr'
+WITH_BF_STATICCXX = 'false'
+BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
WITH_BF_SDL = 'true'
BF_SDL = LIBDIR + '/sdl'
@@ -34,10 +42,13 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true'
+WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = LIBDIR + '/gcc/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = ' Half IlmImf Iex '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
WITH_BF_DDS = 'true'
diff --git a/config/openbsd3-config.py b/config/openbsd3-config.py
index f7f254973af..5ef3d90f168 100644
--- a/config/openbsd3-config.py
+++ b/config/openbsd3-config.py
@@ -9,10 +9,12 @@ BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}/config'
WITH_BF_OPENAL = 'false'
+# WITH_BF_STATICOPENAL = 'false'
#BF_OPENAL = LIBDIR + '/openal'
#BF_OPENAL_INC = '${BF_OPENAL}/include'
#BF_OPENAL_LIB = 'openal'
#BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
+#BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
WITH_BF_SDL = 'true'
BF_SDL = '/usr/local' #$(shell sdl-config --prefix)
@@ -24,9 +26,12 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'false'
+WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '/usr/local'
BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = 'Half IlmImf Iex Imath '
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
WITH_BF_DDS = 'true'
diff --git a/config/sunos5-config.py b/config/sunos5-config.py
index b3ca0e267ff..bfb1513ca3f 100644
--- a/config/sunos5-config.py
+++ b/config/sunos5-config.py
@@ -9,10 +9,18 @@ BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_
BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic']
WITH_BF_OPENAL = 'true'
+WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = '/usr/local'
BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
BF_OPENAL_LIB = 'openal'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
+
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_CXX = '/usr'
+WITH_BF_STATICCXX = 'false'
+BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
WITH_BF_SDL = 'true'
BF_SDL = '/usr/local' #$(shell sdl-config --prefix)
@@ -24,10 +32,13 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true'
+WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '/usr/local'
BF_OPENEXR_INC = ['${BF_OPENEXR}/include', '${BF_OPENEXR}/include/OpenEXR' ]
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
BF_OPENEXR_LIB = 'Half IlmImf Iex Imath '
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
WITH_BF_DDS = 'true'
diff --git a/config/win32-mingw-config.py b/config/win32-mingw-config.py
index d9fd6ce8d4f..4ff93bf7078 100644
--- a/config/win32-mingw-config.py
+++ b/config/win32-mingw-config.py
@@ -12,10 +12,13 @@ BF_PYTHON_LIB = 'python25'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib'
WITH_BF_OPENAL = 'true'
+WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = LIBDIR + '/openal'
BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'dxguid openal_static'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
WITH_BF_FFMPEG = 'false'
BF_FFMPEG_LIB = 'avformat swscale avcodec avutil xvidcore x264'
@@ -37,10 +40,13 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true'
+WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = LIBDIR + '/gcc/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = ' Half IlmImf Iex '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
WITH_BF_DDS = 'true'
diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py
index 02e5dbb7f8f..063d1461def 100644
--- a/config/win32-vc-config.py
+++ b/config/win32-vc-config.py
@@ -19,10 +19,18 @@ BF_PYTHON_LIB = 'python25'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib'
WITH_BF_OPENAL = 'true'
+WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = LIBDIR + '/openal'
BF_OPENAL_INC = '${BF_OPENAL}/include ${BF_OPENAL}/include/AL '
BF_OPENAL_LIB = 'dxguid openal_static'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
+
+# TODO - are these useful on win32?
+# BF_CXX = '/usr'
+# WITH_BF_STATICCXX = 'false'
+# BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
WITH_BF_ICONV = 'true'
BF_ICONV = LIBDIR + '/iconv'
@@ -45,10 +53,13 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true'
+WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = LIBDIR + '/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/IlmImf ${BF_OPENEXR}/include/Iex ${BF_OPENEXR}/include/Imath '
BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib_msvc'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a'
WITH_BF_DDS = 'true'
diff --git a/extern/bullet2/CMakeLists.txt b/extern/bullet2/CMakeLists.txt
index c5495fdf92b..e28e811087f 100644
--- a/extern/bullet2/CMakeLists.txt
+++ b/extern/bullet2/CMakeLists.txt
@@ -35,6 +35,7 @@ FILE(GLOB SRC
src/BulletDynamics/ConstraintSolver/*.cpp
src/BulletDynamics/Vehicle/*.cpp
src/BulletDynamics/Dynamics/*.cpp
+ src/BulletSoftBody/*.cpp
)
ADD_DEFINITIONS(-D_LIB)
diff --git a/extern/bullet2/Makefile b/extern/bullet2/Makefile
index e05d441a6be..d26289c8b01 100644
--- a/extern/bullet2/Makefile
+++ b/extern/bullet2/Makefile
@@ -40,7 +40,8 @@ BulletCollision/NarrowPhaseCollision \
BulletCollision//CollisionDispatch \
BulletDynamics/ConstraintSolver \
BulletDynamics/Vehicle \
-BulletDynamics/Dynamics
+BulletDynamics/Dynamics \
+BulletSoftBody
include nan_subdirs.mk
diff --git a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj
index 6de2fd3a2bd..be4f78102a4 100644
--- a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj
+++ b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj
@@ -58,9 +58,11 @@ IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\C
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Dynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Vehicle MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\LinearMath MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\LinearMath
+IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletSoftBody MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletSoftBody
XCOPY /Y ..\..\src\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include
XCOPY /Y ..\..\src\LinearMath\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\LinearMath
+XCOPY /Y ..\..\src\BulletSoftBody\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletSoftBody
XCOPY /Y ..\..\src\BulletCollision\BroadphaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\BroadphaseCollision
XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
@@ -394,12 +396,24 @@ ECHO Done
+
+
+
+
+
+
+
+
@@ -410,6 +424,12 @@ ECHO Done
+
+
+
+
@@ -482,18 +502,45 @@ ECHO Done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -534,6 +581,12 @@ ECHO Done
+
+
+
+
@@ -589,6 +642,21 @@ ECHO Done
+
+
+
+
+
+
+
+
+
+
@@ -628,6 +696,18 @@ ECHO Done
+
+
+
+
+
+
+
+
@@ -731,6 +811,12 @@ ECHO Done
+
+
+
+
@@ -761,12 +847,21 @@ ECHO Done
+
+
+
+
+
+
@@ -785,6 +880,18 @@ ECHO Done
+
+
+
+
+
+
+
+
@@ -827,6 +934,12 @@ ECHO Done
+
+
+
+
@@ -842,6 +955,12 @@ ECHO Done
+
+
+
+
+
+
+
+
@@ -868,6 +993,9 @@ ECHO Done
+
+
@@ -886,6 +1014,9 @@ ECHO Done
+
+
@@ -904,9 +1035,6 @@ ECHO Done
-
-
@@ -920,6 +1048,58 @@ ECHO Done
RelativePath="..\..\src\LinearMath\btVector3.h">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/extern/bullet2/readme.txt b/extern/bullet2/readme.txt
index 4d1a4c11706..02430cb5c0e 100644
--- a/extern/bullet2/readme.txt
+++ b/extern/bullet2/readme.txt
@@ -1,3 +1,8 @@
+***
+Apply bullet_compound_raycast.patch if not already applied in Bullet source
+This patch is needed to return correct raycast results on compound shape.
+/ben
+
*** These files in extern/bullet2 are NOT part of the Blender build yet ***
diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h
index 078dcae63bb..8074aed3038 100644
--- a/extern/bullet2/src/Bullet-C-Api.h
+++ b/extern/bullet2/src/Bullet-C-Api.h
@@ -23,15 +23,153 @@ subject to the following restrictions:
#ifndef BULLET_C_API_H
#define BULLET_C_API_H
+#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+#ifdef BT_USE_DOUBLE_PRECISION
+typedef double plReal;
+#else
+typedef float plReal;
+#endif
+
+typedef plReal plVector3[3];
+typedef plReal plQuaternion[4];
+
#ifdef __cplusplus
extern "C" {
#endif
-double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]);
+/* Particular physics SDK */
+ PL_DECLARE_HANDLE(plPhysicsSdkHandle);
+
+/* Dynamics world, belonging to some physics SDK */
+ PL_DECLARE_HANDLE(plDynamicsWorldHandle);
+
+/* Rigid Body that can be part of a Dynamics World */
+ PL_DECLARE_HANDLE(plRigidBodyHandle);
+
+/* Collision Shape/Geometry, property of a Rigid Body */
+ PL_DECLARE_HANDLE(plCollisionShapeHandle);
+
+/* Constraint for Rigid Bodies */
+ PL_DECLARE_HANDLE(plConstraintHandle);
+
+/* Triangle Mesh interface */
+ PL_DECLARE_HANDLE(plMeshInterfaceHandle);
+
+/* Broadphase Scene/Proxy Handles */
+ PL_DECLARE_HANDLE(plCollisionBroadphaseHandle);
+ PL_DECLARE_HANDLE(plBroadphaseProxyHandle);
+ PL_DECLARE_HANDLE(plCollisionWorldHandle);
+
+/*
+ Create and Delete a Physics SDK
+*/
+
+ extern plPhysicsSdkHandle plNewBulletSdk(); //this could be also another sdk, like ODE, PhysX etc.
+ extern void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk);
+
+/* Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */
+
+ typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2);
+
+ extern plCollisionBroadphaseHandle plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback);
+
+ extern void plDestroyBroadphase(plCollisionBroadphaseHandle bp);
+
+ extern plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
+
+ extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle);
+
+ extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
+
+/* todo: add pair cache support with queries like add/remove/find pair */
+
+ extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk);
+
+/* todo: add/remove objects */
+
+
+/* Dynamics World */
+
+ extern plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk);
+
+ extern void plDeleteDynamicsWorld(plDynamicsWorldHandle world);
+
+ extern void plStepSimulation(plDynamicsWorldHandle, plReal timeStep);
+
+ extern void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
+
+ extern void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
+
+
+/* Rigid Body */
+
+ extern plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape );
+
+ extern void plDeleteRigidBody(plRigidBodyHandle body);
+
+
+/* Collision Shape definition */
+
+ extern plCollisionShapeHandle plNewSphereShape(plReal radius);
+ extern plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z);
+ extern plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height);
+ extern plCollisionShapeHandle plNewConeShape(plReal radius, plReal height);
+ extern plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height);
+ extern plCollisionShapeHandle plNewCompoundShape();
+ extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn);
+
+ extern void plDeleteShape(plCollisionShapeHandle shape);
+
+ /* Convex Meshes */
+ extern plCollisionShapeHandle plNewConvexHullShape();
+ extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z);
+/* Concave static triangle meshes */
+ extern plMeshInterfaceHandle plNewMeshInterface();
+ extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2);
+ extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle);
+
+ extern void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling);
+
+/* SOLID has Response Callback/Table/Management */
+/* PhysX has Triggers, User Callbacks and filtering */
+/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */
+
+/* typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle rbHandle, plVector3 pos); */
+/* typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle rbHandle, plQuaternion orientation); */
+
+ /* get world transform */
+ extern void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
+ extern void plGetPosition(plRigidBodyHandle object,plVector3 position);
+ extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation);
+
+ /* set world transform (position/orientation) */
+ extern void plSetPosition(plRigidBodyHandle object, const plVector3 position);
+ extern void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation);
+ extern void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient);
+
+ typedef struct plRayCastResult {
+ plRigidBodyHandle m_body;
+ plCollisionShapeHandle m_shape;
+ plVector3 m_positionWorld;
+ plVector3 m_normalWorld;
+ } plRayCastResult;
+
+ extern int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res);
+
+ /* Sweep API */
+
+ /* extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */
+
+ /* Continuous Collision Detection API */
+
+ // needed for source/blender/blenkernel/intern/collision.c
+ double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]);
#ifdef __cplusplus
}
#endif
+
#endif //BULLET_C_API_H
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
index be4a11506df..d7eea33ea41 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
@@ -21,640 +21,18 @@
#include
-#ifdef DEBUG_BROADPHASE
-#include
-void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality)
+btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache)
+:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache)
{
- int numEdges = m_pHandles[0].m_maxEdges[axis];
- printf("SAP Axis %d, numEdges=%d\n",axis,numEdges);
-
- int i;
- for (i=0;im_handle);
- int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
- char beginOrEnd;
- beginOrEnd=pEdge->IsMax()?'E':'B';
- printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex);
- }
-
- if (checkCardinality)
- assert(numEdges == m_numHandles*2+1);
-}
-#endif //DEBUG_BROADPHASE
-
-
-btBroadphaseProxy* btAxisSweep3::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask)
-{
- (void)shapeType;
- BP_FP_INT_TYPE handleId = addHandle(min,max, userPtr,collisionFilterGroup,collisionFilterMask);
-
- Handle* handle = getHandle(handleId);
-
- return handle;
-}
-
-void btAxisSweep3::destroyProxy(btBroadphaseProxy* proxy)
-{
- Handle* handle = static_cast(proxy);
- removeHandle(handle->m_handleId);
-}
-
-void btAxisSweep3::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)
-{
- Handle* handle = static_cast(proxy);
- updateHandle(handle->m_handleId,aabbMin,aabbMax);
-
-}
-
-
-
-
-
-
-btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles)
-:btOverlappingPairCache()
-{
- m_invalidPair = 0;
- //assert(bounds.HasVolume());
-
// 1 handle is reserved as sentinel
- btAssert(maxHandles > 1 && maxHandles < BP_MAX_HANDLES);
-
- // init bounds
- m_worldAabbMin = worldAabbMin;
- m_worldAabbMax = worldAabbMax;
-
- btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
-
- BP_FP_INT_TYPE maxInt = BP_HANDLE_SENTINEL;
-
- m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
-
- // allocate handles buffer and put all handles on free list
- m_pHandles = new Handle[maxHandles];
- m_maxHandles = maxHandles;
- m_numHandles = 0;
-
- // handle 0 is reserved as the null index, and is also used as the sentinel
- m_firstFreeHandle = 1;
- {
- for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++)
- m_pHandles[i].SetNextFree(i + 1);
- m_pHandles[maxHandles - 1].SetNextFree(0);
- }
-
- {
- // allocate edge buffers
- for (int i = 0; i < 3; i++)
- m_pEdges[i] = new Edge[maxHandles * 2];
- }
- //removed overlap management
-
- // make boundary sentinels
-
- m_pHandles[0].m_clientObject = 0;
-
- for (int axis = 0; axis < 3; axis++)
- {
- m_pHandles[0].m_minEdges[axis] = 0;
- m_pHandles[0].m_maxEdges[axis] = 1;
-
- m_pEdges[axis][0].m_pos = 0;
- m_pEdges[axis][0].m_handle = 0;
- m_pEdges[axis][1].m_pos = BP_HANDLE_SENTINEL;
- m_pEdges[axis][1].m_handle = 0;
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
-
- }
+ btAssert(maxHandles > 1 && maxHandles < 32767);
}
-btAxisSweep3::~btAxisSweep3()
+
+bt32BitAxisSweep3::bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache )
+:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache)
{
-
- for (int i = 2; i >= 0; i--)
- delete[] m_pEdges[i];
- delete[] m_pHandles;
-}
-
-void btAxisSweep3::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const
-{
- btPoint3 clampedPoint(point);
-
-
-
- clampedPoint.setMax(m_worldAabbMin);
- clampedPoint.setMin(m_worldAabbMax);
-
- btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize;
- out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & BP_HANDLE_MASK) | isMax);
- out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & BP_HANDLE_MASK) | isMax);
- out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & BP_HANDLE_MASK) | isMax);
-
-}
-
-
-
-BP_FP_INT_TYPE btAxisSweep3::allocHandle()
-{
- assert(m_firstFreeHandle);
-
- BP_FP_INT_TYPE handle = m_firstFreeHandle;
- m_firstFreeHandle = getHandle(handle)->GetNextFree();
- m_numHandles++;
-
- return handle;
-}
-
-void btAxisSweep3::freeHandle(BP_FP_INT_TYPE handle)
-{
- assert(handle > 0 && handle < m_maxHandles);
-
- getHandle(handle)->SetNextFree(m_firstFreeHandle);
- m_firstFreeHandle = handle;
-
- m_numHandles--;
-}
-
-
-
-BP_FP_INT_TYPE btAxisSweep3::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask)
-{
- // quantize the bounds
- BP_FP_INT_TYPE min[3], max[3];
- quantize(min, aabbMin, 0);
- quantize(max, aabbMax, 1);
-
- // allocate a handle
- BP_FP_INT_TYPE handle = allocHandle();
- assert(handle!= 0xcdcd);
-
- Handle* pHandle = getHandle(handle);
-
- pHandle->m_handleId = handle;
- //pHandle->m_pOverlaps = 0;
- pHandle->m_clientObject = pOwner;
- pHandle->m_collisionFilterGroup = collisionFilterGroup;
- pHandle->m_collisionFilterMask = collisionFilterMask;
-
- // compute current limit of edge arrays
- BP_FP_INT_TYPE limit = m_numHandles * 2;
-
-
- // insert new edges just inside the max boundary edge
- for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
- {
-
- m_pHandles[0].m_maxEdges[axis] += 2;
-
- m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
-
- m_pEdges[axis][limit - 1].m_pos = min[axis];
- m_pEdges[axis][limit - 1].m_handle = handle;
-
- m_pEdges[axis][limit].m_pos = max[axis];
- m_pEdges[axis][limit].m_handle = handle;
-
- pHandle->m_minEdges[axis] = limit - 1;
- pHandle->m_maxEdges[axis] = limit;
- }
-
- // now sort the new edges to their correct position
- sortMinDown(0, pHandle->m_minEdges[0], false);
- sortMaxDown(0, pHandle->m_maxEdges[0], false);
- sortMinDown(1, pHandle->m_minEdges[1], false);
- sortMaxDown(1, pHandle->m_maxEdges[1], false);
- sortMinDown(2, pHandle->m_minEdges[2], true);
- sortMaxDown(2, pHandle->m_maxEdges[2], true);
-
-
- return handle;
-}
-
-
-void btAxisSweep3::removeHandle(BP_FP_INT_TYPE handle)
-{
-
- Handle* pHandle = getHandle(handle);
-
- //explicitly remove the pairs containing the proxy
- //we could do it also in the sortMinUp (passing true)
- //todo: compare performance
- removeOverlappingPairsContainingProxy(pHandle);
-
-
- // compute current limit of edge arrays
- int limit = m_numHandles * 2;
-
- int axis;
-
- for (axis = 0;axis<3;axis++)
- {
- m_pHandles[0].m_maxEdges[axis] -= 2;
- }
-
- // remove the edges by sorting them up to the end of the list
- for ( axis = 0; axis < 3; axis++)
- {
- Edge* pEdges = m_pEdges[axis];
- BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
- pEdges[max].m_pos = BP_HANDLE_SENTINEL;
-
- sortMaxUp(axis,max,false);
-
-
- BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
- pEdges[i].m_pos = BP_HANDLE_SENTINEL;
-
-
- sortMinUp(axis,i,false);
-
- pEdges[limit-1].m_handle = 0;
- pEdges[limit-1].m_pos = BP_HANDLE_SENTINEL;
-
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis,false);
-#endif //DEBUG_BROADPHASE
-
-
- }
-
-
- // free the handle
- freeHandle(handle);
-
-
-}
-
-extern int gOverlappingPairs;
-
-
-void btAxisSweep3::refreshOverlappingPairs()
-{
-
-}
-void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback)
-{
-
- //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
- m_overlappingPairArray.heapSort(btBroadphasePairSortPredicate());
-
- //remove the 'invalid' ones
-#ifdef USE_POPBACK_REMOVAL
- while (m_invalidPair>0)
- {
- m_invalidPair--;
- m_overlappingPairArray.pop_back();
- }
-#else
- m_overlappingPairArray.resize(m_overlappingPairArray.size() - m_invalidPair);
- m_invalidPair = 0;
-#endif
-
-
- int i;
-
- btBroadphasePair previousPair;
- previousPair.m_pProxy0 = 0;
- previousPair.m_pProxy1 = 0;
- previousPair.m_algorithm = 0;
-
-
- for (i=0;iprocessOverlap(pair);
- } else
- {
- needsRemoval = true;
- }
- } else
- {
- //remove duplicate
- needsRemoval = true;
- //should have no algorithm
- btAssert(!pair.m_algorithm);
- }
-
- if (needsRemoval)
- {
- cleanOverlappingPair(pair);
-
- // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
- // m_overlappingPairArray.pop_back();
- pair.m_pProxy0 = 0;
- pair.m_pProxy1 = 0;
- m_invalidPair++;
- gOverlappingPairs--;
- }
-
- }
-}
-
-
-bool btAxisSweep3::testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
-{
- const Handle* pHandleA = static_cast(proxy0);
- const Handle* pHandleB = static_cast(proxy1);
-
- //optimization 1: check the array index (memory address), instead of the m_pos
-
- for (int axis = 0; axis < 3; axis++)
- {
- if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
- pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
- {
- return false;
- }
- }
- return true;
-}
-
-bool btAxisSweep3::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB)
-{
- //optimization 1: check the array index (memory address), instead of the m_pos
-
- for (int axis = 0; axis < 3; axis++)
- {
- if (axis != ignoreAxis)
- {
- if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
- pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
- {
- return false;
- }
- }
- }
-
- //optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization)
-
- /*for (int axis = 0; axis < 3; axis++)
- {
- if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos ||
- m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos)
- {
- return false;
- }
- }
- */
-
- return true;
-}
-
-void btAxisSweep3::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax)
-{
-// assert(bounds.IsFinite());
- //assert(bounds.HasVolume());
-
- Handle* pHandle = getHandle(handle);
-
- // quantize the new bounds
- BP_FP_INT_TYPE min[3], max[3];
- quantize(min, aabbMin, 0);
- quantize(max, aabbMax, 1);
-
- // update changed edges
- for (int axis = 0; axis < 3; axis++)
- {
- BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
- BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
-
- int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos;
- int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos;
-
- m_pEdges[axis][emin].m_pos = min[axis];
- m_pEdges[axis][emax].m_pos = max[axis];
-
- // expand (only adds overlaps)
- if (dmin < 0)
- sortMinDown(axis, emin);
-
- if (dmax > 0)
- sortMaxUp(axis, emax);
-
- // shrink (only removes overlaps)
- if (dmin > 0)
- sortMinUp(axis, emin);
-
- if (dmax < 0)
- sortMaxDown(axis, emax);
-
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
- }
-
-
-}
-
-
-
-
-// sorting a min edge downwards can only ever *add* overlaps
-void btAxisSweep3::sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps)
-{
-
- Edge* pEdge = m_pEdges[axis] + edge;
- Edge* pPrev = pEdge - 1;
- Handle* pHandleEdge = getHandle(pEdge->m_handle);
-
- while (pEdge->m_pos < pPrev->m_pos)
- {
- Handle* pHandlePrev = getHandle(pPrev->m_handle);
-
- if (pPrev->IsMax())
- {
- // if previous edge is a maximum check the bounds and add an overlap if necessary
- if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev))
- {
- addOverlappingPair(pHandleEdge,pHandlePrev);
-
- //AddOverlap(pEdge->m_handle, pPrev->m_handle);
-
- }
-
- // update edge reference in other handle
- pHandlePrev->m_maxEdges[axis]++;
- }
- else
- pHandlePrev->m_minEdges[axis]++;
-
- pHandleEdge->m_minEdges[axis]--;
-
- // swap the edges
- Edge swap = *pEdge;
- *pEdge = *pPrev;
- *pPrev = swap;
-
- // decrement
- pEdge--;
- pPrev--;
- }
-
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
-
-}
-
-// sorting a min edge upwards can only ever *remove* overlaps
-void btAxisSweep3::sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps)
-{
- Edge* pEdge = m_pEdges[axis] + edge;
- Edge* pNext = pEdge + 1;
- Handle* pHandleEdge = getHandle(pEdge->m_handle);
-
- while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
- {
- Handle* pHandleNext = getHandle(pNext->m_handle);
-
- if (pNext->IsMax())
- {
- // if next edge is maximum remove any overlap between the two handles
- if (updateOverlaps)
- {
- /*
- Handle* handle0 = getHandle(pEdge->m_handle);
- Handle* handle1 = getHandle(pNext->m_handle);
- btBroadphasePair tmpPair(*handle0,*handle1);
- removeOverlappingPair(tmpPair);
- */
-
- }
-
- // update edge reference in other handle
- pHandleNext->m_maxEdges[axis]--;
- }
- else
- pHandleNext->m_minEdges[axis]--;
-
- pHandleEdge->m_minEdges[axis]++;
-
- // swap the edges
- Edge swap = *pEdge;
- *pEdge = *pNext;
- *pNext = swap;
-
- // increment
- pEdge++;
- pNext++;
- }
-
-
-}
-
-// sorting a max edge downwards can only ever *remove* overlaps
-void btAxisSweep3::sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps)
-{
-
- Edge* pEdge = m_pEdges[axis] + edge;
- Edge* pPrev = pEdge - 1;
- Handle* pHandleEdge = getHandle(pEdge->m_handle);
-
- while (pEdge->m_pos < pPrev->m_pos)
- {
- Handle* pHandlePrev = getHandle(pPrev->m_handle);
-
- if (!pPrev->IsMax())
- {
- // if previous edge was a minimum remove any overlap between the two handles
- if (updateOverlaps)
- {
- //this is done during the overlappingpairarray iteration/narrowphase collision
- /*
- Handle* handle0 = getHandle(pEdge->m_handle);
- Handle* handle1 = getHandle(pPrev->m_handle);
- btBroadphasePair* pair = findPair(handle0,handle1);
- //assert(pair);
-
- if (pair)
- {
- removeOverlappingPair(*pair);
- }
- */
-
- }
-
- // update edge reference in other handle
- pHandlePrev->m_minEdges[axis]++;;
- }
- else
- pHandlePrev->m_maxEdges[axis]++;
-
- pHandleEdge->m_maxEdges[axis]--;
-
- // swap the edges
- Edge swap = *pEdge;
- *pEdge = *pPrev;
- *pPrev = swap;
-
- // decrement
- pEdge--;
- pPrev--;
- }
-
-
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
-
-}
-
-// sorting a max edge upwards can only ever *add* overlaps
-void btAxisSweep3::sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps)
-{
- Edge* pEdge = m_pEdges[axis] + edge;
- Edge* pNext = pEdge + 1;
- Handle* pHandleEdge = getHandle(pEdge->m_handle);
-
- while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
- {
- Handle* pHandleNext = getHandle(pNext->m_handle);
-
- if (!pNext->IsMax())
- {
- // if next edge is a minimum check the bounds and add an overlap if necessary
- if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext))
- {
- Handle* handle0 = getHandle(pEdge->m_handle);
- Handle* handle1 = getHandle(pNext->m_handle);
- addOverlappingPair(handle0,handle1);
- }
-
- // update edge reference in other handle
- pHandleNext->m_minEdges[axis]--;
- }
- else
- pHandleNext->m_maxEdges[axis]--;
-
- pHandleEdge->m_maxEdges[axis]++;
-
- // swap the edges
- Edge swap = *pEdge;
- *pEdge = *pNext;
- *pNext = swap;
-
- // increment
- pEdge++;
- pNext++;
- }
-
+ // 1 handle is reserved as sentinel
+ btAssert(maxHandles > 1 && maxHandles < 2147483647);
}
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
index 57bbb368672..d0ad09a385a 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
@@ -19,34 +19,26 @@
#ifndef AXIS_SWEEP_3_H
#define AXIS_SWEEP_3_H
-#include "../../LinearMath/btPoint3.h"
-#include "../../LinearMath/btVector3.h"
+#include "LinearMath/btPoint3.h"
+#include "LinearMath/btVector3.h"
#include "btOverlappingPairCache.h"
+#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
-
-
-//Enable BP_USE_FIXEDPOINT_INT_32 if you need more then 32767 objects
-//#define BP_USE_FIXEDPOINT_INT_32 1
-
-#ifdef BP_USE_FIXEDPOINT_INT_32
- #define BP_FP_INT_TYPE unsigned int
- #define BP_MAX_HANDLES 1500000 //arbitrary maximum number of handles
- #define BP_HANDLE_SENTINEL 0x7fffffff
- #define BP_HANDLE_MASK 0xfffffffe
-#else
- #define BP_FP_INT_TYPE unsigned short int
- #define BP_MAX_HANDLES 32767
- #define BP_HANDLE_SENTINEL 0xffff
- #define BP_HANDLE_MASK 0xfffe
-#endif //BP_USE_FIXEDPOINT_INT_32
+#include "btOverlappingPairCallback.h"
//#define DEBUG_BROADPHASE 1
+#define USE_OVERLAP_TEST_ON_REMOVES 1
-/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
-/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using integer coordinates instead of floats.
-/// The testOverlap check is optimized to check the array index, rather then the actual AABB coordinates/pos
-class btAxisSweep3 : public btOverlappingPairCache
+/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
+/// It uses quantized integers to represent the begin and end points for each of the 3 axis.
+/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
+template
+class btAxisSweep3Internal : public btBroadphaseInterface
{
+protected:
+
+ BP_FP_INT_TYPE m_bpHandleMask;
+ BP_FP_INT_TYPE m_handleSentinel;
public:
@@ -57,47 +49,57 @@ public:
BP_FP_INT_TYPE m_pos; // low bit is min/max
BP_FP_INT_TYPE m_handle;
- BP_FP_INT_TYPE IsMax() const {return m_pos & 1;}
+ BP_FP_INT_TYPE IsMax() const {return static_cast(m_pos & 1);}
};
public:
- class Handle : public btBroadphaseProxy
+ class Handle : public btBroadphaseProxy
{
public:
-
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
// indexes into the edge arrays
BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12
- BP_FP_INT_TYPE m_handleId;
+// BP_FP_INT_TYPE m_uniqueId;
BP_FP_INT_TYPE m_pad;
//void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
- inline void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
- inline BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
+ SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
+ SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
}; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
-private:
+protected:
btPoint3 m_worldAabbMin; // overall system bounds
btPoint3 m_worldAabbMax; // overall system bounds
btVector3 m_quantize; // scaling factor for quantization
BP_FP_INT_TYPE m_numHandles; // number of active handles
- int m_maxHandles; // max number of handles
+ BP_FP_INT_TYPE m_maxHandles; // max number of handles
Handle* m_pHandles; // handles pool
+
BP_FP_INT_TYPE m_firstFreeHandle; // free handles list
Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
+ void* m_pEdgesRawPtr[3];
- int m_invalidPair;
+ btOverlappingPairCache* m_pairCache;
+
+ ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
+ btOverlappingPairCallback* m_userPairCallback;
+
+ bool m_ownsPairCache;
+
+ int m_invalidPair;
// allocation/deallocation
BP_FP_INT_TYPE allocHandle();
void freeHandle(BP_FP_INT_TYPE handle);
- bool testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB);
+ bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1);
#ifdef DEBUG_BROADPHASE
void debugPrintAxis(int axis,bool checkCardinality=true);
@@ -108,29 +110,803 @@ private:
void quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const;
- void sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true);
- void sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true);
- void sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true);
- void sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true);
+ void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+ void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+ void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+ void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
public:
- btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles = 16384);
- virtual ~btAxisSweep3();
- virtual void refreshOverlappingPairs();
+ btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0);
+
+ virtual ~btAxisSweep3Internal();
+
+ BP_FP_INT_TYPE getNumHandles() const
+ {
+ return m_numHandles;
+ }
+
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
- BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask);
- void removeHandle(BP_FP_INT_TYPE handle);
- void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax);
- inline Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
+ BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
+ void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher);
+ void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher);
+ SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
void processAllOverlappingPairs(btOverlapCallback* callback);
//Broadphase Interface
- virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask);
- virtual void destroyProxy(btBroadphaseProxy* proxy);
- virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax);
- bool testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* 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 void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+
+ bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+ btOverlappingPairCache* getOverlappingPairCache()
+ {
+ return m_pairCache;
+ }
+ const btOverlappingPairCache* getOverlappingPairCache() const
+ {
+ return m_pairCache;
+ }
+
+ void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
+ {
+ m_userPairCallback = pairCallback;
+ }
+ const btOverlappingPairCallback* getOverlappingPairUserCallback() const
+ {
+ return m_userPairCallback;
+ }
+
+ ///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 = m_worldAabbMin;
+ aabbMax = m_worldAabbMax;
+ }
+
+ virtual void printStats()
+ {
+/* printf("btAxisSweep3.h\n");
+ printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+ printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
+ m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
+ */
+
+ }
+
+};
+
+////////////////////////////////////////////////////////////////////
+
+
+
+
+#ifdef DEBUG_BROADPHASE
+#include
+
+template
+void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality)
+{
+ int numEdges = m_pHandles[0].m_maxEdges[axis];
+ printf("SAP Axis %d, numEdges=%d\n",axis,numEdges);
+
+ int i;
+ for (i=0;im_handle);
+ int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
+ char beginOrEnd;
+ beginOrEnd=pEdge->IsMax()?'E':'B';
+ printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex);
+ }
+
+ if (checkCardinality)
+ assert(numEdges == m_numHandles*2+1);
+}
+#endif //DEBUG_BROADPHASE
+
+template
+btBroadphaseProxy* btAxisSweep3Internal::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
+{
+ (void)shapeType;
+ BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy);
+
+ Handle* handle = getHandle(handleId);
+
+ return handle;
+}
+
+
+
+template
+void btAxisSweep3Internal::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+ Handle* handle = static_cast(proxy);
+ removeHandle(static_cast(handle->m_uniqueId), dispatcher);
+}
+
+template
+void btAxisSweep3Internal::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
+{
+ Handle* handle = static_cast(proxy);
+ updateHandle(static_cast(handle->m_uniqueId), aabbMin, aabbMax,dispatcher);
+
+}
+
+
+
+
+
+template
+btAxisSweep3Internal::btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache )
+:m_bpHandleMask(handleMask),
+m_handleSentinel(handleSentinel),
+m_pairCache(pairCache),
+m_userPairCallback(0),
+m_ownsPairCache(false),
+m_invalidPair(0)
+{
+ BP_FP_INT_TYPE maxHandles = static_cast(userMaxHandles+1);//need to add one sentinel handle
+
+ if (!m_pairCache)
+ {
+ void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
+ m_pairCache = new(ptr) btHashedOverlappingPairCache();
+ m_ownsPairCache = true;
+ }
+
+ //assert(bounds.HasVolume());
+
+ // init bounds
+ m_worldAabbMin = worldAabbMin;
+ m_worldAabbMax = worldAabbMax;
+
+ btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
+
+ BP_FP_INT_TYPE maxInt = m_handleSentinel;
+
+ m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
+
+ // allocate handles buffer, using btAlignedAlloc, and put all handles on free list
+ m_pHandles = new Handle[maxHandles];
+
+ m_maxHandles = maxHandles;
+ m_numHandles = 0;
+
+ // handle 0 is reserved as the null index, and is also used as the sentinel
+ m_firstFreeHandle = 1;
+ {
+ for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++)
+ m_pHandles[i].SetNextFree(static_cast(i + 1));
+ m_pHandles[maxHandles - 1].SetNextFree(0);
+ }
+
+ {
+ // allocate edge buffers
+ for (int i = 0; i < 3; i++)
+ {
+ m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16);
+ m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
+ }
+ }
+ //removed overlap management
+
+ // make boundary sentinels
+
+ m_pHandles[0].m_clientObject = 0;
+
+ for (int axis = 0; axis < 3; axis++)
+ {
+ m_pHandles[0].m_minEdges[axis] = 0;
+ m_pHandles[0].m_maxEdges[axis] = 1;
+
+ m_pEdges[axis][0].m_pos = 0;
+ m_pEdges[axis][0].m_handle = 0;
+ m_pEdges[axis][1].m_pos = m_handleSentinel;
+ m_pEdges[axis][1].m_handle = 0;
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+ }
+
+}
+
+template
+btAxisSweep3Internal::~btAxisSweep3Internal()
+{
+
+ for (int i = 2; i >= 0; i--)
+ {
+ btAlignedFree(m_pEdgesRawPtr[i]);
+ }
+ delete [] m_pHandles;
+
+ if (m_ownsPairCache)
+ {
+ m_pairCache->~btOverlappingPairCache();
+ btAlignedFree(m_pairCache);
+ }
+}
+
+template
+void btAxisSweep3Internal::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const
+{
+ btPoint3 clampedPoint(point);
+
+
+
+ clampedPoint.setMax(m_worldAabbMin);
+ clampedPoint.setMin(m_worldAabbMax);
+
+ btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize;
+ out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax);
+ out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax);
+ out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax);
+
+}
+
+
+template
+BP_FP_INT_TYPE btAxisSweep3Internal::allocHandle()
+{
+ assert(m_firstFreeHandle);
+
+ BP_FP_INT_TYPE handle = m_firstFreeHandle;
+ m_firstFreeHandle = getHandle(handle)->GetNextFree();
+ m_numHandles++;
+
+ return handle;
+}
+
+template
+void btAxisSweep3Internal::freeHandle(BP_FP_INT_TYPE handle)
+{
+ assert(handle > 0 && handle < m_maxHandles);
+
+ getHandle(handle)->SetNextFree(m_firstFreeHandle);
+ m_firstFreeHandle = handle;
+
+ m_numHandles--;
+}
+
+
+template
+BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
+{
+ // quantize the bounds
+ BP_FP_INT_TYPE min[3], max[3];
+ quantize(min, aabbMin, 0);
+ quantize(max, aabbMax, 1);
+
+ // allocate a handle
+ BP_FP_INT_TYPE handle = allocHandle();
+
+
+ Handle* pHandle = getHandle(handle);
+
+ pHandle->m_uniqueId = static_cast(handle);
+ //pHandle->m_pOverlaps = 0;
+ pHandle->m_clientObject = pOwner;
+ pHandle->m_collisionFilterGroup = collisionFilterGroup;
+ pHandle->m_collisionFilterMask = collisionFilterMask;
+ pHandle->m_multiSapParentProxy = multiSapProxy;
+
+ // compute current limit of edge arrays
+ BP_FP_INT_TYPE limit = static_cast(m_numHandles * 2);
+
+
+ // insert new edges just inside the max boundary edge
+ for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
+ {
+
+ m_pHandles[0].m_maxEdges[axis] += 2;
+
+ m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
+
+ m_pEdges[axis][limit - 1].m_pos = min[axis];
+ m_pEdges[axis][limit - 1].m_handle = handle;
+
+ m_pEdges[axis][limit].m_pos = max[axis];
+ m_pEdges[axis][limit].m_handle = handle;
+
+ pHandle->m_minEdges[axis] = static_cast(limit - 1);
+ pHandle->m_maxEdges[axis] = limit;
+ }
+
+ // now sort the new edges to their correct position
+ sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false);
+ sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false);
+ sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false);
+ sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false);
+ sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true);
+ sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true);
+
+
+ return handle;
+}
+
+
+template
+void btAxisSweep3Internal::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher)
+{
+
+ Handle* pHandle = getHandle(handle);
+
+ //explicitly remove the pairs containing the proxy
+ //we could do it also in the sortMinUp (passing true)
+ //todo: compare performance
+ if (!m_pairCache->hasDeferredRemoval())
+ {
+ m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher);
+ }
+
+ // compute current limit of edge arrays
+ int limit = static_cast(m_numHandles * 2);
+
+ int axis;
+
+ for (axis = 0;axis<3;axis++)
+ {
+ m_pHandles[0].m_maxEdges[axis] -= 2;
+ }
+
+ // remove the edges by sorting them up to the end of the list
+ for ( axis = 0; axis < 3; axis++)
+ {
+ Edge* pEdges = m_pEdges[axis];
+ BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
+ pEdges[max].m_pos = m_handleSentinel;
+
+ sortMaxUp(axis,max,dispatcher,false);
+
+
+ BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
+ pEdges[i].m_pos = m_handleSentinel;
+
+
+ sortMinUp(axis,i,dispatcher,false);
+
+ pEdges[limit-1].m_handle = 0;
+ pEdges[limit-1].m_pos = m_handleSentinel;
+
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis,false);
+#endif //DEBUG_BROADPHASE
+
+
+ }
+
+
+ // free the handle
+ freeHandle(handle);
+
+
+}
+
+extern int gOverlappingPairs;
+//#include
+
+template
+void btAxisSweep3Internal::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+
+ if (m_pairCache->hasDeferredRemoval())
+ {
+
+ btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+ 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;iprocessOverlap(pair);
+ } else
+ {
+ needsRemoval = true;
+ }
+ } else
+ {
+ //remove duplicate
+ needsRemoval = true;
+ //should have no algorithm
+ btAssert(!pair.m_algorithm);
+ }
+
+ if (needsRemoval)
+ {
+ m_pairCache->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.quickSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+ #endif//CLEAN_INVALID_PAIRS
+
+ //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
+ }
+
+
+
+
+
+}
+
+
+template
+bool btAxisSweep3Internal::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ const Handle* pHandleA = static_cast(proxy0);
+ const Handle* pHandleB = static_cast(proxy1);
+
+ //optimization 1: check the array index (memory address), instead of the m_pos
+
+ for (int axis = 0; axis < 3; axis++)
+ {
+ if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
+ pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+template
+bool btAxisSweep3Internal::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1)
+{
+ //optimization 1: check the array index (memory address), instead of the m_pos
+
+ if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] ||
+ pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
+ pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
+ pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1])
+ {
+ return false;
+ }
+ return true;
+}
+
+template
+void btAxisSweep3Internal::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher)
+{
+// assert(bounds.IsFinite());
+ //assert(bounds.HasVolume());
+
+ Handle* pHandle = getHandle(handle);
+
+ // quantize the new bounds
+ BP_FP_INT_TYPE min[3], max[3];
+ quantize(min, aabbMin, 0);
+ quantize(max, aabbMax, 1);
+
+ // update changed edges
+ for (int axis = 0; axis < 3; axis++)
+ {
+ BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
+ BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
+
+ int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos;
+ int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos;
+
+ m_pEdges[axis][emin].m_pos = min[axis];
+ m_pEdges[axis][emax].m_pos = max[axis];
+
+ // expand (only adds overlaps)
+ if (dmin < 0)
+ sortMinDown(axis, emin,dispatcher,true);
+
+ if (dmax > 0)
+ sortMaxUp(axis, emax,dispatcher,true);
+
+ // shrink (only removes overlaps)
+ if (dmin > 0)
+ sortMinUp(axis, emin,dispatcher,true);
+
+ if (dmax < 0)
+ sortMaxDown(axis, emax,dispatcher,true);
+
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+ }
+
+
+}
+
+
+
+
+// sorting a min edge downwards can only ever *add* overlaps
+template
+void btAxisSweep3Internal::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
+{
+
+ Edge* pEdge = m_pEdges[axis] + edge;
+ Edge* pPrev = pEdge - 1;
+ Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+ while (pEdge->m_pos < pPrev->m_pos)
+ {
+ Handle* pHandlePrev = getHandle(pPrev->m_handle);
+
+ if (pPrev->IsMax())
+ {
+ // if previous edge is a maximum check the bounds and add an overlap if necessary
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+ if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2))
+ {
+ m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev);
+ if (m_userPairCallback)
+ m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev);
+
+ //AddOverlap(pEdge->m_handle, pPrev->m_handle);
+
+ }
+
+ // update edge reference in other handle
+ pHandlePrev->m_maxEdges[axis]++;
+ }
+ else
+ pHandlePrev->m_minEdges[axis]++;
+
+ pHandleEdge->m_minEdges[axis]--;
+
+ // swap the edges
+ Edge swap = *pEdge;
+ *pEdge = *pPrev;
+ *pPrev = swap;
+
+ // decrement
+ pEdge--;
+ pPrev--;
+ }
+
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+}
+
+// sorting a min edge upwards can only ever *remove* overlaps
+template
+void btAxisSweep3Internal::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
+{
+ Edge* pEdge = m_pEdges[axis] + edge;
+ Edge* pNext = pEdge + 1;
+ Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+ while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
+ {
+ Handle* pHandleNext = getHandle(pNext->m_handle);
+
+ if (pNext->IsMax())
+ {
+ Handle* handle0 = getHandle(pEdge->m_handle);
+ Handle* handle1 = getHandle(pNext->m_handle);
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+
+ // if next edge is maximum remove any overlap between the two handles
+ if (updateOverlaps
+#ifdef USE_OVERLAP_TEST_ON_REMOVES
+ && testOverlap2D(handle0,handle1,axis1,axis2)
+#endif //USE_OVERLAP_TEST_ON_REMOVES
+ )
+ {
+
+
+ m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
+ if (m_userPairCallback)
+ m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
+
+ }
+
+
+ // update edge reference in other handle
+ pHandleNext->m_maxEdges[axis]--;
+ }
+ else
+ pHandleNext->m_minEdges[axis]--;
+
+ pHandleEdge->m_minEdges[axis]++;
+
+ // swap the edges
+ Edge swap = *pEdge;
+ *pEdge = *pNext;
+ *pNext = swap;
+
+ // increment
+ pEdge++;
+ pNext++;
+ }
+
+
+}
+
+// sorting a max edge downwards can only ever *remove* overlaps
+template
+void btAxisSweep3Internal::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
+{
+
+ Edge* pEdge = m_pEdges[axis] + edge;
+ Edge* pPrev = pEdge - 1;
+ Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+ while (pEdge->m_pos < pPrev->m_pos)
+ {
+ Handle* pHandlePrev = getHandle(pPrev->m_handle);
+
+ if (!pPrev->IsMax())
+ {
+ // if previous edge was a minimum remove any overlap between the two handles
+ Handle* handle0 = getHandle(pEdge->m_handle);
+ Handle* handle1 = getHandle(pPrev->m_handle);
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+
+ if (updateOverlaps
+#ifdef USE_OVERLAP_TEST_ON_REMOVES
+ && testOverlap2D(handle0,handle1,axis1,axis2)
+#endif //USE_OVERLAP_TEST_ON_REMOVES
+ )
+ {
+ //this is done during the overlappingpairarray iteration/narrowphase collision
+
+
+ m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
+ if (m_userPairCallback)
+ m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
+
+
+
+ }
+
+ // update edge reference in other handle
+ pHandlePrev->m_minEdges[axis]++;;
+ }
+ else
+ pHandlePrev->m_maxEdges[axis]++;
+
+ pHandleEdge->m_maxEdges[axis]--;
+
+ // swap the edges
+ Edge swap = *pEdge;
+ *pEdge = *pPrev;
+ *pPrev = swap;
+
+ // decrement
+ pEdge--;
+ pPrev--;
+ }
+
+
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+}
+
+// sorting a max edge upwards can only ever *add* overlaps
+template
+void btAxisSweep3Internal::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
+{
+ Edge* pEdge = m_pEdges[axis] + edge;
+ Edge* pNext = pEdge + 1;
+ Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+ while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
+ {
+ Handle* pHandleNext = getHandle(pNext->m_handle);
+
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+
+ if (!pNext->IsMax())
+ {
+ // if next edge is a minimum check the bounds and add an overlap if necessary
+ if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2))
+ {
+ Handle* handle0 = getHandle(pEdge->m_handle);
+ Handle* handle1 = getHandle(pNext->m_handle);
+ m_pairCache->addOverlappingPair(handle0,handle1);
+ if (m_userPairCallback)
+ m_userPairCallback->addOverlappingPair(handle0,handle1);
+ }
+
+ // update edge reference in other handle
+ pHandleNext->m_minEdges[axis]--;
+ }
+ else
+ pHandleNext->m_maxEdges[axis]--;
+
+ pHandleEdge->m_maxEdges[axis]++;
+
+ // swap the edges
+ Edge swap = *pEdge;
+ *pEdge = *pNext;
+ *pNext = swap;
+
+ // increment
+ pEdge++;
+ pNext++;
+ }
+
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+
+
+/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
+/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats.
+/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance.
+class btAxisSweep3 : public btAxisSweep3Internal
+{
+public:
+
+ btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0);
+
+};
+
+/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune.
+/// This comes at the cost of more memory per handle, and a bit slower performance.
+/// It uses arrays rather then lists for storage of the 3 axis.
+class bt32BitAxisSweep3 : public btAxisSweep3Internal
+{
+public:
+
+ bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0);
};
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
index b6ace03c07a..200ac365329 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
@@ -20,20 +20,34 @@ subject to the following restrictions:
struct btDispatcherInfo;
class btDispatcher;
-struct btBroadphaseProxy;
-#include "../../LinearMath/btVector3.h"
+#include "btBroadphaseProxy.h"
+class btOverlappingPairCache;
-///BroadphaseInterface for aabb-overlapping object pairs
+#include "LinearMath/btVector3.h"
+
+///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs.
+///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase.
+///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class.
class btBroadphaseInterface
{
public:
virtual ~btBroadphaseInterface() {}
- virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) =0;
- virtual void destroyProxy(btBroadphaseProxy* proxy)=0;
- virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)=0;
- virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy)=0;
+ 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 void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0;
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
+ ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0;
+
+ virtual btOverlappingPairCache* getOverlappingPairCache()=0;
+ virtual const btOverlappingPairCache* getOverlappingPairCache() const =0;
+
+ ///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 =0;
+
+ virtual void printStats() = 0;
};
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
index 40d9748ffa9..e0bb67f8521 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
@@ -16,7 +16,8 @@ subject to the following restrictions:
#ifndef BROADPHASE_PROXY_H
#define BROADPHASE_PROXY_H
-#include "../../LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
+#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
+#include "LinearMath/btAlignedAllocator.h"
/// btDispatcher uses these types
@@ -38,6 +39,7 @@ IMPLICIT_CONVEX_SHAPES_START_HERE,
CONE_SHAPE_PROXYTYPE,
CONVEX_SHAPE_PROXYTYPE,
CYLINDER_SHAPE_PROXYTYPE,
+ UNIFORM_SCALING_SHAPE_PROXYTYPE,
MINKOWSKI_SUM_SHAPE_PROXYTYPE,
MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
//concave shapes
@@ -50,6 +52,8 @@ CONCAVE_SHAPES_START_HERE,
TERRAIN_SHAPE_PROXYTYPE,
///Used for GIMPACT Trimesh integration
GIMPACT_SHAPE_PROXYTYPE,
+///Multimaterial mesh
+ MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
EMPTY_SHAPE_PROXYTYPE,
STATIC_PLANE_PROXYTYPE,
@@ -57,13 +61,18 @@ CONCAVE_SHAPES_END_HERE,
COMPOUND_SHAPE_PROXYTYPE,
+ SOFTBODY_SHAPE_PROXYTYPE,
+
MAX_BROADPHASE_COLLISION_TYPES
};
-///btBroadphaseProxy
-struct btBroadphaseProxy
+///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
+///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
+ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
{
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
///optional filtering to cull potential collisions
enum CollisionFilterGroups
@@ -73,44 +82,60 @@ struct btBroadphaseProxy
KinematicFilter = 4,
DebrisFilter = 8,
SensorTrigger = 16,
- AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
+ AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
};
//Usually the client btCollisionObject or Rigidbody class
void* m_clientObject;
+
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
- //used for memory pools
- btBroadphaseProxy() :m_clientObject(0){}
+ void* m_multiSapParentProxy;
- btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask)
+
+ int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
+
+ SIMD_FORCE_INLINE int getUid() const
+ {
+ return m_uniqueId;
+ }
+
+ //used for memory pools
+ btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0)
+ {
+ }
+
+ btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0)
:m_clientObject(userPtr),
m_collisionFilterGroup(collisionFilterGroup),
m_collisionFilterMask(collisionFilterMask)
{
+ m_multiSapParentProxy = multiSapParentProxy;
}
- static inline bool isPolyhedral(int proxyType)
+
+
+ static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
{
return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
}
- static inline bool isConvex(int proxyType)
+ static SIMD_FORCE_INLINE bool isConvex(int proxyType)
{
return (proxyType < CONCAVE_SHAPES_START_HERE);
}
- static inline bool isConcave(int proxyType)
+ static SIMD_FORCE_INLINE bool isConcave(int proxyType)
{
return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
(proxyType < CONCAVE_SHAPES_END_HERE));
}
- static inline bool isCompound(int proxyType)
+ static SIMD_FORCE_INLINE bool isCompound(int proxyType)
{
return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
}
- static inline bool isInfinite(int proxyType)
+ static SIMD_FORCE_INLINE bool isInfinite(int proxyType)
{
return (proxyType == STATIC_PLANE_PROXYTYPE);
}
@@ -124,8 +149,9 @@ struct btBroadphaseProxy;
-/// contains a pair of aabb-overlapping objects
-struct btBroadphasePair
+///The btBroadphasePair class contains a pair of aabb-overlapping objects.
+///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes.
+ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
{
btBroadphasePair ()
:
@@ -136,6 +162,8 @@ struct btBroadphasePair
{
}
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
btBroadphasePair(const btBroadphasePair& other)
: m_pProxy0(other.m_pProxy0),
m_pProxy1(other.m_pProxy1),
@@ -181,6 +209,7 @@ SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePa
*/
+
class btBroadphasePairSortPredicate
{
public:
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
index 2ad0c86d8a2..c95d1be0f2c 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
@@ -18,6 +18,6 @@ subject to the following restrictions:
btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
{
- m_dispatcher = ci.m_dispatcher;
+ m_dispatcher = ci.m_dispatcher1;
}
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
index 55cec386a7b..1618ad9fdd3 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
@@ -16,7 +16,8 @@ subject to the following restrictions:
#ifndef COLLISION_ALGORITHM_H
#define COLLISION_ALGORITHM_H
-#include "../../LinearMath/btScalar.h"
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btAlignedObjectArray.h"
struct btBroadphaseProxy;
class btDispatcher;
@@ -25,21 +26,22 @@ class btCollisionObject;
struct btDispatcherInfo;
class btPersistentManifold;
+typedef btAlignedObjectArray btManifoldArray;
struct btCollisionAlgorithmConstructionInfo
{
btCollisionAlgorithmConstructionInfo()
- :m_dispatcher(0),
+ :m_dispatcher1(0),
m_manifold(0)
{
}
btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp)
- :m_dispatcher(dispatcher)
+ :m_dispatcher1(dispatcher)
{
(void)temp;
}
- btDispatcher* m_dispatcher;
+ btDispatcher* m_dispatcher1;
btPersistentManifold* m_manifold;
int getDispatcherId();
@@ -71,6 +73,7 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
};
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp
new file mode 100644
index 00000000000..7c41c8d8f71
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp
@@ -0,0 +1,1289 @@
+/*
+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.
+*/
+///btDbvt implementation by Nathanael Presson
+
+#include "btDbvt.h"
+
+//
+typedef btAlignedObjectArray tNodeArray;
+typedef btAlignedObjectArray tConstNodeArray;
+
+//
+struct btDbvtNodeEnumerator : btDbvt::ICollide
+{
+tConstNodeArray nodes;
+void Process(const btDbvtNode* n) { nodes.push_back(n); }
+};
+
+//
+static DBVT_INLINE int indexof(const btDbvtNode* node)
+{
+return(node->parent->childs[1]==node);
+}
+
+//
+static DBVT_INLINE btDbvtVolume merge( const btDbvtVolume& a,
+ const btDbvtVolume& b)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+DBVT_ALIGN char locals[sizeof(btDbvtAabbMm)];
+btDbvtVolume& res=*(btDbvtVolume*)locals;
+#else
+btDbvtVolume res;
+#endif
+Merge(a,b,res);
+return(res);
+}
+
+// volume+edge lengths
+static DBVT_INLINE btScalar size(const btDbvtVolume& a)
+{
+const btVector3 edges=a.Lengths();
+return( edges.x()*edges.y()*edges.z()+
+ edges.x()+edges.y()+edges.z());
+}
+
+//
+static void getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth)
+{
+if(node->isinternal())
+ {
+ getmaxdepth(node->childs[0],depth+1,maxdepth);
+ getmaxdepth(node->childs[0],depth+1,maxdepth);
+ } else maxdepth=btMax(maxdepth,depth);
+}
+
+//
+static DBVT_INLINE void deletenode( btDbvt* pdbvt,
+ btDbvtNode* node)
+{
+btAlignedFree(pdbvt->m_free);
+pdbvt->m_free=node;
+}
+
+//
+static void recursedeletenode( btDbvt* pdbvt,
+ btDbvtNode* node)
+{
+if(!node->isleaf())
+ {
+ recursedeletenode(pdbvt,node->childs[0]);
+ recursedeletenode(pdbvt,node->childs[1]);
+ }
+if(node==pdbvt->m_root) pdbvt->m_root=0;
+deletenode(pdbvt,node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
+ btDbvtNode* parent,
+ void* data)
+{
+btDbvtNode* node;
+if(pdbvt->m_free)
+ { node=pdbvt->m_free;pdbvt->m_free=0; }
+ else
+ { node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); }
+node->parent = parent;
+node->data = data;
+node->childs[1] = 0;
+return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
+ btDbvtNode* parent,
+ const btDbvtVolume& volume,
+ void* data)
+{
+btDbvtNode* node=createnode(pdbvt,parent,data);
+node->volume=volume;
+return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
+ btDbvtNode* parent,
+ const btDbvtVolume& volume0,
+ const btDbvtVolume& volume1,
+ void* data)
+{
+btDbvtNode* node=createnode(pdbvt,parent,data);
+Merge(volume0,volume1,node->volume);
+return(node);
+}
+
+//
+static void insertleaf( btDbvt* pdbvt,
+ btDbvtNode* root,
+ btDbvtNode* leaf)
+{
+if(!pdbvt->m_root)
+ {
+ pdbvt->m_root = leaf;
+ leaf->parent = 0;
+ }
+ else
+ {
+ if(!root->isleaf())
+ {
+ do {
+ root=root->childs[Select( leaf->volume,
+ root->childs[0]->volume,
+ root->childs[1]->volume)];
+ } while(!root->isleaf());
+ }
+ btDbvtNode* prev=root->parent;
+ btDbvtNode* node=createnode(pdbvt,prev,leaf->volume,root->volume,0);
+ if(prev)
+ {
+ prev->childs[indexof(root)] = node;
+ node->childs[0] = root;root->parent=node;
+ node->childs[1] = leaf;leaf->parent=node;
+ do {
+ if(!prev->volume.Contain(node->volume))
+ Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+ else
+ break;
+ node=prev;
+ } while(0!=(prev=node->parent));
+ }
+ else
+ {
+ node->childs[0] = root;root->parent=node;
+ node->childs[1] = leaf;leaf->parent=node;
+ pdbvt->m_root = node;
+ }
+ }
+}
+
+//
+static btDbvtNode* removeleaf( btDbvt* pdbvt,
+ btDbvtNode* leaf)
+{
+if(leaf==pdbvt->m_root)
+ {
+ pdbvt->m_root=0;
+ return(0);
+ }
+ else
+ {
+ btDbvtNode* parent=leaf->parent;
+ btDbvtNode* prev=parent->parent;
+ btDbvtNode* sibling=parent->childs[1-indexof(leaf)];
+ if(prev)
+ {
+ prev->childs[indexof(parent)]=sibling;
+ sibling->parent=prev;
+ deletenode(pdbvt,parent);
+ while(prev)
+ {
+ const btDbvtVolume pb=prev->volume;
+ Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+ if(NotEqual(pb,prev->volume))
+ {
+ prev=prev->parent;
+ } else break;
+ }
+ return(prev?prev:pdbvt->m_root);
+ }
+ else
+ {
+ pdbvt->m_root=sibling;
+ sibling->parent=0;
+ deletenode(pdbvt,parent);
+ return(pdbvt->m_root);
+ }
+ }
+}
+
+//
+static void fetchleaves(btDbvt* pdbvt,
+ btDbvtNode* root,
+ tNodeArray& leaves,
+ int depth=-1)
+{
+if(root->isinternal()&&depth)
+ {
+ fetchleaves(pdbvt,root->childs[0],leaves,depth-1);
+ fetchleaves(pdbvt,root->childs[1],leaves,depth-1);
+ deletenode(pdbvt,root);
+ }
+ else
+ {
+ leaves.push_back(root);
+ }
+}
+
+//
+static void split( const tNodeArray& leaves,
+ tNodeArray& left,
+ tNodeArray& right,
+ const btVector3& org,
+ const btVector3& axis)
+{
+left.resize(0);
+right.resize(0);
+for(int i=0,ni=leaves.size();ivolume.Center()-org)<0)
+ left.push_back(leaves[i]);
+ else
+ right.push_back(leaves[i]);
+ }
+}
+
+//
+static btDbvtVolume bounds( const tNodeArray& leaves)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+DBVT_ALIGN char locals[sizeof(btDbvtVolume)];
+btDbvtVolume& volume=*(btDbvtVolume*)locals;
+volume=leaves[0]->volume;
+#else
+btDbvtVolume volume=leaves[0]->volume;
+#endif
+for(int i=1,ni=leaves.size();ivolume,volume);
+ }
+return(volume);
+}
+
+//
+static void bottomup( btDbvt* pdbvt,
+ tNodeArray& leaves)
+{
+while(leaves.size()>1)
+ {
+ btScalar minsize=SIMD_INFINITY;
+ int minidx[2]={-1,-1};
+ for(int i=0;ivolume,leaves[j]->volume));
+ if(szvolume,n[1]->volume,0);
+ p->childs[0] = n[0];
+ p->childs[1] = n[1];
+ n[0]->parent = p;
+ n[1]->parent = p;
+ leaves[minidx[0]] = p;
+ leaves.swap(minidx[1],leaves.size()-1);
+ leaves.pop_back();
+ }
+}
+
+//
+static btDbvtNode* topdown(btDbvt* pdbvt,
+ tNodeArray& leaves,
+ int bu_treshold)
+{
+static const btVector3 axis[]={btVector3(1,0,0),
+ btVector3(0,1,0),
+ btVector3(0,0,1)};
+if(leaves.size()>1)
+ {
+ if(leaves.size()>bu_treshold)
+ {
+ const btDbvtVolume vol=bounds(leaves);
+ const btVector3 org=vol.Center();
+ tNodeArray sets[2];
+ int bestaxis=-1;
+ int bestmidp=leaves.size();
+ int splitcount[3][2]={{0,0},{0,0},{0,0}};
+ int i;
+ for( i=0;ivolume.Center()-org;
+ for(int j=0;j<3;++j)
+ {
+ ++splitcount[j][dot(x,axis[j])>0?1:0];
+ }
+ }
+ for( i=0;i<3;++i)
+ {
+ if((splitcount[i][0]>0)&&(splitcount[i][1]>0))
+ {
+ const int midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1]));
+ if(midp=0)
+ {
+ sets[0].reserve(splitcount[bestaxis][0]);
+ sets[1].reserve(splitcount[bestaxis][1]);
+ split(leaves,sets[0],sets[1],org,axis[bestaxis]);
+ }
+ else
+ {
+ sets[0].reserve(leaves.size()/2+1);
+ sets[1].reserve(leaves.size()/2);
+ for(int i=0,ni=leaves.size();ichilds[0]=topdown(pdbvt,sets[0],bu_treshold);
+ node->childs[1]=topdown(pdbvt,sets[1],bu_treshold);
+ node->childs[0]->parent=node;
+ node->childs[1]->parent=node;
+ return(node);
+ }
+ else
+ {
+ bottomup(pdbvt,leaves);
+ return(leaves[0]);
+ }
+ }
+return(leaves[0]);
+}
+
+//
+static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n,btDbvtNode*& r)
+{
+btDbvtNode* p=n->parent;
+btAssert(n->isinternal());
+if(p>n)
+ {
+ const int i=indexof(n);
+ const int j=1-i;
+ btDbvtNode* s=p->childs[j];
+ btDbvtNode* q=p->parent;
+ btAssert(n==p->childs[i]);
+ if(q) q->childs[indexof(p)]=n; else r=n;
+ s->parent=n;
+ p->parent=n;
+ n->parent=q;
+ p->childs[0]=n->childs[0];
+ p->childs[1]=n->childs[1];
+ n->childs[0]->parent=p;
+ n->childs[1]->parent=p;
+ n->childs[i]=p;
+ n->childs[j]=s;
+ btSwap(p->volume,n->volume);
+ return(p);
+ }
+return(n);
+}
+
+//
+static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count)
+{
+while(n&&(count--)) n=n->parent;
+return(n);
+}
+
+//
+// Api
+//
+
+//
+ btDbvt::btDbvt()
+{
+m_root = 0;
+m_free = 0;
+m_lkhd = -1;
+m_leaves = 0;
+m_opath = 0;
+}
+
+//
+ btDbvt::~btDbvt()
+{
+clear();
+}
+
+//
+void btDbvt::clear()
+{
+if(m_root) recursedeletenode(this,m_root);
+btAlignedFree(m_free);
+m_free=0;
+}
+
+//
+void btDbvt::optimizeBottomUp()
+{
+if(m_root)
+ {
+ tNodeArray leaves;
+ leaves.reserve(m_leaves);
+ fetchleaves(this,m_root,leaves);
+ bottomup(this,leaves);
+ m_root=leaves[0];
+ }
+}
+
+//
+void btDbvt::optimizeTopDown(int bu_treshold)
+{
+if(m_root)
+ {
+ tNodeArray leaves;
+ leaves.reserve(m_leaves);
+ fetchleaves(this,m_root,leaves);
+ m_root=topdown(this,leaves,bu_treshold);
+ }
+}
+
+//
+void btDbvt::optimizeIncremental(int passes)
+{
+if(passes<0) passes=m_leaves;
+if(m_root&&(passes>0))
+ {
+ do {
+ btDbvtNode* node=m_root;
+ unsigned bit=0;
+ while(node->isinternal())
+ {
+ node=sort(node,m_root)->childs[(m_opath>>bit)&1];
+ bit=(bit+1)&(sizeof(unsigned)*8-1);
+ }
+ update(node);
+ ++m_opath;
+ } while(--passes);
+ }
+}
+
+//
+btDbvtNode* btDbvt::insert(const btDbvtVolume& volume,void* data)
+{
+btDbvtNode* leaf=createnode(this,0,volume,data);
+insertleaf(this,m_root,leaf);
+++m_leaves;
+return(leaf);
+}
+
+//
+void btDbvt::update(btDbvtNode* leaf,int lookahead)
+{
+btDbvtNode* root=removeleaf(this,leaf);
+if(root)
+ {
+ if(lookahead>=0)
+ {
+ for(int i=0;(iparent;++i)
+ {
+ root=root->parent;
+ }
+ } else root=m_root;
+ }
+insertleaf(this,root,leaf);
+}
+
+//
+void btDbvt::update(btDbvtNode* leaf,const btDbvtVolume& volume)
+{
+btDbvtNode* root=removeleaf(this,leaf);
+if(root)
+ {
+ if(m_lkhd>=0)
+ {
+ for(int i=0;(iparent;++i)
+ {
+ root=root->parent;
+ }
+ } else root=m_root;
+ }
+leaf->volume=volume;
+insertleaf(this,root,leaf);
+}
+
+//
+bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin)
+{
+if(leaf->volume.Contain(volume)) return(false);
+volume.Expand(btVector3(margin,margin,margin));
+volume.SignedExpand(velocity);
+update(leaf,volume);
+return(true);
+}
+
+//
+bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity)
+{
+if(leaf->volume.Contain(volume)) return(false);
+volume.SignedExpand(velocity);
+update(leaf,volume);
+return(true);
+}
+
+//
+bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin)
+{
+if(leaf->volume.Contain(volume)) return(false);
+volume.Expand(btVector3(margin,margin,margin));
+update(leaf,volume);
+return(true);
+}
+
+//
+void btDbvt::remove(btDbvtNode* leaf)
+{
+removeleaf(this,leaf);
+deletenode(this,leaf);
+--m_leaves;
+}
+
+//
+void btDbvt::write(IWriter* iwriter) const
+{
+btDbvtNodeEnumerator nodes;
+nodes.nodes.reserve(m_leaves*2);
+enumNodes(m_root,nodes);
+iwriter->Prepare(m_root,nodes.nodes.size());
+for(int i=0;iparent) p=nodes.nodes.findLinearSearch(n->parent);
+ if(n->isinternal())
+ {
+ const int c0=nodes.nodes.findLinearSearch(n->childs[0]);
+ const int c1=nodes.nodes.findLinearSearch(n->childs[1]);
+ iwriter->WriteNode(n,i,p,c0,c1);
+ }
+ else
+ {
+ iwriter->WriteLeaf(n,i,p);
+ }
+ }
+}
+
+//
+void btDbvt::clone(btDbvt& dest,IClone* iclone) const
+{
+dest.clear();
+if(m_root!=0)
+ {
+ btAlignedObjectArray stack;
+ stack.reserve(m_leaves);
+ stack.push_back(sStkCLN(m_root,0));
+ do {
+ const int i=stack.size()-1;
+ const sStkCLN e=stack[i];
+ btDbvtNode* n=createnode(&dest,e.parent,e.node->volume,e.node->data);
+ stack.pop_back();
+ if(e.parent!=0)
+ e.parent->childs[i&1]=n;
+ else
+ dest.m_root=n;
+ if(e.node->isinternal())
+ {
+ stack.push_back(sStkCLN(e.node->childs[0],n));
+ stack.push_back(sStkCLN(e.node->childs[1],n));
+ }
+ else
+ {
+ iclone->CloneLeaf(n);
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+int btDbvt::maxdepth(const btDbvtNode* node)
+{
+int depth=0;
+if(node) getmaxdepth(node,1,depth);
+return(depth);
+}
+
+//
+int btDbvt::countLeaves(const btDbvtNode* node)
+{
+if(node->isinternal())
+ return(countLeaves(node->childs[0])+countLeaves(node->childs[1]));
+ else
+ return(1);
+}
+
+//
+void btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves)
+{
+if(node->isinternal())
+ {
+ extractLeaves(node->childs[0],leaves);
+ extractLeaves(node->childs[1],leaves);
+ }
+ else
+ {
+ leaves.push_back(node);
+ }
+}
+
+//
+#if DBVT_ENABLE_BENCHMARK
+
+#include
+#include
+#include "LinearMath/btQuickProf.h"
+
+/*
+q6600,2.4ghz
+
+/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32"
+/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
+/Fo"..\..\out\release8\build\libbulletcollision\\"
+/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
+/W3 /nologo /c /Wp64 /Zi /errorReport:prompt
+
+Benchmarking dbvt...
+ World scale: 100.000000
+ Extents base: 1.000000
+ Extents range: 4.000000
+ Leaves: 8192
+ sizeof(btDbvtVolume): 32 bytes
+ sizeof(btDbvtNode): 44 bytes
+[1] btDbvtVolume intersections: 3499 ms (-1%)
+[2] btDbvtVolume merges: 1934 ms (0%)
+[3] btDbvt::collideTT: 5485 ms (-21%)
+[4] btDbvt::collideTT self: 2814 ms (-20%)
+[5] btDbvt::collideTT xform: 7379 ms (-1%)
+[6] btDbvt::collideTT xform,self: 7270 ms (-2%)
+[7] btDbvt::collideRAY: 6314 ms (0%),(332143 r/s)
+[8] insert/remove: 2093 ms (0%),(1001983 ir/s)
+[9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
+[10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
+[11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
+[12] btDbvtVolume notequal: 3659 ms (0%)
+[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
+[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
+[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
+[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
+[17] btDbvtVolume select: 3419 ms (0%)
+*/
+
+struct btDbvtBenchmark
+{
+struct NilPolicy : btDbvt::ICollide
+ {
+ NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {}
+ void Process(const btDbvtNode*,const btDbvtNode*) { ++m_pcount; }
+ void Process(const btDbvtNode*) { ++m_pcount; }
+ void Process(const btDbvtNode*,btScalar depth)
+ {
+ ++m_pcount;
+ if(m_checksort)
+ { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); }
+ }
+ int m_pcount;
+ btScalar m_depth;
+ bool m_checksort;
+ };
+struct P14 : btDbvt::ICollide
+ {
+ struct Node
+ {
+ const btDbvtNode* leaf;
+ btScalar depth;
+ };
+ void Process(const btDbvtNode* leaf,btScalar depth)
+ {
+ Node n;
+ n.leaf = leaf;
+ n.depth = depth;
+ }
+ static int sortfnc(const Node& a,const Node& b)
+ {
+ if(a.depthb.depth) return(-1);
+ return(0);
+ }
+ btAlignedObjectArray m_nodes;
+ };
+struct P15 : btDbvt::ICollide
+ {
+ struct Node
+ {
+ const btDbvtNode* leaf;
+ btScalar depth;
+ };
+ void Process(const btDbvtNode* leaf)
+ {
+ Node n;
+ n.leaf = leaf;
+ n.depth = dot(leaf->volume.Center(),m_axis);
+ }
+ static int sortfnc(const Node& a,const Node& b)
+ {
+ if(a.depthb.depth) return(-1);
+ return(0);
+ }
+ btAlignedObjectArray m_nodes;
+ btVector3 m_axis;
+ };
+static btScalar RandUnit()
+ {
+ return(rand()/(btScalar)RAND_MAX);
+ }
+static btVector3 RandVector3()
+ {
+ return(btVector3(RandUnit(),RandUnit(),RandUnit()));
+ }
+static btVector3 RandVector3(btScalar cs)
+ {
+ return(RandVector3()*cs-btVector3(cs,cs,cs)/2);
+ }
+static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es)
+ {
+ return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es));
+ }
+static btTransform RandTransform(btScalar cs)
+ {
+ btTransform t;
+ t.setOrigin(RandVector3(cs));
+ t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized());
+ return(t);
+ }
+static void RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt)
+ {
+ dbvt.clear();
+ for(int i=0;i volumes;
+ btAlignedObjectArray results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i volumes;
+ btAlignedObjectArray results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i transforms;
+ btDbvtBenchmark::NilPolicy policy;
+ transforms.resize(cfgBenchmark5_Iterations);
+ for(int i=0;i transforms;
+ btDbvtBenchmark::NilPolicy policy;
+ transforms.resize(cfgBenchmark6_Iterations);
+ for(int i=0;i rayorg;
+ btAlignedObjectArray raydir;
+ btDbvtBenchmark::NilPolicy policy;
+ rayorg.resize(cfgBenchmark7_Iterations);
+ raydir.resize(cfgBenchmark7_Iterations);
+ for(int i=0;i leaves;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ dbvt.extractLeaves(dbvt.m_root,leaves);
+ printf("[9] updates (teleport): ");
+ wallclock.reset();
+ for(int i=0;i(leaves[rand()%cfgLeaves]),
+ btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale));
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time);
+ }
+if(cfgBenchmark10_Enable)
+ {// Benchmark 10
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray leaves;
+ btAlignedObjectArray vectors;
+ vectors.resize(cfgBenchmark10_Iterations);
+ for(int i=0;i(leaves[rand()%cfgLeaves]);
+ btDbvtVolume v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d);
+ dbvt.update(l,v);
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time);
+ }
+if(cfgBenchmark11_Enable)
+ {// Benchmark 11
+ srand(380843);
+ btDbvt dbvt;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[11] optimize (incremental): ");
+ wallclock.reset();
+ for(int i=0;i volumes;
+ btAlignedObjectArray results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i vectors;
+ btDbvtBenchmark::NilPolicy policy;
+ vectors.resize(cfgBenchmark13_Iterations);
+ for(int i=0;i vectors;
+ btDbvtBenchmark::P14 policy;
+ vectors.resize(cfgBenchmark14_Iterations);
+ for(int i=0;i vectors;
+ btDbvtBenchmark::P15 policy;
+ vectors.resize(cfgBenchmark15_Iterations);
+ for(int i=0;i batch;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ batch.reserve(cfgBenchmark16_BatchCount);
+ printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount);
+ wallclock.reset();
+ for(int i=0;i volumes;
+ btAlignedObjectArray results;
+ btAlignedObjectArray indices;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ indices.resize(cfgLeaves);
+ for(int i=0;i= 1400)
+ #define DBVT_USE_TEMPLATE 1
+ #else
+ #define DBVT_USE_TEMPLATE 0
+#endif
+#else
+#define DBVT_USE_TEMPLATE 0
+#endif
+
+// Use only intrinsics instead of inline asm
+#define DBVT_USE_INTRINSIC_SSE 1
+
+// Using memmov for collideOCL
+#define DBVT_USE_MEMMOVE 1
+
+// Enable benchmarking code
+#define DBVT_ENABLE_BENCHMARK 0
+
+// Inlining
+#define DBVT_INLINE SIMD_FORCE_INLINE
+// Align
+#ifdef WIN32
+#define DBVT_ALIGN __declspec(align(16))
+#else
+#define DBVT_ALIGN
+#endif
+
+// Specific methods implementation
+
+#ifdef WIN32_AVOID_SSE_WHEN_EMBEDDED_INSIDE_BLENDER //there is always some weird compiler that breaks SSE builds
+#define DBVT_SELECT_IMPL DBVT_IMPL_SSE
+#define DBVT_MERGE_IMPL DBVT_IMPL_SSE
+#define DBVT_INT0_IMPL DBVT_IMPL_SSE
+#else
+#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC
+#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC
+#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC
+#endif
+
+#if (DBVT_SELECT_IMPL==DBVT_IMPL_SSE)|| \
+ (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)|| \
+ (DBVT_INT0_IMPL==DBVT_IMPL_SSE)
+#include
+#endif
+
+//
+// Auto config and checks
+//
+
+#if DBVT_USE_TEMPLATE
+#define DBVT_VIRTUAL
+#define DBVT_VIRTUAL_DTOR(a)
+#define DBVT_PREFIX template
+#define DBVT_IPOLICY T& policy
+#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)0;
+#else
+#define DBVT_VIRTUAL_DTOR(a) virtual ~a() {}
+#define DBVT_VIRTUAL virtual
+#define DBVT_PREFIX
+#define DBVT_IPOLICY ICollide& policy
+#define DBVT_CHECKTYPE
+#endif
+
+#if DBVT_USE_MEMMOVE
+#ifndef __CELLOS_LV2__
+#include
+#endif
+#include
+#endif
+
+#ifndef DBVT_USE_TEMPLATE
+#error "DBVT_USE_TEMPLATE undefined"
+#endif
+
+#ifndef DBVT_USE_MEMMOVE
+#error "DBVT_USE_MEMMOVE undefined"
+#endif
+
+#ifndef DBVT_ENABLE_BENCHMARK
+#error "DBVT_ENABLE_BENCHMARK undefined"
+#endif
+
+#ifndef DBVT_SELECT_IMPL
+#error "DBVT_SELECT_IMPL undefined"
+#endif
+
+#ifndef DBVT_MERGE_IMPL
+#error "DBVT_MERGE_IMPL undefined"
+#endif
+
+#ifndef DBVT_INT0_IMPL
+#error "DBVT_INT0_IMPL undefined"
+#endif
+
+//
+// Defaults volumes
+//
+
+/* btDbvtAabbMm */
+struct btDbvtAabbMm
+{
+DBVT_INLINE btVector3 Center() const { return((mi+mx)/2); }
+DBVT_INLINE btVector3 Lengths() const { return(mx-mi); }
+DBVT_INLINE btVector3 Extents() const { return((mx-mi)/2); }
+DBVT_INLINE const btVector3& Mins() const { return(mi); }
+DBVT_INLINE const btVector3& Maxs() const { return(mx); }
+static inline btDbvtAabbMm FromCE(const btVector3& c,const btVector3& e);
+static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r);
+static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx);
+static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n);
+static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n);
+DBVT_INLINE void Expand(const btVector3& e);
+DBVT_INLINE void SignedExpand(const btVector3& e);
+DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const;
+DBVT_INLINE int Classify(const btVector3& n,btScalar o,int s) const;
+DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const;
+DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b,
+ const btTransform& xform);
+DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
+ const btVector3& b);
+DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
+ const btVector3& org,
+ const btVector3& invdir,
+ const unsigned* signs);
+DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+DBVT_INLINE friend int Select( const btDbvtAabbMm& o,
+ const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+DBVT_INLINE friend void Merge( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b,
+ btDbvtAabbMm& r);
+DBVT_INLINE friend bool NotEqual( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+private:
+DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const;
+private:
+btVector3 mi,mx;
+};
+
+// Types
+typedef btDbvtAabbMm btDbvtVolume;
+
+/* btDbvtNode */
+struct btDbvtNode
+{
+ btDbvtVolume volume;
+ btDbvtNode* parent;
+ DBVT_INLINE bool isleaf() const { return(childs[1]==0); }
+ DBVT_INLINE bool isinternal() const { return(!isleaf()); }
+ union {
+ btDbvtNode* childs[2];
+ void* data;
+ int dataAsInt;
+ };
+};
+
+///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
+///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes.
+///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
+struct btDbvt
+ {
+ /* Stack element */
+ struct sStkNN
+ {
+ const btDbvtNode* a;
+ const btDbvtNode* b;
+ sStkNN() {}
+ sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {}
+ };
+ struct sStkNP
+ {
+ const btDbvtNode* node;
+ int mask;
+ sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {}
+ };
+ struct sStkNPS
+ {
+ const btDbvtNode* node;
+ int mask;
+ btScalar value;
+ sStkNPS() {}
+ sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {}
+ };
+ struct sStkCLN
+ {
+ const btDbvtNode* node;
+ btDbvtNode* parent;
+ sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {}
+ };
+ // Policies/Interfaces
+
+ /* ICollide */
+ struct ICollide
+ {
+ DBVT_VIRTUAL_DTOR(ICollide)
+ DBVT_VIRTUAL void Process(const btDbvtNode*,const btDbvtNode*) {}
+ DBVT_VIRTUAL void Process(const btDbvtNode*) {}
+ DBVT_VIRTUAL void Process(const btDbvtNode* n,btScalar) { Process(n); }
+ DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return(true); }
+ DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return(true); }
+ };
+ /* IWriter */
+ struct IWriter
+ {
+ virtual ~IWriter() {}
+ virtual void Prepare(const btDbvtNode* root,int numnodes)=0;
+ virtual void WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0;
+ virtual void WriteLeaf(const btDbvtNode*,int index,int parent)=0;
+ };
+ /* IClone */
+ struct IClone
+ {
+ virtual ~IClone() {}
+ virtual void CloneLeaf(btDbvtNode*) {}
+ };
+
+ // Constants
+ enum {
+ SIMPLE_STACKSIZE = 64,
+ DOUBLE_STACKSIZE = SIMPLE_STACKSIZE*2
+ };
+
+ // Fields
+ btDbvtNode* m_root;
+ btDbvtNode* m_free;
+ int m_lkhd;
+ int m_leaves;
+ unsigned m_opath;
+ // Methods
+ btDbvt();
+ ~btDbvt();
+ void clear();
+ bool empty() const { return(0==m_root); }
+ void optimizeBottomUp();
+ void optimizeTopDown(int bu_treshold=128);
+ void optimizeIncremental(int passes);
+ btDbvtNode* insert(const btDbvtVolume& box,void* data);
+ void update(btDbvtNode* leaf,int lookahead=-1);
+ void update(btDbvtNode* leaf,const btDbvtVolume& volume);
+ bool update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin);
+ bool update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity);
+ bool update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin);
+ void remove(btDbvtNode* leaf);
+ void write(IWriter* iwriter) const;
+ void clone(btDbvt& dest,IClone* iclone=0) const;
+ static int maxdepth(const btDbvtNode* node);
+ static int countLeaves(const btDbvtNode* node);
+ static void extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves);
+ #if DBVT_ENABLE_BENCHMARK
+ static void benchmark();
+ #else
+ static void benchmark(){}
+ #endif
+ // DBVT_IPOLICY must support ICollide policy/interface
+ DBVT_PREFIX
+ static void enumNodes( const btDbvtNode* root,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void enumLeaves( const btDbvtNode* root,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ const btTransform& xform,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideTT( const btDbvtNode* root0,
+ const btTransform& xform0,
+ const btDbvtNode* root1,
+ const btTransform& xform1,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideTV( const btDbvtNode* root,
+ const btDbvtVolume& volume,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideRAY( const btDbvtNode* root,
+ const btVector3& origin,
+ const btVector3& direction,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideKDOP(const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ int count,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideOCL( const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ const btVector3& sortaxis,
+ int count,
+ DBVT_IPOLICY,
+ bool fullsort=true);
+ DBVT_PREFIX
+ static void collideTU( const btDbvtNode* root,
+ DBVT_IPOLICY);
+ // Helpers
+ static DBVT_INLINE int nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h)
+ {
+ int m=0;
+ while(l>1;
+ if(a[i[m]].value>=v) l=m+1; else h=m;
+ }
+ return(h);
+ }
+ static DBVT_INLINE int allocate( btAlignedObjectArray& ifree,
+ btAlignedObjectArray& stock,
+ const sStkNPS& value)
+ {
+ int i;
+ if(ifree.size()>0)
+ { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; }
+ else
+ { i=stock.size();stock.push_back(value); }
+ return(i);
+ }
+ //
+ private:
+ btDbvt(const btDbvt&) {}
+ };
+
+//
+// Inline's
+//
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e)
+{
+btDbvtAabbMm box;
+box.mi=c-e;box.mx=c+e;
+return(box);
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r)
+{
+return(FromCE(c,btVector3(r,r,r)));
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx)
+{
+btDbvtAabbMm box;
+box.mi=mi;box.mx=mx;
+return(box);
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n)
+{
+btDbvtAabbMm box;
+box.mi=box.mx=pts[0];
+for(int i=1;i0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]);
+if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]);
+if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]);
+}
+
+//
+DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const
+{
+return( (mi.x()<=a.mi.x())&&
+ (mi.y()<=a.mi.y())&&
+ (mi.z()<=a.mi.z())&&
+ (mx.x()>=a.mx.x())&&
+ (mx.y()>=a.mx.y())&&
+ (mx.z()>=a.mx.z()));
+}
+
+//
+DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const
+{
+btVector3 pi,px;
+switch(s)
+ {
+ case (0+0+0): px=btVector3(mi.x(),mi.y(),mi.z());
+ pi=btVector3(mx.x(),mx.y(),mx.z());break;
+ case (1+0+0): px=btVector3(mx.x(),mi.y(),mi.z());
+ pi=btVector3(mi.x(),mx.y(),mx.z());break;
+ case (0+2+0): px=btVector3(mi.x(),mx.y(),mi.z());
+ pi=btVector3(mx.x(),mi.y(),mx.z());break;
+ case (1+2+0): px=btVector3(mx.x(),mx.y(),mi.z());
+ pi=btVector3(mi.x(),mi.y(),mx.z());break;
+ case (0+0+4): px=btVector3(mi.x(),mi.y(),mx.z());
+ pi=btVector3(mx.x(),mx.y(),mi.z());break;
+ case (1+0+4): px=btVector3(mx.x(),mi.y(),mx.z());
+ pi=btVector3(mi.x(),mx.y(),mi.z());break;
+ case (0+2+4): px=btVector3(mi.x(),mx.y(),mx.z());
+ pi=btVector3(mx.x(),mi.y(),mi.z());break;
+ case (1+2+4): px=btVector3(mx.x(),mx.y(),mx.z());
+ pi=btVector3(mi.x(),mi.y(),mi.z());break;
+ }
+if((dot(n,px)+o)<0) return(-1);
+if((dot(n,pi)+o)>=0) return(+1);
+return(0);
+}
+
+//
+DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const
+{
+const btVector3* b[]={&mx,&mi};
+const btVector3 p( b[(signs>>0)&1]->x(),
+ b[(signs>>1)&1]->y(),
+ b[(signs>>2)&1]->z());
+return(dot(p,v));
+}
+
+//
+DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const
+{
+for(int i=0;i<3;++i)
+ {
+ if(d[i]<0)
+ { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; }
+ else
+ { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; }
+ }
+}
+
+//
+DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+#if DBVT_INT0_IMPL == DBVT_IMPL_SSE
+const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)),
+ _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi))));
+const __int32* pu((const __int32*)&rt);
+return((pu[0]|pu[1]|pu[2])==0);
+#else
+return( (a.mi.x()<=b.mx.x())&&
+ (a.mx.x()>=b.mi.x())&&
+ (a.mi.y()<=b.mx.y())&&
+ (a.mx.y()>=b.mi.y())&&
+ (a.mi.z()<=b.mx.z())&&
+ (a.mx.z()>=b.mi.z()));
+#endif
+}
+
+//
+DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b,
+ const btTransform& xform)
+{
+const btVector3 d0=xform*b.Center()-a.Center();
+const btVector3 d1=d0*xform.getBasis();
+btScalar s0[2]={0,0};
+btScalar s1[2]={dot(xform.getOrigin(),d0),s1[0]};
+a.AddSpan(d0,s0[0],s0[1]);
+b.AddSpan(d1,s1[0],s1[1]);
+if(s0[0]>(s1[1])) return(false);
+if(s0[1]<(s1[0])) return(false);
+return(true);
+}
+
+//
+DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
+ const btVector3& b)
+{
+return( (b.x()>=a.mi.x())&&
+ (b.y()>=a.mi.y())&&
+ (b.z()>=a.mi.z())&&
+ (b.x()<=a.mx.x())&&
+ (b.y()<=a.mx.y())&&
+ (b.z()<=a.mx.z()));
+}
+
+//
+DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
+ const btVector3& org,
+ const btVector3& invdir,
+ const unsigned* signs)
+{
+#if 0
+const btVector3 b0((a.mi-org)*invdir);
+const btVector3 b1((a.mx-org)*invdir);
+const btVector3 tmin(btMin(b0[0],b1[0]),btMin(b0[1],b1[1]),btMin(b0[2],b1[2]));
+const btVector3 tmax(btMax(b0[0],b1[0]),btMax(b0[1],b1[1]),btMax(b0[2],b1[2]));
+const btScalar tin=btMax(tmin[0],btMax(tmin[1],tmin[2]));
+const btScalar tout=btMin(tmax[0],btMin(tmax[1],tmax[2]));
+return(tinx()-org[0])*invdir[0];
+btScalar txmax=(bounds[1-signs[0]]->x()-org[0])*invdir[0];
+const btScalar tymin=(bounds[ signs[1]]->y()-org[1])*invdir[1];
+const btScalar tymax=(bounds[1-signs[1]]->y()-org[1])*invdir[1];
+if((txmin>tymax)||(tymin>txmax)) return(false);
+if(tymin>txmin) txmin=tymin;
+if(tymaxz()-org[2])*invdir[2];
+const btScalar tzmax=(bounds[1-signs[2]]->z()-org[2])*invdir[2];
+if((txmin>tzmax)||(tzmin>txmax)) return(false);
+if(tzmin>txmin) txmin=tzmin;
+if(tzmax0);
+#endif
+}
+
+//
+DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx);
+return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z()));
+}
+
+//
+DBVT_INLINE int Select( const btDbvtAabbMm& o,
+ const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE
+static DBVT_ALIGN const unsigned __int32 mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff};
+ // TODO: the intrinsic version is 11% slower
+ #if DBVT_USE_INTRINSIC_SSE
+ __m128 omi(_mm_load_ps(o.mi));
+ omi=_mm_add_ps(omi,_mm_load_ps(o.mx));
+ __m128 ami(_mm_load_ps(a.mi));
+ ami=_mm_add_ps(ami,_mm_load_ps(a.mx));
+ ami=_mm_sub_ps(ami,omi);
+ ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask));
+ __m128 bmi(_mm_load_ps(b.mi));
+ bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx));
+ bmi=_mm_sub_ps(bmi,omi);
+ bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask));
+ __m128 t0(_mm_movehl_ps(ami,ami));
+ ami=_mm_add_ps(ami,t0);
+ ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1));
+ __m128 t1(_mm_movehl_ps(bmi,bmi));
+ bmi=_mm_add_ps(bmi,t1);
+ bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1));
+ return(_mm_cmple_ss(bmi,ami).m128_u32[0]&1);
+ #else
+ DBVT_ALIGN __int32 r[1];
+ __asm
+ {
+ mov eax,o
+ mov ecx,a
+ mov edx,b
+ movaps xmm0,[eax]
+ movaps xmm5,mask
+ addps xmm0,[eax+16]
+ movaps xmm1,[ecx]
+ movaps xmm2,[edx]
+ addps xmm1,[ecx+16]
+ addps xmm2,[edx+16]
+ subps xmm1,xmm0
+ subps xmm2,xmm0
+ andps xmm1,xmm5
+ andps xmm2,xmm5
+ movhlps xmm3,xmm1
+ movhlps xmm4,xmm2
+ addps xmm1,xmm3
+ addps xmm2,xmm4
+ pshufd xmm3,xmm1,1
+ pshufd xmm4,xmm2,1
+ addss xmm1,xmm3
+ addss xmm2,xmm4
+ cmpless xmm2,xmm1
+ movss r,xmm2
+ }
+ return(r[0]&1);
+ #endif
+#else
+return(Proximity(o,a)b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i];
+ }
+#endif
+}
+
+//
+DBVT_INLINE bool NotEqual( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+return( (a.mi.x()!=b.mi.x())||
+ (a.mi.y()!=b.mi.y())||
+ (a.mi.z()!=b.mi.z())||
+ (a.mx.x()!=b.mx.x())||
+ (a.mx.y()!=b.mx.y())||
+ (a.mx.z()!=b.mx.z()));
+}
+
+//
+// Inline's
+//
+
+//
+DBVT_PREFIX
+inline void btDbvt::enumNodes( const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+policy.Process(root);
+if(root->isinternal())
+ {
+ enumNodes(root->childs[0],policy);
+ enumNodes(root->childs[1],policy);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::enumLeaves( const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root->isinternal())
+ {
+ enumLeaves(root->childs[0],policy);
+ enumLeaves(root->childs[1],policy);
+ }
+ else
+ {
+ policy.Process(root);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root0&&root1)
+ {
+ btAlignedObjectArray stack;
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-4;
+ stack.resize(DOUBLE_STACKSIZE);
+ stack[0]=sStkNN(root0,root1);
+ do {
+ sStkNN p=stack[--depth];
+ if(depth>treshold)
+ {
+ stack.resize(stack.size()*2);
+ treshold=stack.size()-4;
+ }
+ if(p.a==p.b)
+ {
+ if(p.a->isinternal())
+ {
+ stack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
+ stack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
+ stack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+ }
+ }
+ else if(Intersect(p.a->volume,p.b->volume))
+ {
+ if(p.a->isinternal())
+ {
+ if(p.b->isinternal())
+ {
+ stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+ stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+ stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+ stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+ }
+ else
+ {
+ stack[depth++]=sStkNN(p.a->childs[0],p.b);
+ stack[depth++]=sStkNN(p.a->childs[1],p.b);
+ }
+ }
+ else
+ {
+ if(p.b->isinternal())
+ {
+ stack[depth++]=sStkNN(p.a,p.b->childs[0]);
+ stack[depth++]=sStkNN(p.a,p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a,p.b);
+ }
+ }
+ }
+ } while(depth);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ const btTransform& xform,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root0&&root1)
+ {
+ btAlignedObjectArray stack;
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-4;
+ stack.resize(DOUBLE_STACKSIZE);
+ stack[0]=sStkNN(root0,root1);
+ do {
+ sStkNN p=stack[--depth];
+ if(Intersect(p.a->volume,p.b->volume,xform))
+ {
+ if(depth>treshold)
+ {
+ stack.resize(stack.size()*2);
+ treshold=stack.size()-4;
+ }
+ if(p.a->isinternal())
+ {
+ if(p.b->isinternal())
+ {
+ stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+ stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+ stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+ stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+ }
+ else
+ {
+ stack[depth++]=sStkNN(p.a->childs[0],p.b);
+ stack[depth++]=sStkNN(p.a->childs[1],p.b);
+ }
+ }
+ else
+ {
+ if(p.b->isinternal())
+ {
+ stack[depth++]=sStkNN(p.a,p.b->childs[0]);
+ stack[depth++]=sStkNN(p.a,p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a,p.b);
+ }
+ }
+ }
+ } while(depth);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTT( const btDbvtNode* root0,
+ const btTransform& xform0,
+ const btDbvtNode* root1,
+ const btTransform& xform1,
+ DBVT_IPOLICY)
+{
+const btTransform xform=xform0.inverse()*xform1;
+collideTT(root0,root1,xform,policy);
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTV( const btDbvtNode* root,
+ const btDbvtVolume& vol,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root)
+ {
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol);
+ btAlignedObjectArray stack;
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do {
+ const btDbvtNode* n=stack[stack.size()-1];
+ stack.pop_back();
+ if(Intersect(n->volume,volume))
+ {
+ if(n->isinternal())
+ {
+ stack.push_back(n->childs[0]);
+ stack.push_back(n->childs[1]);
+ }
+ else
+ {
+ policy.Process(n);
+ }
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideRAY( const btDbvtNode* root,
+ const btVector3& origin,
+ const btVector3& direction,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root)
+ {
+ const btVector3 normal=direction.normalized();
+ const btVector3 invdir( 1/normal.x(),
+ 1/normal.y(),
+ 1/normal.z());
+ const unsigned signs[]={ direction.x()<0,
+ direction.y()<0,
+ direction.z()<0};
+ btAlignedObjectArray stack;
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do {
+ const btDbvtNode* node=stack[stack.size()-1];
+ stack.pop_back();
+ if(Intersect(node->volume,origin,invdir,signs))
+ {
+ if(node->isinternal())
+ {
+ stack.push_back(node->childs[0]);
+ stack.push_back(node->childs[1]);
+ }
+ else
+ {
+ policy.Process(node);
+ }
+ }
+ } while(stack.size());
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideKDOP(const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ int count,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root)
+ {
+ const int inside=(1< stack;
+ int signs[sizeof(unsigned)*8];
+ btAssert(count=0)?1:0)+
+ ((normals[i].y()>=0)?2:0)+
+ ((normals[i].z()>=0)?4:0);
+ }
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(sStkNP(root,0));
+ do {
+ sStkNP se=stack[stack.size()-1];
+ bool out=false;
+ stack.pop_back();
+ for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]);
+ switch(side)
+ {
+ case -1: out=true;break;
+ case +1: se.mask|=j;break;
+ }
+ }
+ }
+ if(!out)
+ {
+ if((se.mask!=inside)&&(se.node->isinternal()))
+ {
+ stack.push_back(sStkNP(se.node->childs[0],se.mask));
+ stack.push_back(sStkNP(se.node->childs[1],se.mask));
+ }
+ else
+ {
+ if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy);
+ }
+ }
+ } while(stack.size());
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideOCL( const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ const btVector3& sortaxis,
+ int count,
+ DBVT_IPOLICY,
+ bool fsort)
+{
+DBVT_CHECKTYPE
+if(root)
+ {
+ const unsigned srtsgns=(sortaxis[0]>=0?1:0)+
+ (sortaxis[1]>=0?2:0)+
+ (sortaxis[2]>=0?4:0);
+ const int inside=(1< stock;
+ btAlignedObjectArray ifree;
+ btAlignedObjectArray stack;
+ int signs[sizeof(unsigned)*8];
+ btAssert(count=0)?1:0)+
+ ((normals[i].y()>=0)?2:0)+
+ ((normals[i].z()>=0)?4:0);
+ }
+ stock.reserve(SIMPLE_STACKSIZE);
+ stack.reserve(SIMPLE_STACKSIZE);
+ ifree.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns))));
+ do {
+ const int id=stack[stack.size()-1];
+ sStkNPS se=stock[id];
+ stack.pop_back();ifree.push_back(id);
+ if(se.mask!=inside)
+ {
+ bool out=false;
+ for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]);
+ switch(side)
+ {
+ case -1: out=true;break;
+ case +1: se.mask|=j;break;
+ }
+ }
+ }
+ if(out) continue;
+ }
+ if(policy.Descent(se.node))
+ {
+ if(se.node->isinternal())
+ {
+ const btDbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]};
+ sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)),
+ sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))};
+ const int q=nes[0].value0))
+ {
+ /* Insert 0 */
+ j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size());
+ stack.push_back(0);
+ #if DBVT_USE_MEMMOVE
+ memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+ #else
+ for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+ #endif
+ stack[j]=allocate(ifree,stock,nes[q]);
+ /* Insert 1 */
+ j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size());
+ stack.push_back(0);
+ #if DBVT_USE_MEMMOVE
+ memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+ #else
+ for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+ #endif
+ stack[j]=allocate(ifree,stock,nes[1-q]);
+ }
+ else
+ {
+ stack.push_back(allocate(ifree,stock,nes[q]));
+ stack.push_back(allocate(ifree,stock,nes[1-q]));
+ }
+ }
+ else
+ {
+ policy.Process(se.node,se.value);
+ }
+ }
+ } while(stack.size());
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTU( const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root)
+ {
+ btAlignedObjectArray stack;
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do {
+ const btDbvtNode* n=stack[stack.size()-1];
+ stack.pop_back();
+ if(policy.Descent(n))
+ {
+ if(n->isinternal())
+ { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
+ else
+ { policy.Process(n); }
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+// PP Cleanup
+//
+
+#undef DBVT_USE_MEMMOVE
+#undef DBVT_USE_TEMPLATE
+#undef DBVT_VIRTUAL_DTOR
+#undef DBVT_VIRTUAL
+#undef DBVT_PREFIX
+#undef DBVT_IPOLICY
+#undef DBVT_CHECKTYPE
+#undef DBVT_IMPL_GENERIC
+#undef DBVT_IMPL_SSE
+#undef DBVT_USE_INTRINSIC_SSE
+#undef DBVT_SELECT_IMPL
+#undef DBVT_MERGE_IMPL
+#undef DBVT_INT0_IMPL
+
+#endif
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
new file mode 100644
index 00000000000..fd82fd7cae3
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
@@ -0,0 +1,547 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 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.
+*/
+///btDbvtBroadphase implementation by Nathanael Presson
+
+#include "btDbvtBroadphase.h"
+
+//
+// Profiling
+//
+
+#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK
+#include
+#endif
+
+#if DBVT_BP_PROFILE
+struct ProfileScope
+ {
+ __forceinline ProfileScope(btClock& clock,unsigned long& value) :
+ m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds())
+ {
+ }
+ __forceinline ~ProfileScope()
+ {
+ (*m_value)+=m_clock->getTimeMicroseconds()-m_base;
+ }
+ btClock* m_clock;
+ unsigned long* m_value;
+ unsigned long m_base;
+ };
+#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_)
+#else
+#define SPC(_value_)
+#endif
+
+//
+// Helpers
+//
+
+//
+template
+static inline void listappend(T* item,T*& list)
+{
+item->links[0]=0;
+item->links[1]=list;
+if(list) list->links[0]=item;
+list=item;
+}
+
+//
+template
+static inline void listremove(T* item,T*& list)
+{
+if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
+if(item->links[1]) item->links[1]->links[0]=item->links[0];
+}
+
+//
+template
+static inline int listcount(T* root)
+{
+int n=0;
+while(root) { ++n;root=root->links[1]; }
+return(n);
+}
+
+//
+template
+static inline void clear(T& value)
+{
+static const struct ZeroDummy : T {} zerodummy;
+value=zerodummy;
+}
+
+//
+// Colliders
+//
+
+/* Tree collider */
+struct btDbvtTreeCollider : btDbvt::ICollide
+{
+btDbvtBroadphase* pbp;
+btDbvtProxy* proxy;
+ btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
+void Process(const btDbvtNode* na,const btDbvtNode* nb)
+ {
+ if(na!=nb)
+ {
+ btDbvtProxy* pa=(btDbvtProxy*)na->data;
+ btDbvtProxy* pb=(btDbvtProxy*)nb->data;
+ #if DBVT_BP_SORTPAIRS
+ if(pa>pb) btSwap(pa,pb);
+ #endif
+ pbp->m_paircache->addOverlappingPair(pa,pb);
+ ++pbp->m_newpairs;
+ }
+ }
+void Process(const btDbvtNode* n)
+ {
+ Process(n,proxy->leaf);
+ }
+};
+
+//
+// btDbvtBroadphase
+//
+
+//
+btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
+{
+m_deferedcollide = false;
+m_needcleanup = true;
+m_releasepaircache = (paircache!=0)?false:true;
+m_prediction = 1/(btScalar)2;
+m_stageCurrent = 0;
+m_fixedleft = 0;
+m_fupdates = 1;
+m_dupdates = 0;
+m_cupdates = 10;
+m_newpairs = 1;
+m_updates_call = 0;
+m_updates_done = 0;
+m_updates_ratio = 0;
+m_paircache = paircache?
+ paircache :
+ new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
+m_gid = 0;
+m_pid = 0;
+m_cid = 0;
+for(int i=0;i<=STAGECOUNT;++i)
+ {
+ m_stageRoots[i]=0;
+ }
+#if DBVT_BP_PROFILE
+clear(m_profiling);
+#endif
+}
+
+//
+btDbvtBroadphase::~btDbvtBroadphase()
+{
+if(m_releasepaircache)
+{
+ m_paircache->~btOverlappingPairCache();
+ btAlignedFree(m_paircache);
+}
+}
+
+//
+btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ int /*shapeType*/,
+ void* userPtr,
+ short int collisionFilterGroup,
+ short int collisionFilterMask,
+ btDispatcher* dispatcher,
+ void* /*multiSapProxy*/)
+{
+btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( userPtr,
+ collisionFilterGroup,
+ collisionFilterMask);
+proxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
+proxy->stage = m_stageCurrent;
+proxy->m_uniqueId = ++m_gid;
+proxy->leaf = m_sets[0].insert(proxy->aabb,proxy);
+listappend(proxy,m_stageRoots[m_stageCurrent]);
+if(!m_deferedcollide)
+ {
+ btDbvtTreeCollider collider(this);
+ collider.proxy=proxy;
+ btDbvt::collideTV(m_sets[0].m_root,proxy->aabb,collider);
+ }
+return(proxy);
+}
+
+//
+void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy,
+ btDispatcher* dispatcher)
+{
+btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+if(proxy->stage==STAGECOUNT)
+ m_sets[1].remove(proxy->leaf);
+ else
+ m_sets[0].remove(proxy->leaf);
+listremove(proxy,m_stageRoots[proxy->stage]);
+m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher);
+btAlignedFree(proxy);
+m_needcleanup=true;
+}
+
+//
+void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btDispatcher* /*dispatcher*/)
+{
+btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
+#if DBVT_BP_PREVENTFALSEUPDATE
+if(NotEqual(aabb,proxy->leaf->volume))
+#endif
+ {
+ bool docollide=false;
+ if(proxy->stage==STAGECOUNT)
+ {/* fixed -> dynamic set */
+ m_sets[1].remove(proxy->leaf);
+ proxy->leaf=m_sets[0].insert(aabb,proxy);
+ docollide=true;
+ }
+ else
+ {/* dynamic set */
+ ++m_updates_call;
+ if(Intersect(proxy->leaf->volume,aabb))
+ {/* Moving */
+ const btVector3 delta=aabbMin-proxy->aabb.Mins();
+ btVector3 velocity(aabb.Extents()*m_prediction);
+ if(delta[0]<0) velocity[0]=-velocity[0];
+ if(delta[1]<0) velocity[1]=-velocity[1];
+ if(delta[2]<0) velocity[2]=-velocity[2];
+ if (
+ #ifdef DBVT_BP_MARGIN
+ m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN)
+ #else
+ m_sets[0].update(proxy->leaf,aabb,velocity)
+ #endif
+ )
+ {
+ ++m_updates_done;
+ docollide=true;
+ }
+ }
+ else
+ {/* Teleporting */
+ m_sets[0].update(proxy->leaf,aabb);
+ ++m_updates_done;
+ docollide=true;
+ }
+ }
+ listremove(proxy,m_stageRoots[proxy->stage]);
+ proxy->aabb = aabb;
+ proxy->stage = m_stageCurrent;
+ listappend(proxy,m_stageRoots[m_stageCurrent]);
+ if(docollide)
+ {
+ m_needcleanup=true;
+ if(!m_deferedcollide)
+ {
+ btDbvtTreeCollider collider(this);
+ btDbvt::collideTT(m_sets[1].m_root,proxy->leaf,collider);
+ btDbvt::collideTT(m_sets[0].m_root,proxy->leaf,collider);
+ }
+ }
+ }
+}
+
+//
+void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+collide(dispatcher);
+#if DBVT_BP_PROFILE
+if(0==(m_pid%DBVT_BP_PROFILING_RATE))
+ {
+ printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
+ unsigned int total=m_profiling.m_total;
+ if(total<=0) total=1;
+ printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE);
+ printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE);
+ printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE);
+ printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE);
+ const unsigned long sum=m_profiling.m_ddcollide+
+ m_profiling.m_fdcollide+
+ m_profiling.m_cleanup;
+ printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE);
+ printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE));
+ clear(m_profiling);
+ m_clock.reset();
+ }
+#endif
+}
+
+//
+void btDbvtBroadphase::collide(btDispatcher* dispatcher)
+{
+SPC(m_profiling.m_total);
+/* optimize */
+m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
+if(m_fixedleft)
+ {
+ const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
+ m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
+ m_fixedleft=btMax(0,m_fixedleft-count);
+ }
+/* dynamic -> fixed set */
+m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
+btDbvtProxy* current=m_stageRoots[m_stageCurrent];
+if(current)
+ {
+ btDbvtTreeCollider collider(this);
+ do {
+ btDbvtProxy* next=current->links[1];
+ listremove(current,m_stageRoots[current->stage]);
+ listappend(current,m_stageRoots[STAGECOUNT]);
+ #if DBVT_BP_ACCURATESLEEPING
+ m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher);
+ collider.proxy=current;
+ btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider);
+ btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider);
+ #endif
+ m_sets[0].remove(current->leaf);
+ current->leaf = m_sets[1].insert(current->aabb,current);
+ current->stage = STAGECOUNT;
+ current = next;
+ } while(current);
+ m_fixedleft=m_sets[1].m_leaves;
+ m_needcleanup=true;
+ }
+/* collide dynamics */
+ {
+ btDbvtTreeCollider collider(this);
+ if(m_deferedcollide)
+ {
+ SPC(m_profiling.m_fdcollide);
+ btDbvt::collideTT(m_sets[0].m_root,m_sets[1].m_root,collider);
+ }
+ if(m_deferedcollide)
+ {
+ SPC(m_profiling.m_ddcollide);
+ btDbvt::collideTT(m_sets[0].m_root,m_sets[0].m_root,collider);
+ }
+ }
+/* clean up */
+if(m_needcleanup)
+ {
+ SPC(m_profiling.m_cleanup);
+ btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
+ if(pairs.size()>0)
+ {
+ const int ci=pairs.size();
+ int ni=btMin(ci,btMax(m_newpairs,(ci*m_cupdates)/100));
+ for(int i=0;ileaf->volume,pb->leaf->volume))
+ {
+ #if DBVT_BP_SORTPAIRS
+ if(pa>pb) btSwap(pa,pb);
+ #endif
+ m_paircache->removeOverlappingPair(pa,pb,dispatcher);
+ --ni;--i;
+ }
+ }
+ if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
+ }
+ }
+++m_pid;
+m_newpairs=1;
+m_needcleanup=false;
+if(m_updates_call>0)
+ { m_updates_ratio=m_updates_done/(btScalar)m_updates_call; }
+ else
+ { m_updates_ratio=0; }
+m_updates_done/=2;
+m_updates_call/=2;
+}
+
+//
+void btDbvtBroadphase::optimize()
+{
+m_sets[0].optimizeTopDown();
+m_sets[1].optimizeTopDown();
+}
+
+//
+btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
+{
+return(m_paircache);
+}
+
+//
+const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
+{
+return(m_paircache);
+}
+
+//
+void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+{
+
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds;
+
+if(!m_sets[0].empty())
+ if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume,
+ m_sets[1].m_root->volume,bounds);
+ else
+ bounds=m_sets[0].m_root->volume;
+else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume;
+ else
+ bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0);
+aabbMin=bounds.Mins();
+aabbMax=bounds.Maxs();
+}
+
+//
+void btDbvtBroadphase::printStats()
+{}
+
+//
+#if DBVT_BP_ENABLE_BENCHMARK
+
+struct btBroadphaseBenchmark
+ {
+ struct Experiment
+ {
+ const char* name;
+ int object_count;
+ int update_count;
+ int spawn_count;
+ int iterations;
+ btScalar speed;
+ btScalar amplitude;
+ };
+ struct Object
+ {
+ btVector3 center;
+ btVector3 extents;
+ btBroadphaseProxy* proxy;
+ btScalar time;
+ void update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi)
+ {
+ time += speed;
+ center[0] = btCos(time*(btScalar)2.17)*amplitude+
+ btSin(time)*amplitude/2;
+ center[1] = btCos(time*(btScalar)1.38)*amplitude+
+ btSin(time)*amplitude;
+ center[2] = btSin(time*(btScalar)0.777)*amplitude;
+ pbi->setAabb(proxy,center-extents,center+extents,0);
+ }
+ };
+ static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); }
+ static btScalar UnitRand() { return(UnsignedRand(16384)/(btScalar)16384); }
+ static void OutputTime(const char* name,btClock& c,unsigned count=0)
+ {
+ const unsigned long us=c.getTimeMicroseconds();
+ const unsigned long ms=(us+500)/1000;
+ const btScalar sec=us/(btScalar)(1000*1000);
+ if(count>0)
+ printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec);
+ else
+ printf("%s : %u us (%u ms)\r\n",name,us,ms);
+ }
+ };
+
+void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
+{
+static const btBroadphaseBenchmark::Experiment experiments[]=
+ {
+ {"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100},
+ /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
+ {"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
+ };
+static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]);
+btAlignedObjectArray objects;
+btClock wallclock;
+/* Begin */
+for(int iexp=0;iexpcenter[0]=btBroadphaseBenchmark::UnitRand()*50;
+ po->center[1]=btBroadphaseBenchmark::UnitRand()*50;
+ po->center[2]=btBroadphaseBenchmark::UnitRand()*50;
+ po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2;
+ po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2;
+ po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2;
+ po->time=btBroadphaseBenchmark::UnitRand()*2000;
+ po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0);
+ objects.push_back(po);
+ }
+ btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock);
+ /* First update */
+ wallclock.reset();
+ for(int i=0;iupdate(speed,amplitude,pbi);
+ }
+ btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock);
+ /* Updates */
+ wallclock.reset();
+ for(int i=0;iupdate(speed,amplitude,pbi);
+ }
+ pbi->calculateOverlappingPairs(0);
+ }
+ btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations);
+ /* Clean up */
+ wallclock.reset();
+ for(int i=0;idestroyProxy(objects[i]->proxy,0);
+ delete objects[i];
+ }
+ objects.resize(0);
+ btBroadphaseBenchmark::OutputTime("\tRelease",wallclock);
+ }
+
+}
+#else
+void btDbvtBroadphase::benchmark(btBroadphaseInterface*)
+{}
+#endif
+
+#if DBVT_BP_PROFILE
+#undef SPC
+#endif
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
new file mode 100644
index 00000000000..4576e48f3f4
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
@@ -0,0 +1,117 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 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.
+*/
+///btDbvtBroadphase implementation by Nathanael Presson
+#ifndef BT_DBVT_BROADPHASE_H
+#define BT_DBVT_BROADPHASE_H
+
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+
+//
+// Compile time config
+//
+
+#define DBVT_BP_PROFILE 0
+#define DBVT_BP_SORTPAIRS 1
+#define DBVT_BP_PREVENTFALSEUPDATE 0
+#define DBVT_BP_ACCURATESLEEPING 0
+#define DBVT_BP_ENABLE_BENCHMARK 0
+#define DBVT_BP_MARGIN (btScalar)0.05
+
+#if DBVT_BP_PROFILE
+ #define DBVT_BP_PROFILING_RATE 256
+ #include "LinearMath/btQuickprof.h"
+#endif
+
+//
+// btDbvtProxy
+//
+struct btDbvtProxy : btBroadphaseProxy
+{
+/* Fields */
+btDbvtAabbMm aabb;
+btDbvtNode* leaf;
+btDbvtProxy* links[2];
+int stage;
+/* ctor */
+btDbvtProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
+ btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask)
+ {
+ links[0]=links[1]=0;
+ }
+};
+
+typedef btAlignedObjectArray btDbvtProxyArray;
+
+///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
+///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
+///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
+struct btDbvtBroadphase : btBroadphaseInterface
+{
+/* Config */
+enum {
+ DYNAMIC_SET = 0, /* Dynamic set index */
+ FIXED_SET = 1, /* Fixed set index */
+ STAGECOUNT = 2 /* Number of stages */
+ };
+/* Fields */
+btDbvt m_sets[2]; // Dbvt sets
+btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
+btOverlappingPairCache* m_paircache; // Pair cache
+btScalar m_prediction; // Velocity prediction
+int m_stageCurrent; // Current stage
+int m_fupdates; // % of fixed updates per frame
+int m_dupdates; // % of dynamic updates per frame
+int m_cupdates; // % of cleanup updates per frame
+int m_newpairs; // Number of pairs created
+int m_fixedleft; // Fixed optimization left
+unsigned m_updates_call; // Number of updates call
+unsigned m_updates_done; // Number of updates done
+btScalar m_updates_ratio; // m_updates_done/m_updates_call
+int m_pid; // Parse id
+int m_cid; // Cleanup index
+int m_gid; // Gen id
+bool m_releasepaircache; // Release pair cache on delete
+bool m_deferedcollide; // Defere dynamic/static collision to collide call
+bool m_needcleanup; // Need to run cleanup?
+bool m_initialize; // Initialization
+#if DBVT_BP_PROFILE
+btClock m_clock;
+struct {
+ unsigned long m_total;
+ unsigned long m_ddcollide;
+ unsigned long m_fdcollide;
+ unsigned long m_cleanup;
+ unsigned long m_jobcount;
+ } m_profiling;
+#endif
+/* Methods */
+btDbvtBroadphase(btOverlappingPairCache* paircache=0);
+~btDbvtBroadphase();
+void collide(btDispatcher* dispatcher);
+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);
+void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+void calculateOverlappingPairs(btDispatcher* dispatcher);
+btOverlappingPairCache* getOverlappingPairCache();
+const btOverlappingPairCache* getOverlappingPairCache() const;
+void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
+void printStats();
+static void benchmark(btBroadphaseInterface*);
+};
+
+#endif
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h
index 3d958cc8fef..6db71a0170e 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h
@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef _DISPATCHER_H
#define _DISPATCHER_H
-#include "../../LinearMath/btScalar.h"
+#include "LinearMath/btScalar.h"
class btCollisionAlgorithm;
struct btBroadphaseProxy;
@@ -43,7 +43,9 @@ struct btDispatcherInfo
m_useContinuous(false),
m_debugDraw(0),
m_enableSatConvex(false),
- m_enableSPU(false),
+ m_enableSPU(true),
+ m_useEpa(true),
+ m_allowedCcdPenetration(btScalar(0.04)),
m_stackAllocator(0)
{
@@ -51,17 +53,19 @@ struct btDispatcherInfo
btScalar m_timeStep;
int m_stepCount;
int m_dispatchFunc;
- btScalar m_timeOfImpact;
+ mutable btScalar m_timeOfImpact;
bool m_useContinuous;
class btIDebugDraw* m_debugDraw;
bool m_enableSatConvex;
bool m_enableSPU;
+ bool m_useEpa;
+ btScalar m_allowedCcdPenetration;
btStackAlloc* m_stackAllocator;
};
-/// btDispatcher can be used in combination with broadphase to dispatch overlapping pairs.
-/// For example for pairwise collision detection or user callbacks (game logic).
+///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs.
+///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic).
class btDispatcher
{
@@ -81,12 +85,18 @@ public:
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0;
- virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)=0;
+ virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0;
virtual int getNumManifolds() const = 0;
virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
+ virtual btPersistentManifold** getInternalManifoldPointer() = 0;
+
+ virtual void* allocateCollisionAlgorithm(int size) = 0;
+
+ virtual void freeCollisionAlgorithm(void* ptr) = 0;
+
};
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
new file mode 100644
index 00000000000..3f866ab7c5f
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
@@ -0,0 +1,466 @@
+/*
+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;igetBroadphaseAabb(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();
+}
+
+
+
+
+
+
+//#include
+
+void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
+{
+ btMultiSapProxy* multiProxy = static_cast(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;im_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);
+
+
+
+
+ m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
+ int i;
+
+ for ( i=0;im_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;igetBroadphaseAabb(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;im_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;im_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 )
+ {
+ 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;im_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;iprintStats();
+
+ }
+ */
+
+}
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
new file mode 100644
index 00000000000..a0c002de856
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
@@ -0,0 +1,144 @@
+/*
+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 btSapBroadphaseArray;
+
+///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 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(userPtr,collisionFilterGroup,collisionFilterMask),
+ m_aabbMin(aabbMin),
+ m_aabbMax(aabbMax),
+ m_shapeType(shapeType)
+ {
+ m_multiSapParentProxy =this;
+ }
+
+
+ };
+
+protected:
+
+
+ btAlignedObjectArray 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);
+
+ 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(-1e30f,-1e30f,-1e30f);
+ aabbMax.setValue(1e30f,1e30f,1e30f);
+ }
+
+ void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
+
+ virtual void printStats();
+
+ void quicksort (btBroadphasePairArray& a, int lo, int hi);
+
+};
+
+#endif //BT_MULTI_SAP_BROADPHASE
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
index 60f0a41a9d7..ff65cdde79f 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
@@ -1,4 +1,3 @@
-
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
@@ -21,44 +20,43 @@ subject to the following restrictions:
#include "btDispatcher.h"
#include "btCollisionAlgorithm.h"
+#include
+
int gOverlappingPairs = 0;
-btOverlappingPairCache::btOverlappingPairCache():
-m_blockedForChanges(false),
-m_overlapFilterCallback(0)
-//m_NumOverlapBroadphasePair(0)
+int gRemovePairs =0;
+int gAddedPairs =0;
+int gFindPairs =0;
+
+
+
+
+btHashedOverlappingPairCache::btHashedOverlappingPairCache():
+ m_overlapFilterCallback(0),
+ m_blockedForChanges(false)
{
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+ growTables();
}
-btOverlappingPairCache::~btOverlappingPairCache()
+
+
+btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
{
//todo/test: show we erase/delete data, or is it automatic
}
-void btOverlappingPairCache::removeOverlappingPair(btBroadphasePair& findPair)
-{
-
- int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
- if (findIndex < m_overlappingPairArray.size())
- {
- gOverlappingPairs--;
- btBroadphasePair& pair = m_overlappingPairArray[findIndex];
- cleanOverlappingPair(pair);
-
- m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.size()-1);
- m_overlappingPairArray.pop_back();
- }
-}
-
-void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair)
+void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
{
if (pair.m_algorithm)
{
{
- delete pair.m_algorithm;;
+ pair.m_algorithm->~btCollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
pair.m_algorithm=0;
}
}
@@ -67,60 +65,20 @@ void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair)
-
-void btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
-{
- //don't add overlap with own
- assert(proxy0 != proxy1);
-
- if (!needsBroadphaseCollision(proxy0,proxy1))
- return;
-
-
- btBroadphasePair pair(*proxy0,*proxy1);
-
- m_overlappingPairArray.push_back(pair);
- gOverlappingPairs++;
-
-}
-
-///this findPair becomes really slow. Either sort the list to speedup the query, or
-///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
-///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
-///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
- btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
-{
- if (!needsBroadphaseCollision(proxy0,proxy1))
- return 0;
-
- btBroadphasePair tmpPair(*proxy0,*proxy1);
- int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
-
- if (findIndex < m_overlappingPairArray.size())
- {
- //assert(it != m_overlappingPairSet.end());
- btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
- return pair;
- }
- return 0;
-}
-
-
-
-
-
-void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy)
+void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class CleanPairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_cleanProxy;
btOverlappingPairCache* m_pairCache;
+ btDispatcher* m_dispatcher;
public:
- CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache)
+ CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
:m_cleanProxy(cleanProxy),
- m_pairCache(pairCache)
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
@@ -128,22 +86,23 @@ void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy)
if ((pair.m_pProxy0 == m_cleanProxy) ||
(pair.m_pProxy1 == m_cleanProxy))
{
- m_pairCache->cleanOverlappingPair(pair);
+ m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
}
return false;
}
};
- CleanPairCallback cleanPairs(proxy,this);
+ CleanPairCallback cleanPairs(proxy,this,dispatcher);
- processAllOverlappingPairs(&cleanPairs);
+ processAllOverlappingPairs(&cleanPairs,dispatcher);
}
-void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy)
+
+void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class RemovePairCallback : public btOverlapCallback
@@ -166,12 +125,346 @@ void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseP
RemovePairCallback removeCallback(proxy);
- processAllOverlappingPairs(&removeCallback);
+ processAllOverlappingPairs(&removeCallback,dispatcher);
}
-void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback)
+
+
+btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+ gFindPairs++;
+ if(proxy0>proxy1) btSwap(proxy0,proxy1);
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+
+ int hash = static_cast(getHash(static_cast(proxyId1), static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+ if (hash >= m_hashTable.size())
+ {
+ return NULL;
+ }
+
+ int index = m_hashTable[hash];
+ while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+ {
+ index = m_next[index];
+ }
+
+ if (index == BT_NULL_PAIR)
+ {
+ return NULL;
+ }
+
+ btAssert(index < m_overlappingPairArray.size());
+
+ return &m_overlappingPairArray[index];
+}
+
+//#include
+
+void btHashedOverlappingPairCache::growTables()
+{
+
+ int newCapacity = m_overlappingPairArray.capacity();
+
+ if (m_hashTable.size() < newCapacity)
+ {
+ //grow hashtable and next table
+ int curHashtableSize = m_hashTable.size();
+
+ m_hashTable.resize(newCapacity);
+ m_next.resize(newCapacity);
+
+
+ int i;
+
+ for (i= 0; i < newCapacity; ++i)
+ {
+ m_hashTable[i] = BT_NULL_PAIR;
+ }
+ for (i = 0; i < newCapacity; ++i)
+ {
+ m_next[i] = BT_NULL_PAIR;
+ }
+
+ for(i=0;igetUid();
+ int proxyId2 = pair.m_pProxy1->getUid();
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+ int hashValue = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+ m_next[i] = m_hashTable[hashValue];
+ m_hashTable[hashValue] = i;
+ }
+
+
+ }
+}
+
+btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+ if(proxy0>proxy1) btSwap(proxy0,proxy1);
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+
+ int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+
+
+ btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+ if (pair != NULL)
+ {
+ return pair;
+ }
+ /*for(int i=0;i%u\r\n",proxyId1,proxyId2);
+ internalFindPair(proxy0, proxy1, hash);
+ }
+ }*/
+ int count = m_overlappingPairArray.size();
+ int oldCapacity = m_overlappingPairArray.capacity();
+ void* mem = &m_overlappingPairArray.expand();
+ int newCapacity = m_overlappingPairArray.capacity();
+
+ if (oldCapacity < newCapacity)
+ {
+ growTables();
+ //hash with new capacity
+ hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+ }
+
+ pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+// pair->m_pProxy0 = proxy0;
+// pair->m_pProxy1 = proxy1;
+ pair->m_algorithm = 0;
+ pair->m_userInfo = 0;
+
+
+ m_next[count] = m_hashTable[hash];
+ m_hashTable[hash] = count;
+
+ return pair;
+}
+
+
+
+void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
+{
+ gRemovePairs++;
+ if(proxy0>proxy1) btSwap(proxy0,proxy1);
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+
+ int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+ btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+ if (pair == NULL)
+ {
+ return 0;
+ }
+
+ cleanOverlappingPair(*pair,dispatcher);
+
+ void* userData = pair->m_userInfo;
+
+ btAssert(pair->m_pProxy0->getUid() == proxyId1);
+ btAssert(pair->m_pProxy1->getUid() == proxyId2);
+
+ int pairIndex = int(pair - &m_overlappingPairArray[0]);
+ btAssert(pairIndex < m_overlappingPairArray.size());
+
+ // Remove the pair from the hash table.
+ int index = m_hashTable[hash];
+ btAssert(index != BT_NULL_PAIR);
+
+ int previous = BT_NULL_PAIR;
+ while (index != pairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != BT_NULL_PAIR)
+ {
+ btAssert(m_next[previous] == pairIndex);
+ m_next[previous] = m_next[pairIndex];
+ }
+ else
+ {
+ m_hashTable[hash] = m_next[pairIndex];
+ }
+
+ // We now move the last pair into spot of the
+ // pair being removed. We need to fix the hash
+ // table indices to support the move.
+
+ int lastPairIndex = m_overlappingPairArray.size() - 1;
+
+ // If the removed pair is the last pair, we are done.
+ if (lastPairIndex == pairIndex)
+ {
+ m_overlappingPairArray.pop_back();
+ return userData;
+ }
+
+ // Remove the last pair from the hash table.
+ const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
+ /* missing swap here too, Nat. */
+ int lastHash = static_cast(getHash(static_cast(last->m_pProxy0->getUid()), static_cast(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1));
+
+ index = m_hashTable[lastHash];
+ btAssert(index != BT_NULL_PAIR);
+
+ previous = BT_NULL_PAIR;
+ while (index != lastPairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != BT_NULL_PAIR)
+ {
+ btAssert(m_next[previous] == lastPairIndex);
+ m_next[previous] = m_next[lastPairIndex];
+ }
+ else
+ {
+ m_hashTable[lastHash] = m_next[lastPairIndex];
+ }
+
+ // Copy the last pair into the remove pair's spot.
+ m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
+
+ // Insert the last pair into the hash table
+ m_next[pairIndex] = m_hashTable[lastHash];
+ m_hashTable[lastHash] = pairIndex;
+
+ m_overlappingPairArray.pop_back();
+
+ return userData;
+}
+//#include
+
+void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+{
+
+ int i;
+
+// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
+ for (i=0;iprocessOverlap(*pair))
+ {
+ removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
+
+ gOverlappingPairs--;
+ } else
+ {
+ i++;
+ }
+ }
+}
+
+
+
+void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
+{
+ if (!hasDeferredRemoval())
+ {
+ btBroadphasePair findPair(*proxy0,*proxy1);
+
+ int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
+ if (findIndex < m_overlappingPairArray.size())
+ {
+ gOverlappingPairs--;
+ btBroadphasePair& pair = m_overlappingPairArray[findIndex];
+ void* userData = pair.m_userInfo;
+ cleanOverlappingPair(pair,dispatcher);
+
+ m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
+ m_overlappingPairArray.pop_back();
+ return userData;
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ //don't add overlap with own
+ assert(proxy0 != proxy1);
+
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ void* mem = &m_overlappingPairArray.expand();
+ btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+ gOverlappingPairs++;
+ gAddedPairs++;
+ return pair;
+
+}
+
+///this findPair becomes really slow. Either sort the list to speedup the query, or
+///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
+///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
+///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
+ btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ btBroadphasePair tmpPair(*proxy0,*proxy1);
+ int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
+
+ if (findIndex < m_overlappingPairArray.size())
+ {
+ //assert(it != m_overlappingPairSet.end());
+ btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
+ return pair;
+ }
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+//#include
+
+void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
{
int i;
@@ -182,9 +475,9 @@ void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callb
btBroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*pair))
{
- cleanOverlappingPair(*pair);
+ cleanOverlappingPair(*pair,dispatcher);
- m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+ m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1);
m_overlappingPairArray.pop_back();
gOverlappingPairs--;
} else
@@ -194,3 +487,93 @@ void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callb
}
}
+
+
+
+btSortedOverlappingPairCache::btSortedOverlappingPairCache():
+ m_blockedForChanges(false),
+ m_hasDeferredRemoval(true),
+ m_overlapFilterCallback(0)
+{
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+}
+
+btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
+{
+ //todo/test: show we erase/delete data, or is it automatic
+}
+
+void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
+{
+ if (pair.m_algorithm)
+ {
+ {
+ pair.m_algorithm->~btCollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+ pair.m_algorithm=0;
+ gRemovePairs--;
+ }
+ }
+}
+
+
+void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+ class CleanPairCallback : public btOverlapCallback
+ {
+ btBroadphaseProxy* m_cleanProxy;
+ btOverlappingPairCache* m_pairCache;
+ btDispatcher* m_dispatcher;
+
+ public:
+ CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
+ :m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
+ {
+ }
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ if ((pair.m_pProxy0 == m_cleanProxy) ||
+ (pair.m_pProxy1 == m_cleanProxy))
+ {
+ m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+ }
+ return false;
+ }
+
+ };
+
+ CleanPairCallback cleanPairs(proxy,this,dispatcher);
+
+ processAllOverlappingPairs(&cleanPairs,dispatcher);
+
+}
+
+
+void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+ class RemovePairCallback : public btOverlapCallback
+ {
+ btBroadphaseProxy* m_obsoleteProxy;
+
+ public:
+ RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
+ :m_obsoleteProxy(obsoleteProxy)
+ {
+ }
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ return ((pair.m_pProxy0 == m_obsoleteProxy) ||
+ (pair.m_pProxy1 == m_obsoleteProxy));
+ }
+
+ };
+
+ RemovePairCallback removeCallback(proxy);
+
+ processAllOverlappingPairs(&removeCallback,dispatcher);
+}
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
index a81fe3264df..66679bd218a 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
@@ -1,4 +1,3 @@
-
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
@@ -20,9 +19,13 @@ subject to the following restrictions:
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
-#include "../../LinearMath/btPoint3.h"
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "btOverlappingPairCallback.h"
+#include "LinearMath/btPoint3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+class btDispatcher;
+
+typedef btAlignedObjectArray btBroadphasePairArray;
struct btOverlapCallback
{
@@ -30,6 +33,7 @@ struct btOverlapCallback
{}
//return true for deletion of the pair
virtual bool processOverlap(btBroadphasePair& pair) = 0;
+
};
struct btOverlapFilterCallback
@@ -40,38 +44,261 @@ struct btOverlapFilterCallback
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
};
-///btOverlappingPairCache maintains the objects with overlapping AABB
+
+
+
+
+
+
+extern int gRemovePairs;
+extern int gAddedPairs;
+extern int gFindPairs;
+
+const int BT_NULL_PAIR=0xffffffff;
+
+///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
+///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations.
+class btOverlappingPairCache : public btOverlappingPairCallback
+{
+public:
+ virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
+
+ virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
+
+ virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
+
+ virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
+
+ virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
+
+ virtual int getNumOverlappingPairs() const = 0;
+
+ virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0;
+
+ virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
+
+ virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
+
+ virtual bool hasDeferredRemoval() = 0;
+
+};
+
+/// 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
+{
+ btBroadphasePairArray m_overlappingPairArray;
+ btOverlapFilterCallback* m_overlapFilterCallback;
+ bool m_blockedForChanges;
+
+
+public:
+ btHashedOverlappingPairCache();
+ virtual ~btHashedOverlappingPairCache();
+
+
+ void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
+
+ SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
+ {
+ if (m_overlapFilterCallback)
+ return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+
+ bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+ collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+
+ return collides;
+ }
+
+ // Add a pair and return the new pair. If the pair already exists,
+ // no new pair is created and the old one is returned.
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+ {
+ gAddedPairs++;
+
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ return internalAddPair(proxy0,proxy1);
+ }
+
+
+
+ void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
+
+ virtual btBroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ const btBroadphasePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
+
+ void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
+
+
+
+ btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
+
+ int GetCount() const { return m_overlappingPairArray.size(); }
+// btBroadphasePair* GetPairs() { return m_pairs; }
+
+ btOverlapFilterCallback* getOverlapFilterCallback()
+ {
+ return m_overlapFilterCallback;
+ }
+
+ void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+ {
+ m_overlapFilterCallback = callback;
+ }
+
+ int getNumOverlappingPairs() const
+ {
+ return m_overlappingPairArray.size();
+ }
+private:
+
+ btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+ void growTables();
+
+ SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2)
+ {
+ return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2;
+ }
+
+ /*
+ // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
+ // This assumes proxyId1 and proxyId2 are 16-bit.
+ SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2)
+ {
+ int key = (proxyId2 << 16) | proxyId1;
+ key = ~key + (key << 15);
+ key = key ^ (key >> 12);
+ key = key + (key << 2);
+ key = key ^ (key >> 4);
+ key = key * 2057;
+ key = key ^ (key >> 16);
+ return key;
+ }
+ */
+
+
+
+ SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
+ {
+ int key = static_cast(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16));
+ // Thomas Wang's hash
+
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return static_cast(key);
+ }
+
+
+
+
+
+ SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
+ {
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+ #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
+ if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);
+ #endif
+
+ int index = m_hashTable[hash];
+
+ while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+ {
+ index = m_next[index];
+ }
+
+ if ( index == BT_NULL_PAIR )
+ {
+ return NULL;
+ }
+
+ btAssert(index < m_overlappingPairArray.size());
+
+ return &m_overlappingPairArray[index];
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return false;
+ }
+
+public:
+
+ btAlignedObjectArray m_hashTable;
+ btAlignedObjectArray m_next;
+
+};
+
+
+
+
+///btSortedOverlappingPairCache maintains the objects with overlapping AABB
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
-class btOverlappingPairCache : public btBroadphaseInterface
+class btSortedOverlappingPairCache : public btOverlappingPairCache
{
protected:
//avoid brute-force finding all the time
- btAlignedObjectArray m_overlappingPairArray;
-
+ btBroadphasePairArray m_overlappingPairArray;
+
//during the dispatch, check that user doesn't destroy/create proxy
bool m_blockedForChanges;
+
+ ///by default, do the removal during the pair traversal
+ bool m_hasDeferredRemoval;
//if set, use the callback instead of the built in filter in needBroadphaseCollision
btOverlapFilterCallback* m_overlapFilterCallback;
+
public:
- btOverlappingPairCache();
- virtual ~btOverlappingPairCache();
+ btSortedOverlappingPairCache();
+ virtual ~btSortedOverlappingPairCache();
- virtual void processAllOverlappingPairs(btOverlapCallback*);
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
- void removeOverlappingPair(btBroadphasePair& pair);
+ void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
- void cleanOverlappingPair(btBroadphasePair& pair);
+ void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
- void addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+ btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
- void cleanProxyFromPairs(btBroadphaseProxy* proxy);
+ void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
- void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy);
+ void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
@@ -84,10 +311,19 @@ class btOverlappingPairCache : public btBroadphaseInterface
return collides;
}
-
+
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ const btBroadphasePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
+
- virtual void refreshOverlappingPairs() =0;
btBroadphasePair* getOverlappingPairArrayPtr()
{
@@ -114,7 +350,88 @@ class btOverlappingPairCache : public btBroadphaseInterface
m_overlapFilterCallback = callback;
}
+ virtual bool hasDeferredRemoval()
+ {
+ return m_hasDeferredRemoval;
+ }
+
+
};
+
+
+
+///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and testing.
+class btNullPairCache : public btOverlappingPairCache
+{
+
+ btBroadphasePairArray m_overlappingPairArray;
+
+public:
+
+ virtual btBroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
+ {
+
+ }
+
+ virtual int getNumOverlappingPairs() const
+ {
+ return 0;
+ }
+
+ virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
+ {
+
+ }
+
+ virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
+ {
+ }
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
+ {
+ }
+
+ virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
+ {
+ return 0;
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return true;
+ }
+
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
+ {
+ return 0;
+ }
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/)
+ {
+ return 0;
+ }
+
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
+ {
+ }
+
+
+};
+
+
#endif //OVERLAPPING_PAIR_CACHE_H
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
new file mode 100644
index 00000000000..9c7b6f81367
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
@@ -0,0 +1,40 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef OVERLAPPING_PAIR_CALLBACK_H
+#define OVERLAPPING_PAIR_CALLBACK_H
+
+class btDispatcher;
+struct btBroadphasePair;
+
+///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
+class btOverlappingPairCallback
+{
+public:
+ virtual ~btOverlappingPairCallback()
+ {
+
+ }
+
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0;
+
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0;
+
+};
+
+#endif //OVERLAPPING_PAIR_CALLBACK_H
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
new file mode 100644
index 00000000000..a30bd1fd9e1
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
@@ -0,0 +1,1025 @@
+/*
+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 "btQuantizedBvh.h"
+
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btIDebugDraw.h"
+
+
+btQuantizedBvh::btQuantizedBvh() : m_useQuantization(false),
+ //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
+ m_traversalMode(TRAVERSAL_STACKLESS)
+ //m_traversalMode(TRAVERSAL_RECURSIVE)
+ ,m_subtreeHeaderCount(0) //PCK: add this line
+{
+
+}
+
+
+
+
+
+void btQuantizedBvh::buildInternal()
+{
+ ///assumes that caller filled in the m_quantizedLeafNodes
+ m_useQuantization = true;
+ int numLeafNodes = 0;
+
+ if (m_useQuantization)
+ {
+ //now we have an array of leafnodes in m_leafNodes
+ numLeafNodes = m_quantizedLeafNodes.size();
+
+ m_quantizedContiguousNodes.resize(2*numLeafNodes);
+
+ }
+
+ m_curNodeIndex = 0;
+
+ buildTree(0,numLeafNodes);
+
+ ///if the entire tree is small then subtree size, we need to create a header info for the tree
+ if(m_useQuantization && !m_SubtreeHeaders.size())
+ {
+ btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+ subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+ subtree.m_rootNodeIndex = 0;
+ subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+ }
+
+ //PCK: update the copy of the size
+ m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+ //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+ m_quantizedLeafNodes.clear();
+ m_leafNodes.clear();
+}
+
+
+
+///just for debugging, to visualize the individual patches/subtrees
+#ifdef DEBUG_PATCH_COLORS
+btVector3 color[4]=
+{
+ btVector3(255,0,0),
+ btVector3(0,255,0),
+ btVector3(0,0,255),
+ btVector3(0,255,255)
+};
+#endif //DEBUG_PATCH_COLORS
+
+
+
+void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin)
+{
+ //enlarge the AABB to avoid division by zero when initializing the quantization values
+ btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
+ m_bvhAabbMin = bvhAabbMin - clampValue;
+ m_bvhAabbMax = bvhAabbMax + clampValue;
+ btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+ m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+ m_useQuantization = true;
+}
+
+
+
+
+btQuantizedBvh::~btQuantizedBvh()
+{
+}
+
+#ifdef DEBUG_TREE_BUILDING
+int gStackDepth = 0;
+int gMaxStackDepth = 0;
+#endif //DEBUG_TREE_BUILDING
+
+void btQuantizedBvh::buildTree (int startIndex,int endIndex)
+{
+#ifdef DEBUG_TREE_BUILDING
+ gStackDepth++;
+ if (gStackDepth > gMaxStackDepth)
+ gMaxStackDepth = gStackDepth;
+#endif //DEBUG_TREE_BUILDING
+
+
+ int splitAxis, splitIndex, i;
+ int numIndices =endIndex-startIndex;
+ int curIndex = m_curNodeIndex;
+
+ assert(numIndices>0);
+
+ if (numIndices==1)
+ {
+#ifdef DEBUG_TREE_BUILDING
+ gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+
+ assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex);
+
+ m_curNodeIndex++;
+ return;
+ }
+ //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+ splitAxis = calcSplittingAxis(startIndex,endIndex);
+
+ splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis);
+
+ int internalNodeIndex = m_curNodeIndex;
+
+ setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);
+ setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);
+
+ for (i=startIndex;im_escapeIndex;
+
+ int leftChildNodexIndex = m_curNodeIndex;
+
+ //build left child tree
+ buildTree(startIndex,splitIndex);
+
+ int rightChildNodexIndex = m_curNodeIndex;
+ //build right child tree
+ buildTree(splitIndex,endIndex);
+
+#ifdef DEBUG_TREE_BUILDING
+ gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+
+ int escapeIndex = m_curNodeIndex - curIndex;
+
+ if (m_useQuantization)
+ {
+ //escapeIndex is the number of nodes of this subtree
+ const int sizeQuantizedNode =sizeof(btQuantizedBvhNode);
+ const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
+ if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
+ {
+ updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex);
+ }
+ }
+
+ setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex);
+
+}
+
+void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex)
+{
+ btAssert(m_useQuantization);
+
+ btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
+ int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
+ int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast(sizeof(btQuantizedBvhNode));
+
+ btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
+ int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
+ int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast(sizeof(btQuantizedBvhNode));
+
+ if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+ {
+ btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+ subtree.setAabbFromQuantizeNode(leftChildNode);
+ subtree.m_rootNodeIndex = leftChildNodexIndex;
+ subtree.m_subtreeSize = leftSubTreeSize;
+ }
+
+ if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+ {
+ btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+ subtree.setAabbFromQuantizeNode(rightChildNode);
+ subtree.m_rootNodeIndex = rightChildNodexIndex;
+ subtree.m_subtreeSize = rightSubTreeSize;
+ }
+
+ //PCK: update the copy of the size
+ m_subtreeHeaderCount = m_SubtreeHeaders.size();
+}
+
+
+int btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis)
+{
+ int i;
+ int splitIndex =startIndex;
+ int numIndices = endIndex - startIndex;
+ btScalar splitValue;
+
+ btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+ for (i=startIndex;i splitValue)
+ {
+ //swap
+ swapLeafNodes(i,splitIndex);
+ splitIndex++;
+ }
+ }
+
+ //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
+ //otherwise the tree-building might fail due to stack-overflows in certain cases.
+ //unbalanced1 is unsafe: it can cause stack overflows
+ //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
+
+ //unbalanced2 should work too: always use center (perfect balanced trees)
+ //bool unbalanced2 = true;
+
+ //this should be safe too:
+ int rangeBalancedIndices = numIndices/3;
+ bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+
+ if (unbalanced)
+ {
+ splitIndex = startIndex+ (numIndices>>1);
+ }
+
+ bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
+ (void)unbal;
+ btAssert(!unbal);
+
+ return splitIndex;
+}
+
+
+int btQuantizedBvh::calcSplittingAxis(int startIndex,int endIndex)
+{
+ int i;
+
+ btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+ btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
+ int numIndices = endIndex-startIndex;
+
+ for (i=startIndex;im_aabbMinOrg,rootNode->m_aabbMaxOrg);
+ isLeafNode = rootNode->m_escapeIndex == -1;
+
+ //PCK: unsigned instead of bool
+ if (isLeafNode && (aabbOverlap != 0))
+ {
+ nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
+ }
+
+ //PCK: unsigned instead of bool
+ if ((aabbOverlap != 0) || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->m_escapeIndex;
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+ if (maxIterations < walkIterations)
+ maxIterations = walkIterations;
+
+}
+
+/*
+///this was the original recursive traversal, before we optimized towards stackless traversal
+void btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax);
+ if (aabbOverlap)
+ {
+ isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild);
+ if (isLeafNode)
+ {
+ nodeCallback->processNode(rootNode);
+ } else
+ {
+ walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax);
+ walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax);
+ }
+ }
+
+}
+*/
+
+void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+ btAssert(m_useQuantization);
+
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned aabbOverlap;
+
+ //PCK: unsigned instead of bool
+ aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax);
+ isLeafNode = currentNode->isLeafNode();
+
+ //PCK: unsigned instead of bool
+ if (aabbOverlap != 0)
+ {
+ if (isLeafNode)
+ {
+ nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex());
+ } else
+ {
+ //process left and right children
+ const btQuantizedBvhNode* leftChildNode = currentNode+1;
+ walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+
+ const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex();
+ walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ }
+ }
+}
+
+
+
+
+
+void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+{
+ btAssert(m_useQuantization);
+
+ int curIndex = startNodeIndex;
+ int walkIterations = 0;
+ int subTreeSize = endNodeIndex - startNodeIndex;
+ (void)subTreeSize;
+
+ const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+ int escapeIndex;
+
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned boxBoxOverlap = 0;
+ unsigned rayBoxOverlap = 0;
+
+ btScalar lambda_max = 1.0;
+#define RAYAABB2
+#ifdef RAYAABB2
+ btVector3 rayFrom = raySource;
+ btVector3 rayDirection = (rayTarget-raySource);
+ rayDirection.normalize ();
+ lambda_max = rayDirection.dot(rayTarget-raySource);
+ ///what about division by zero? --> just set rayDirection[i] to 1.0
+ rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[0];
+ rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[1];
+ rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[2];
+ unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
+#endif
+
+ /* Quick pruning by quantized box */
+ btVector3 rayAabbMin = raySource;
+ btVector3 rayAabbMax = raySource;
+ rayAabbMin.setMin(rayTarget);
+ rayAabbMax.setMax(rayTarget);
+
+ /* Add box cast extents to bounding box */
+ rayAabbMin += aabbMin;
+ rayAabbMax += aabbMax;
+
+ unsigned short int quantizedQueryAabbMin[3];
+ unsigned short int quantizedQueryAabbMax[3];
+ quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0);
+ quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1);
+
+ while (curIndex < endNodeIndex)
+ {
+
+//#define VISUALLY_ANALYZE_BVH 1
+#ifdef VISUALLY_ANALYZE_BVH
+ //some code snippet to debugDraw aabb, to visually analyze bvh structure
+ static int drawPatch = 0;
+ //need some global access to a debugDrawer
+ extern btIDebugDraw* debugDrawerPtr;
+ if (curIndex==drawPatch)
+ {
+ btVector3 aabbMin,aabbMax;
+ aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+ aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+ btVector3 color(1,0,0);
+ debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+ }
+#endif//VISUALLY_ANALYZE_BVH
+
+ //catch bugs in tree data
+ assert (walkIterations < subTreeSize);
+
+ walkIterations++;
+ //PCK: unsigned instead of bool
+ // only interested if this is closer than any previous hit
+ btScalar param = 1.0;
+ rayBoxOverlap = 0;
+ boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+ isLeafNode = rootNode->isLeafNode();
+ if (boxBoxOverlap)
+ {
+ btVector3 bounds[2];
+ bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
+ bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
+ /* Add box cast extents */
+ bounds[0] += aabbMin;
+ bounds[1] += aabbMax;
+ btVector3 normal;
+#if 0
+ bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
+ bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal);
+ if (ra2 != ra)
+ {
+ printf("functions don't match\n");
+ }
+#endif
+#ifdef RAYAABB2
+ ///careful with this check: need to check division by zero (above) and fix the unQuantize method
+ ///thanks Joerg/hiker for the reproduction case!
+ ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+
+ rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
+#else
+ rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
+#endif
+ }
+
+ if (isLeafNode && rayBoxOverlap)
+ {
+ nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+ }
+
+ //PCK: unsigned instead of bool
+ if ((rayBoxOverlap != 0) || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->getEscapeIndex();
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+ if (maxIterations < walkIterations)
+ maxIterations = walkIterations;
+
+}
+
+void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const
+{
+ btAssert(m_useQuantization);
+
+ int curIndex = startNodeIndex;
+ int walkIterations = 0;
+ int subTreeSize = endNodeIndex - startNodeIndex;
+ (void)subTreeSize;
+
+ const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+ int escapeIndex;
+
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned aabbOverlap;
+
+ while (curIndex < endNodeIndex)
+ {
+
+//#define VISUALLY_ANALYZE_BVH 1
+#ifdef VISUALLY_ANALYZE_BVH
+ //some code snippet to debugDraw aabb, to visually analyze bvh structure
+ static int drawPatch = 0;
+ //need some global access to a debugDrawer
+ extern btIDebugDraw* debugDrawerPtr;
+ if (curIndex==drawPatch)
+ {
+ btVector3 aabbMin,aabbMax;
+ aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+ aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+ btVector3 color(1,0,0);
+ debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+ }
+#endif//VISUALLY_ANALYZE_BVH
+
+ //catch bugs in tree data
+ assert (walkIterations < subTreeSize);
+
+ walkIterations++;
+ //PCK: unsigned instead of bool
+ aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+ isLeafNode = rootNode->isLeafNode();
+
+ if (isLeafNode && aabbOverlap)
+ {
+ nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+ }
+
+ //PCK: unsigned instead of bool
+ if ((aabbOverlap != 0) || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->getEscapeIndex();
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+ if (maxIterations < walkIterations)
+ maxIterations = walkIterations;
+
+}
+
+//This traversal can be called from Playstation 3 SPU
+void btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+ btAssert(m_useQuantization);
+
+ int i;
+
+
+ for (i=0;im_SubtreeHeaders.size();i++)
+ {
+ const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+
+ //PCK: unsigned instead of bool
+ unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+ if (overlap != 0)
+ {
+ walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
+ subtree.m_rootNodeIndex,
+ subtree.m_rootNodeIndex+subtree.m_subtreeSize);
+ }
+ }
+}
+
+
+void btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const
+{
+ bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS;
+ if (fast_path)
+ {
+ walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, btVector3(0, 0, 0), btVector3(0, 0, 0), 0, m_curNodeIndex);
+ } else {
+ /* Otherwise fallback to AABB overlap test */
+ btVector3 aabbMin = raySource;
+ btVector3 aabbMax = raySource;
+ aabbMin.setMin(rayTarget);
+ aabbMax.setMax(rayTarget);
+ reportAabbOverlappingNodex(nodeCallback,aabbMin,aabbMax);
+ }
+}
+
+
+void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS;
+ if (fast_path)
+ {
+ walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+ } else {
+ /* Slow path:
+ Construct the bounding box for the entire box cast and send that down the tree */
+ btVector3 qaabbMin = raySource;
+ btVector3 qaabbMax = raySource;
+ qaabbMin.setMin(rayTarget);
+ qaabbMax.setMax(rayTarget);
+ qaabbMin += aabbMin;
+ qaabbMax += aabbMax;
+ reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
+ }
+}
+
+
+void btQuantizedBvh::swapLeafNodes(int i,int splitIndex)
+{
+ if (m_useQuantization)
+ {
+ btQuantizedBvhNode tmp = m_quantizedLeafNodes[i];
+ m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
+ m_quantizedLeafNodes[splitIndex] = tmp;
+ } else
+ {
+ btOptimizedBvhNode tmp = m_leafNodes[i];
+ m_leafNodes[i] = m_leafNodes[splitIndex];
+ m_leafNodes[splitIndex] = tmp;
+ }
+}
+
+void btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex)
+{
+ if (m_useQuantization)
+ {
+ m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
+ } else
+ {
+ m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
+ }
+}
+
+//PCK: include
+#include
+
+//PCK: consts
+static const unsigned BVH_ALIGNMENT = 16;
+static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
+
+static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
+
+
+
+unsigned int btQuantizedBvh::getAlignmentSerializationPadding()
+{
+ return BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
+}
+
+unsigned btQuantizedBvh::calculateSerializeBufferSize()
+{
+ unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding();
+ baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
+ if (m_useQuantization)
+ {
+ return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode);
+ }
+ return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode);
+}
+
+bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian)
+{
+ assert(m_subtreeHeaderCount == m_SubtreeHeaders.size());
+ m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+/* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+ {
+ ///check alignedment for buffer?
+ btAssert(0);
+ return false;
+ }
+*/
+
+ btQuantizedBvh *targetBvh = (btQuantizedBvh *)o_alignedDataBuffer;
+
+ // construct the class so the virtual function table, etc will be set up
+ // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
+ new (targetBvh) btQuantizedBvh;
+
+ if (i_swapEndian)
+ {
+ targetBvh->m_curNodeIndex = static_cast(btSwapEndian(m_curNodeIndex));
+
+
+ btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin);
+ btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax);
+ btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization);
+
+ targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode);
+ targetBvh->m_subtreeHeaderCount = static_cast(btSwapEndian(m_subtreeHeaderCount));
+ }
+ else
+ {
+ targetBvh->m_curNodeIndex = m_curNodeIndex;
+ targetBvh->m_bvhAabbMin = m_bvhAabbMin;
+ targetBvh->m_bvhAabbMax = m_bvhAabbMax;
+ targetBvh->m_bvhQuantization = m_bvhQuantization;
+ targetBvh->m_traversalMode = m_traversalMode;
+ targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount;
+ }
+
+ targetBvh->m_useQuantization = m_useQuantization;
+
+ unsigned char *nodeData = (unsigned char *)targetBvh;
+ nodeData += sizeof(btQuantizedBvh);
+
+ unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ nodeData += sizeToAdd;
+
+ int nodeCount = m_curNodeIndex;
+
+ if (m_useQuantization)
+ {
+ targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+ if (i_swapEndian)
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+ }
+ }
+ else
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0];
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1];
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2];
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0];
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1];
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2];
+
+ targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex;
+
+
+ }
+ }
+ nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
+ }
+ else
+ {
+ targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+ if (i_swapEndian)
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+ btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+
+ targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex));
+ targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart));
+ targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex));
+ }
+ }
+ else
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg;
+ targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg;
+
+ targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex;
+ targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart;
+ targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex;
+ }
+ }
+ nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
+ }
+
+ sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ nodeData += sizeToAdd;
+
+ // Now serialize the subtree headers
+ targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount);
+ if (i_swapEndian)
+ {
+ for (int i = 0; i < m_subtreeHeaderCount; i++)
+ {
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+ targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex));
+ targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize));
+ }
+ }
+ else
+ {
+ for (int i = 0; i < m_subtreeHeaderCount; i++)
+ {
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+ targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+ targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex);
+ targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize);
+ targetBvh->m_SubtreeHeaders[i] = m_SubtreeHeaders[i];
+ }
+ }
+
+ nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
+
+ return true;
+}
+
+btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+
+ if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+ {
+ return NULL;
+ }
+ btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer;
+
+ if (i_swapEndian)
+ {
+ bvh->m_curNodeIndex = static_cast(btSwapEndian(bvh->m_curNodeIndex));
+
+ btUnSwapVector3Endian(bvh->m_bvhAabbMin);
+ btUnSwapVector3Endian(bvh->m_bvhAabbMax);
+ btUnSwapVector3Endian(bvh->m_bvhQuantization);
+
+ bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode);
+ bvh->m_subtreeHeaderCount = static_cast(btSwapEndian(bvh->m_subtreeHeaderCount));
+ }
+
+ unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
+ btAssert(calculatedBufSize <= i_dataBufferSize);
+
+ if (calculatedBufSize > i_dataBufferSize)
+ {
+ return NULL;
+ }
+
+ unsigned char *nodeData = (unsigned char *)bvh;
+ nodeData += sizeof(btQuantizedBvh);
+
+ unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ nodeData += sizeToAdd;
+
+ int nodeCount = bvh->m_curNodeIndex;
+
+ // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor
+ // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
+ new (bvh) btQuantizedBvh(*bvh, false);
+
+ if (bvh->m_useQuantization)
+ {
+ bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+ if (i_swapEndian)
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+ bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+ }
+ }
+ nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
+ }
+ else
+ {
+ bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+ if (i_swapEndian)
+ {
+ for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+ {
+ btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+ btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+
+ bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
+ bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
+ bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
+ }
+ }
+ nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
+ }
+
+ sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+ nodeData += sizeToAdd;
+
+ // Now serialize the subtree headers
+ bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount);
+ if (i_swapEndian)
+ {
+ for (int i = 0; i < bvh->m_subtreeHeaderCount; i++)
+ {
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+ bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+ bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex));
+ bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize));
+ }
+ }
+
+ return bvh;
+}
+
+// Constructor that prevents btVector3's default constructor from being called
+btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) :
+m_bvhAabbMin(self.m_bvhAabbMin),
+m_bvhAabbMax(self.m_bvhAabbMax),
+m_bvhQuantization(self.m_bvhQuantization)
+{
+
+
+}
+
+
+
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
new file mode 100644
index 00000000000..8a149b533fa
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
@@ -0,0 +1,486 @@
+/*
+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 QUANTIZED_BVH_H
+#define QUANTIZED_BVH_H
+
+//#define DEBUG_CHECK_DEQUANTIZATION 1
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+#ifdef __SPU__
+#define printf spu_printf
+#endif //__SPU__
+
+#include
+#include
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+
+//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
+
+
+//Note: currently we have 16 bytes per quantized node
+#define MAX_SUBTREE_SIZE_IN_BYTES 2048
+
+// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
+// actually) triangles each (since the sign bit is reserved
+#define MAX_NUM_PARTS_IN_BITS 10
+
+///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) btQuantizedBvhNode
+{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes
+ int m_escapeIndexOrTriangleIndex;
+
+ bool isLeafNode() const
+ {
+ //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+ return (m_escapeIndexOrTriangleIndex >= 0);
+ }
+ int getEscapeIndex() const
+ {
+ btAssert(!isLeafNode());
+ return -m_escapeIndexOrTriangleIndex;
+ }
+ int getTriangleIndex() const
+ {
+ btAssert(isLeafNode());
+ // Get only the lower bits where the triangle index is stored
+ return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
+ }
+ int getPartId() const
+ {
+ btAssert(isLeafNode());
+ // Get only the highest bits where the part index is stored
+ return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
+ }
+}
+;
+
+/// btOptimizedBvhNode contains both internal and leaf node information.
+/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
+ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode
+{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ //32 bytes
+ btVector3 m_aabbMinOrg;
+ btVector3 m_aabbMaxOrg;
+
+ //4
+ int m_escapeIndex;
+
+ //8
+ //for child nodes
+ int m_subPart;
+ int m_triangleIndex;
+ int m_padding[5];//bad, due to alignment
+
+
+};
+
+
+///btBvhSubtreeInfo provides info to gather a subtree of limited size
+ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
+{
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ //12 bytes
+ unsigned short int m_quantizedAabbMin[3];
+ unsigned short int m_quantizedAabbMax[3];
+ //4 bytes, points to the root of the subtree
+ int m_rootNodeIndex;
+ //4 bytes
+ int m_subtreeSize;
+ int m_padding[3];
+
+ btBvhSubtreeInfo()
+ {
+ //memset(&m_padding[0], 0, sizeof(m_padding));
+ }
+
+
+ void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
+ {
+ m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
+ m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
+ m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
+ m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
+ m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
+ m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
+ }
+}
+;
+
+
+class btNodeOverlapCallback
+{
+public:
+ virtual ~btNodeOverlapCallback() {};
+
+ virtual void processNode(int subPart, int triangleIndex) = 0;
+};
+
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+
+///for code readability:
+typedef btAlignedObjectArray NodeArray;
+typedef btAlignedObjectArray QuantizedNodeArray;
+typedef btAlignedObjectArray 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 recommended to use quantization for better performance and lower memory requirements.
+ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
+{
+protected:
+
+ NodeArray m_leafNodes;
+ NodeArray m_contiguousNodes;
+
+ QuantizedNodeArray m_quantizedLeafNodes;
+
+ QuantizedNodeArray m_quantizedContiguousNodes;
+
+ int m_curNodeIndex;
+
+
+ //quantization data
+ bool m_useQuantization;
+ btVector3 m_bvhAabbMin;
+ btVector3 m_bvhAabbMax;
+ btVector3 m_bvhQuantization;
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ enum btTraversalMode
+ {
+ TRAVERSAL_STACKLESS = 0,
+ TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
+ TRAVERSAL_RECURSIVE
+ };
+protected:
+
+ btTraversalMode m_traversalMode;
+
+ BvhSubtreeInfoArray m_SubtreeHeaders;
+
+ //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
+ int m_subtreeHeaderCount;
+
+
+ ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
+ ///this might be refactored into a virtual, it is usually not calculated at run-time
+ void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
+ {
+ if (m_useQuantization)
+ {
+ quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
+ } else
+ {
+ m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
+
+ }
+ }
+ void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
+ {
+ if (m_useQuantization)
+ {
+ quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
+ } else
+ {
+ m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
+ }
+ }
+
+ btVector3 getAabbMin(int nodeIndex) const
+ {
+ if (m_useQuantization)
+ {
+ return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
+ }
+ //non-quantized
+ return m_leafNodes[nodeIndex].m_aabbMinOrg;
+
+ }
+ btVector3 getAabbMax(int nodeIndex) const
+ {
+ if (m_useQuantization)
+ {
+ return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
+ }
+ //non-quantized
+ return m_leafNodes[nodeIndex].m_aabbMaxOrg;
+
+ }
+
+
+ void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
+ {
+ if (m_useQuantization)
+ {
+ m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
+ }
+ else
+ {
+ m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
+ }
+
+ }
+
+ void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax)
+ {
+ if (m_useQuantization)
+ {
+ unsigned short int quantizedAabbMin[3];
+ unsigned short int quantizedAabbMax[3];
+ quantize(quantizedAabbMin,newAabbMin,0);
+ quantize(quantizedAabbMax,newAabbMax,1);
+ for (int i=0;i<3;i++)
+ {
+ if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
+ m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
+
+ if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
+ m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
+
+ }
+ } else
+ {
+ //non-quantized
+ m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
+ m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
+ }
+ }
+
+ void swapLeafNodes(int firstIndex,int secondIndex);
+
+ void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
+
+protected:
+
+
+
+ void buildTree (int startIndex,int endIndex);
+
+ int calcSplittingAxis(int startIndex,int endIndex);
+
+ int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
+
+ void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+ void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
+ void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
+
+ ///tree traversal designed for small-memory processors like PS3 SPU
+ void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+
+ ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
+ void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+
+ ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
+ void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
+
+
+#define USE_BANCHLESS 1
+#ifdef USE_BANCHLESS
+ //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
+ SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const
+ {
+ return static_cast(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
+ & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
+ & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
+ 1, 0));
+ }
+#else
+ SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const
+ {
+ bool overlap = true;
+ overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
+ overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
+ overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
+ return overlap;
+ }
+#endif //USE_BANCHLESS
+
+ void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
+
+public:
+ btQuantizedBvh();
+
+ virtual ~btQuantizedBvh();
+
+
+ ///***************************************** expert/internal use only *************************
+ void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
+ QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
+ ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
+ void buildInternal();
+ ///***************************************** expert/internal use only *************************
+
+ void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
+ void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+ SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
+ {
+
+ btAssert(m_useQuantization);
+
+ btAssert(point.getX() <= m_bvhAabbMax.getX());
+ btAssert(point.getY() <= m_bvhAabbMax.getY());
+ btAssert(point.getZ() <= m_bvhAabbMax.getZ());
+
+ btAssert(point.getX() >= m_bvhAabbMin.getX());
+ btAssert(point.getY() >= m_bvhAabbMin.getY());
+ btAssert(point.getZ() >= m_bvhAabbMin.getZ());
+
+ btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
+ ///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
+ ///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
+ ///todo: double-check this
+ if (isMax)
+ {
+ out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
+ out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
+ out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
+ } else
+ {
+ out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
+ out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
+ out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
+ }
+
+
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+ btVector3 newPoint = unQuantize(out);
+ if (isMax)
+ {
+ if (newPoint.getX() < point.getX())
+ {
+ printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+ }
+ if (newPoint.getY() < point.getY())
+ {
+ printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+ }
+ if (newPoint.getZ() < point.getZ())
+ {
+
+ printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+ }
+ } else
+ {
+ if (newPoint.getX() > point.getX())
+ {
+ printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+ }
+ if (newPoint.getY() > point.getY())
+ {
+ printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+ }
+ if (newPoint.getZ() > point.getZ())
+ {
+ printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+ }
+ }
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+ }
+
+
+ SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
+ {
+
+ btAssert(m_useQuantization);
+
+ btVector3 clampedPoint(point2);
+ clampedPoint.setMax(m_bvhAabbMin);
+ clampedPoint.setMin(m_bvhAabbMax);
+
+ quantize(out,clampedPoint,isMax);
+
+ }
+
+ SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
+ {
+ btVector3 vecOut;
+ vecOut.setValue(
+ (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
+ (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
+ (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
+ vecOut += m_bvhAabbMin;
+ return vecOut;
+ }
+
+ ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
+ void setTraversalMode(btTraversalMode traversalMode)
+ {
+ m_traversalMode = traversalMode;
+ }
+
+
+ SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
+ {
+ return m_quantizedContiguousNodes;
+ }
+
+
+ SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
+ {
+ return m_SubtreeHeaders;
+ }
+
+
+ /////Calculate space needed to store BVH for serialization
+ unsigned calculateSerializeBufferSize();
+
+ /// Data buffer MUST be 16 byte aligned
+ virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian);
+
+ ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+ static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+
+ static unsigned int getAlignmentSerializationPadding();
+
+ SIMD_FORCE_INLINE bool isQuantized()
+ {
+ return m_useQuantization;
+ }
+
+private:
+ // Special "copy" constructor that allows for in-place deserialization
+ // Prevents btVector3's default constructor from being called, but doesn't inialize much else
+ // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
+ btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
+
+}
+;
+
+
+#endif //QUANTIZED_BVH_H
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
index 30bcbe0c5f1..a57952ffa06 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
@@ -14,83 +14,84 @@ subject to the following restrictions:
*/
#include "btSimpleBroadphase.h"
-#include
-#include
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btMatrix3x3.h"
#include
+extern int gOverlappingPairs;
void btSimpleBroadphase::validate()
{
- for (int i=0;i=0;i--)
+ if (m_ownsPairCache)
{
- BP_Proxy* proxy = m_pProxies[i];
- destroyProxy(proxy);
+ m_pairCache->~btOverlappingPairCache();
+ btAlignedFree(m_pairCache);
}
- */
}
-btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask)
+btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy)
{
- if (m_numProxies >= m_maxProxies)
+ if (m_numHandles >= m_maxHandles)
{
- assert(0);
+ btAssert(0);
return 0; //should never happen, but don't let the game crash ;-)
}
- assert(min[0]<= max[0] && min[1]<= max[1] && min[2]<= max[2]);
+ assert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]);
- int freeIndex= m_freeProxies[m_firstFreeProxy];
- btSimpleBroadphaseProxy* proxy = new (&m_proxies[freeIndex])btSimpleBroadphaseProxy(min,max,shapeType,userPtr,collisionFilterGroup,collisionFilterMask);
- m_firstFreeProxy++;
-
- btSimpleBroadphaseProxy* proxy1 = &m_proxies[0];
-
- int index = int(proxy - proxy1);
- btAssert(index == freeIndex);
-
- m_pProxies[m_numProxies] = proxy;
- m_numProxies++;
- //validate();
+ int newHandleIndex = allocHandle();
+ btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy);
return proxy;
}
@@ -124,34 +125,19 @@ protected:
};
};
-void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg)
+void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher)
{
- int i;
-
btSimpleBroadphaseProxy* proxy0 = static_cast(proxyOrg);
- btSimpleBroadphaseProxy* proxy1 = &m_proxies[0];
-
- int index = int(proxy0 - proxy1);
- btAssert (index < m_maxProxies);
- m_freeProxies[--m_firstFreeProxy] = index;
+ freeHandle(proxy0);
+
+ m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher);
- removeOverlappingPairsContainingProxy(proxyOrg);
-
- for (i=0;im_min = aabbMin;
@@ -186,37 +172,129 @@ public:
}
};
-void btSimpleBroadphase::refreshOverlappingPairs()
+void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{
//first check for new overlapping pairs
int i,j;
- for (i=0;i= 0)
{
- btBroadphaseProxy* proxy0 = m_pProxies[i];
- for (j=i+1;jfindPair(proxy0,proxy1))
+ {
+ m_pairCache->addOverlappingPair(proxy0,proxy1);
+ }
+ } else
+ {
+ if (!m_pairCache->hasDeferredRemoval())
+ {
+ if ( m_pairCache->findPair(proxy0,proxy1))
+ {
+ m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
+ }
+ }
}
}
+ }
+
+ if (m_ownsPairCache && m_pairCache->hasDeferredRemoval())
+ {
+
+ btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+
+
+ btBroadphasePair previousPair;
+ previousPair.m_pProxy0 = 0;
+ previousPair.m_pProxy1 = 0;
+ previousPair.m_algorithm = 0;
+
+
+ for (i=0;iprocessOverlap(pair);
+ } else
+ {
+ needsRemoval = true;
+ }
+ } else
+ {
+ //remove duplicate
+ needsRemoval = true;
+ //should have no algorithm
+ btAssert(!pair.m_algorithm);
+ }
+
+ if (needsRemoval)
+ {
+ m_pairCache->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.quickSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+#endif//CLEAN_INVALID_PAIRS
}
}
-
-
- CheckOverlapCallback checkOverlap;
-
- processAllOverlappingPairs(&checkOverlap);
-
-
}
+bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
+ btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
+ return aabbOverlap(p0,p1);
+}
+
+
+
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
index fb155e7047c..e2ebb825725 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
@@ -24,35 +24,69 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy
{
btVector3 m_min;
btVector3 m_max;
+ int m_nextFree;
+
+// int m_handleId;
+
btSimpleBroadphaseProxy() {};
- btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask)
- :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask),
+ btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy)
+ :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy),
m_min(minpt),m_max(maxpt)
{
(void)shapeType;
}
+
+ SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;}
+ SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;}
+
+
+
};
-///SimpleBroadphase is a brute force aabb culling broadphase based on O(n^2) aabb checks
-class btSimpleBroadphase : public btOverlappingPairCache
+///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead.
+///It is a brute force aabb culling broadphase based on O(n^2) aabb checks
+class btSimpleBroadphase : public btBroadphaseInterface
{
protected:
- btSimpleBroadphaseProxy* m_proxies;
- int* m_freeProxies;
- int m_firstFreeProxy;
-
- btSimpleBroadphaseProxy** m_pProxies;
- int m_numProxies;
-
+ int m_numHandles; // number of active handles
+ int m_maxHandles; // max number of handles
+ btSimpleBroadphaseProxy* m_pHandles; // handles pool
+
+ void* m_pHandlesRawPtr;
+ int m_firstFreeHandle; // free handles list
+
+ int allocHandle()
+ {
+ btAssert(m_numHandles < m_maxHandles);
+ int freeHandle = m_firstFreeHandle;
+ m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree();
+ m_numHandles++;
+ return freeHandle;
+ }
+
+ void freeHandle(btSimpleBroadphaseProxy* proxy)
+ {
+ int handle = int(proxy-m_pHandles);
+ btAssert(handle >= 0 && handle < m_maxHandles);
+
+ proxy->SetNextFree(m_firstFreeHandle);
+ m_firstFreeHandle = handle;
+
+ m_numHandles--;
+ }
+
+ btOverlappingPairCache* m_pairCache;
+ bool m_ownsPairCache;
+
+ int m_invalidPair;
- int m_maxProxies;
inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
@@ -67,26 +101,48 @@ protected:
protected:
- virtual void refreshOverlappingPairs();
+
+
public:
- btSimpleBroadphase(int maxProxies=16384);
+ btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0);
virtual ~btSimpleBroadphase();
static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1);
- virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask);
+ 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 calculateOverlappingPairs(btDispatcher* dispatcher);
- virtual void destroyProxy(btBroadphaseProxy* proxy);
- virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax);
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
-
-
+ btOverlappingPairCache* getOverlappingPairCache()
+ {
+ return m_pairCache;
+ }
+ const btOverlappingPairCache* getOverlappingPairCache() const
+ {
+ return m_pairCache;
+ }
+
+ bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+ ///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(-1e30f,-1e30f,-1e30f);
+ aabbMax.setValue(1e30f,1e30f,1e30f);
+ }
+ virtual void printStats()
+ {
+// printf("btSimpleBroadphase.h\n");
+// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+ }
};
diff --git a/extern/bullet2/src/BulletCollision/CMakeLists.txt b/extern/bullet2/src/BulletCollision/CMakeLists.txt
index e565bf7edea..d77ca6444c7 100644
--- a/extern/bullet2/src/BulletCollision/CMakeLists.txt
+++ b/extern/bullet2/src/BulletCollision/CMakeLists.txt
@@ -5,56 +5,149 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src }
ADD_LIBRARY(LibBulletCollision
BroadphaseCollision/btAxisSweep3.cpp
+ BroadphaseCollision/btAxisSweep3.h
BroadphaseCollision/btBroadphaseProxy.cpp
+ BroadphaseCollision/btBroadphaseProxy.h
BroadphaseCollision/btCollisionAlgorithm.cpp
+ BroadphaseCollision/btCollisionAlgorithm.h
BroadphaseCollision/btDispatcher.cpp
+ BroadphaseCollision/btDispatcher.h
+ BroadphaseCollision/btDbvtBroadphase.cpp
+ BroadphaseCollision/btDbvtBroadphase.h
+ BroadphaseCollision/btDbvt.cpp
+ BroadphaseCollision/btDbvt.h
+ BroadphaseCollision/btMultiSapBroadphase.cpp
+ BroadphaseCollision/btMultiSapBroadphase.h
BroadphaseCollision/btOverlappingPairCache.cpp
+ BroadphaseCollision/btOverlappingPairCache.h
+ BroadphaseCollision/btOverlappingPairCallback.h
+ BroadphaseCollision/btQuantizedBvh.cpp
+ BroadphaseCollision/btQuantizedBvh.h
BroadphaseCollision/btSimpleBroadphase.cpp
+ BroadphaseCollision/btSimpleBroadphase.h
CollisionDispatch/btCollisionDispatcher.cpp
+ CollisionDispatch/btCollisionDispatcher.h
CollisionDispatch/btCollisionObject.cpp
+ CollisionDispatch/btCollisionObject.h
CollisionDispatch/btCollisionWorld.cpp
+ CollisionDispatch/btCollisionWorld.h
CollisionDispatch/btCompoundCollisionAlgorithm.cpp
+ CollisionDispatch/btCompoundCollisionAlgorithm.h
CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
+ CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
+ CollisionDispatch/btDefaultCollisionConfiguration.cpp
+ CollisionDispatch/btDefaultCollisionConfiguration.h
CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
+ CollisionDispatch/btSphereSphereCollisionAlgorithm.h
+ CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
+ CollisionDispatch/btBoxBoxCollisionAlgorithm.h
+ CollisionDispatch/btBoxBoxDetector.cpp
+ CollisionDispatch/btBoxBoxDetector.h
CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
+ CollisionDispatch/btSphereBoxCollisionAlgorithm.h
+ CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
+ CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
+ CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
+ CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
CollisionDispatch/btConvexConvexAlgorithm.cpp
+ CollisionDispatch/btConvexConvexAlgorithm.h
CollisionDispatch/btEmptyCollisionAlgorithm.cpp
+ CollisionDispatch/btEmptyCollisionAlgorithm.h
CollisionDispatch/btManifoldResult.cpp
+ CollisionDispatch/btManifoldResult.h
CollisionDispatch/btSimulationIslandManager.cpp
+ CollisionDispatch/btSimulationIslandManager.h
CollisionDispatch/btUnionFind.cpp
+ CollisionDispatch/btUnionFind.h
+ CollisionDispatch/SphereTriangleDetector.cpp
+ CollisionDispatch/SphereTriangleDetector.h
CollisionShapes/btBoxShape.cpp
+ CollisionShapes/btBoxShape.h
CollisionShapes/btBvhTriangleMeshShape.cpp
+ CollisionShapes/btBvhTriangleMeshShape.h
+ CollisionShapes/btCapsuleShape.cpp
+ CollisionShapes/btCapsuleShape.h
CollisionShapes/btCollisionShape.cpp
+ CollisionShapes/btCollisionShape.h
CollisionShapes/btCompoundShape.cpp
+ CollisionShapes/btCompoundShape.h
CollisionShapes/btConcaveShape.cpp
+ CollisionShapes/btConcaveShape.h
CollisionShapes/btConeShape.cpp
+ CollisionShapes/btConeShape.h
CollisionShapes/btConvexHullShape.cpp
+ CollisionShapes/btConvexHullShape.h
CollisionShapes/btConvexShape.cpp
+ CollisionShapes/btConvexShape.h
+ CollisionShapes/btConvexInternalShape.cpp
+ CollisionShapes/btConvexInternalShape.h
CollisionShapes/btConvexTriangleMeshShape.cpp
+ CollisionShapes/btConvexTriangleMeshShape.h
CollisionShapes/btCylinderShape.cpp
+ CollisionShapes/btCylinderShape.h
CollisionShapes/btEmptyShape.cpp
+ CollisionShapes/btEmptyShape.h
+ CollisionShapes/btHeightfieldTerrainShape.cpp
+ CollisionShapes/btHeightfieldTerrainShape.h
CollisionShapes/btMinkowskiSumShape.cpp
+ CollisionShapes/btMinkowskiSumShape.h
+ CollisionShapes/btMaterial.h
+ CollisionShapes/btMultimaterialTriangleMeshShape.cpp
+ CollisionShapes/btMultimaterialTriangleMeshShape.h
CollisionShapes/btMultiSphereShape.cpp
+ CollisionShapes/btMultiSphereShape.h
CollisionShapes/btOptimizedBvh.cpp
+ CollisionShapes/btOptimizedBvh.h
CollisionShapes/btPolyhedralConvexShape.cpp
+ CollisionShapes/btPolyhedralConvexShape.h
+ CollisionShapes/btScaledBvhTriangleMeshShape.cpp
+ CollisionShapes/btScaledBvhTriangleMeshShape.h
CollisionShapes/btTetrahedronShape.cpp
+ CollisionShapes/btTetrahedronShape.h
CollisionShapes/btSphereShape.cpp
+ CollisionShapes/btSphereShape.h
+ CollisionShapes/btShapeHull.h
+ CollisionShapes/btShapeHull.cpp
CollisionShapes/btStaticPlaneShape.cpp
+ CollisionShapes/btStaticPlaneShape.h
CollisionShapes/btStridingMeshInterface.cpp
+ CollisionShapes/btStridingMeshInterface.h
CollisionShapes/btTriangleCallback.cpp
+ CollisionShapes/btTriangleCallback.h
CollisionShapes/btTriangleBuffer.cpp
+ CollisionShapes/btTriangleBuffer.h
CollisionShapes/btTriangleIndexVertexArray.cpp
+ CollisionShapes/btTriangleIndexVertexArray.h
+ CollisionShapes/btTriangleIndexVertexMaterialArray.h
+ CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
CollisionShapes/btTriangleMesh.cpp
+ CollisionShapes/btTriangleMesh.h
CollisionShapes/btTriangleMeshShape.cpp
+ CollisionShapes/btTriangleMeshShape.h
+ CollisionShapes/btUniformScalingShape.cpp
+ CollisionShapes/btUniformScalingShape.h
NarrowPhaseCollision/btContinuousConvexCollision.cpp
+ NarrowPhaseCollision/btContinuousConvexCollision.h
NarrowPhaseCollision/btGjkEpa.cpp
+ NarrowPhaseCollision/btGjkEpa.h
+ NarrowPhaseCollision/btGjkEpa2.cpp
+ NarrowPhaseCollision/btGjkEpa2.h
NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
+ NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
NarrowPhaseCollision/btConvexCast.cpp
+ NarrowPhaseCollision/btConvexCast.h
NarrowPhaseCollision/btGjkConvexCast.cpp
+ NarrowPhaseCollision/btGjkConvexCast.h
NarrowPhaseCollision/btGjkPairDetector.cpp
+ NarrowPhaseCollision/btGjkPairDetector.h
NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
+ NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
NarrowPhaseCollision/btPersistentManifold.cpp
+ NarrowPhaseCollision/btPersistentManifold.h
NarrowPhaseCollision/btRaycastCallback.cpp
+ NarrowPhaseCollision/btRaycastCallback.h
NarrowPhaseCollision/btSubSimplexConvexCast.cpp
+ NarrowPhaseCollision/btSubSimplexConvexCast.h
NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
+ NarrowPhaseCollision/btVoronoiSimplexSolver.h
)
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
index 81133670f0c..f6c1e32ac7c 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
@@ -26,7 +26,7 @@ m_triangle(triangle)
}
-void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
+void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
{
(void)debugDraw;
@@ -42,7 +42,16 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res
if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact))
{
- output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
+ if (swapResults)
+ {
+ btVector3 normalOnB = transformB.getBasis()*normal;
+ btVector3 normalOnA = -normalOnB;
+ btVector3 pointOnA = transformB*point+normalOnB*depth;
+ output.addContactPoint(normalOnA,pointOnA,depth);
+ } else
+ {
+ output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
+ }
}
}
@@ -53,6 +62,8 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res
// See also geometrictools.com
// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv
+btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest);
+
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) {
btVector3 diff = p - from;
btVector3 v = to - from;
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
index b32806a6846..26dabaa480e 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
@@ -16,8 +16,8 @@ subject to the following restrictions:
#ifndef SPHERE_TRIANGLE_DETECTOR_H
#define SPHERE_TRIANGLE_DETECTOR_H
-#include "../NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
-#include "../../LinearMath/btPoint3.h"
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "LinearMath/btPoint3.h"
class btSphereShape;
@@ -28,7 +28,7 @@ class btTriangleShape;
/// sphere-triangle to match the btDiscreteCollisionDetectorInterface
struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface
{
- virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw);
+ virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle);
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
new file mode 100644
index 00000000000..cd0c028012c
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
@@ -0,0 +1,85 @@
+/*
+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 "btBoxBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "btBoxBoxDetector.h"
+
+#define USE_PERSISTENT_CONTACTS 1
+
+btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
+: btCollisionAlgorithm(ci),
+m_ownManifold(false),
+m_manifoldPtr(mf)
+{
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
+ {
+ m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
+ m_ownManifold = true;
+ }
+}
+
+btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
+{
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+}
+
+void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ if (!m_manifoldPtr)
+ return;
+
+ btCollisionObject* col0 = body0;
+ btCollisionObject* col1 = body1;
+ btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape();
+ btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape();
+
+
+
+ /// report a contact. internally this will be kept persistent, and contact reduction is done
+ resultOut->setPersistentManifold(m_manifoldPtr);
+#ifndef USE_PERSISTENT_CONTACTS
+ m_manifoldPtr->clearManifold();
+#endif //USE_PERSISTENT_CONTACTS
+
+ btDiscreteCollisionDetectorInterface::ClosestPointInput input;
+ input.m_maximumDistanceSquared = 1e30f;
+ input.m_transformA = body0->getWorldTransform();
+ input.m_transformB = body1->getWorldTransform();
+
+ btBoxBoxDetector detector(box0,box1);
+ detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+
+#ifdef USE_PERSISTENT_CONTACTS
+ // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
+ if (m_ownManifold)
+ {
+ resultOut->refreshContactPoints();
+ }
+#endif //USE_PERSISTENT_CONTACTS
+
+}
+
+btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+ //not yet
+ return 1.f;
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
new file mode 100644
index 00000000000..35afaf175a1
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
@@ -0,0 +1,66 @@
+/*
+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 BOX_BOX__COLLISION_ALGORITHM_H
+#define BOX_BOX__COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+
+class btPersistentManifold;
+
+///box-box collision detection
+class btBoxBoxCollisionAlgorithm : public btCollisionAlgorithm
+{
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+
+public:
+ btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+ : btCollisionAlgorithm(ci) {}
+
+ virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+
+ virtual ~btBoxBoxCollisionAlgorithm();
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ {
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ }
+
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ {
+ int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
+ void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+ return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1);
+ }
+ };
+
+};
+
+#endif //BOX_BOX__COLLISION_ALGORITHM_H
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
new file mode 100644
index 00000000000..45ebff5dc45
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
@@ -0,0 +1,683 @@
+
+/*
+ * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
+ * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
+ * All rights reserved. Email: russ@q12.org Web: www.q12.org
+ Bullet Continuous Collision Detection and Physics Library
+ Bullet is 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.
+*/
+
+///ODE box-box collision detection is adapted to work with Bullet
+
+#include "btBoxBoxDetector.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+
+#include
+#include
+
+btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2)
+: m_box1(box1),
+m_box2(box2)
+{
+
+}
+
+
+// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and
+// generate contact points. this returns 0 if there is no contact otherwise
+// it returns the number of contacts generated.
+// `normal' returns the contact normal.
+// `depth' returns the maximum penetration depth along that normal.
+// `return_code' returns a number indicating the type of contact that was
+// detected:
+// 1,2,3 = box 2 intersects with a face of box 1
+// 4,5,6 = box 1 intersects with a face of box 2
+// 7..15 = edge-edge contact
+// `maxc' is the maximum number of contacts allowed to be generated, i.e.
+// the size of the `contact' array.
+// `contact' and `skip' are the contact array information provided to the
+// collision functions. this function only fills in the position and depth
+// fields.
+struct dContactGeom;
+#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
+#define dInfinity FLT_MAX
+
+
+/*PURE_INLINE btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
+PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); }
+PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); }
+PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); }
+*/
+static btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
+static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); }
+static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); }
+static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); }
+#define dMULTIPLYOP1_331(A,op,B,C) \
+{\
+ (A)[0] op dDOT41((B),(C)); \
+ (A)[1] op dDOT41((B+1),(C)); \
+ (A)[2] op dDOT41((B+2),(C)); \
+}
+
+#define dMULTIPLYOP0_331(A,op,B,C) \
+{ \
+ (A)[0] op dDOT((B),(C)); \
+ (A)[1] op dDOT((B+4),(C)); \
+ (A)[2] op dDOT((B+8),(C)); \
+}
+
+#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
+#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
+
+typedef btScalar dMatrix3[4*3];
+
+void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
+ const btVector3& pb, const btVector3& ub,
+ btScalar *alpha, btScalar *beta);
+void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
+ const btVector3& pb, const btVector3& ub,
+ btScalar *alpha, btScalar *beta)
+{
+ btVector3 p;
+ p[0] = pb[0] - pa[0];
+ p[1] = pb[1] - pa[1];
+ p[2] = pb[2] - pa[2];
+ btScalar uaub = dDOT(ua,ub);
+ btScalar q1 = dDOT(ua,p);
+ btScalar q2 = -dDOT(ub,p);
+ btScalar d = 1-uaub*uaub;
+ if (d <= btScalar(0.0001f)) {
+ // @@@ this needs to be made more robust
+ *alpha = 0;
+ *beta = 0;
+ }
+ else {
+ d = 1.f/d;
+ *alpha = (q1 + uaub*q2)*d;
+ *beta = (uaub*q1 + q2)*d;
+ }
+}
+
+
+
+// find all the intersection points between the 2D rectangle with vertices
+// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]),
+// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]).
+//
+// the intersection points are returned as x,y pairs in the 'ret' array.
+// the number of intersection points is returned by the function (this will
+// be in the range 0 to 8).
+
+static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16])
+{
+ // q (and r) contain nq (and nr) coordinate points for the current (and
+ // chopped) polygons
+ int nq=4,nr=0;
+ btScalar buffer[16];
+ btScalar *q = p;
+ btScalar *r = ret;
+ for (int dir=0; dir <= 1; dir++) {
+ // direction notation: xy[0] = x axis, xy[1] = y axis
+ for (int sign=-1; sign <= 1; sign += 2) {
+ // chop q along the line xy[dir] = sign*h[dir]
+ btScalar *pq = q;
+ btScalar *pr = r;
+ nr = 0;
+ for (int i=nq; i > 0; i--) {
+ // go through all points in q and all lines between adjacent points
+ if (sign*pq[dir] < h[dir]) {
+ // this point is inside the chopping line
+ pr[0] = pq[0];
+ pr[1] = pq[1];
+ pr += 2;
+ nr++;
+ if (nr & 8) {
+ q = r;
+ goto done;
+ }
+ }
+ btScalar *nextq = (i > 1) ? pq+2 : q;
+ if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) {
+ // this line crosses the chopping line
+ pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) /
+ (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]);
+ pr[dir] = sign*h[dir];
+ pr += 2;
+ nr++;
+ if (nr & 8) {
+ q = r;
+ goto done;
+ }
+ }
+ pq += 2;
+ }
+ q = r;
+ r = (q==ret) ? buffer : ret;
+ nq = nr;
+ }
+ }
+ done:
+ if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar));
+ return nr;
+}
+
+
+#define M__PI 3.14159265f
+
+// given n points in the plane (array p, of size 2*n), generate m points that
+// best represent the whole set. the definition of 'best' here is not
+// predetermined - the idea is to select points that give good box-box
+// collision detection behavior. the chosen point indexes are returned in the
+// array iret (of size m). 'i0' is always the first entry in the array.
+// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be
+// in the range [0..n-1].
+
+void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]);
+void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[])
+{
+ // compute the centroid of the polygon in cx,cy
+ int i,j;
+ btScalar a,cx,cy,q;
+ if (n==1) {
+ cx = p[0];
+ cy = p[1];
+ }
+ else if (n==2) {
+ cx = btScalar(0.5)*(p[0] + p[2]);
+ cy = btScalar(0.5)*(p[1] + p[3]);
+ }
+ else {
+ a = 0;
+ cx = 0;
+ cy = 0;
+ for (i=0; i<(n-1); i++) {
+ q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1];
+ a += q;
+ cx += q*(p[i*2]+p[i*2+2]);
+ cy += q*(p[i*2+1]+p[i*2+3]);
+ }
+ q = p[n*2-2]*p[1] - p[0]*p[n*2-1];
+ a = 1.f/(btScalar(3.0)*(a+q));
+ cx = a*(cx + q*(p[n*2-2]+p[0]));
+ cy = a*(cy + q*(p[n*2-1]+p[1]));
+ }
+
+ // compute the angle of each point w.r.t. the centroid
+ btScalar A[8];
+ for (i=0; i M__PI) a -= 2*M__PI;
+ btScalar maxdiff=1e9,diff;
+#if defined(DEBUG) || defined (_DEBUG)
+ *iret = i0; // iret is not allowed to keep this value
+#endif
+ for (i=0; i M__PI) diff = 2*M__PI - diff;
+ if (diff < maxdiff) {
+ maxdiff = diff;
+ *iret = i;
+ }
+ }
+ }
+#if defined(DEBUG) || defined (_DEBUG)
+ btAssert (*iret != i0); // ensure iret got set
+#endif
+ avail[*iret] = 0;
+ iret++;
+ }
+}
+
+
+
+int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
+ const btVector3& side1, const btVector3& p2,
+ const dMatrix3 R2, const btVector3& side2,
+ btVector3& normal, btScalar *depth, int *return_code,
+ int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output);
+int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
+ const btVector3& side1, const btVector3& p2,
+ const dMatrix3 R2, const btVector3& side2,
+ btVector3& normal, btScalar *depth, int *return_code,
+ int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output)
+{
+ const btScalar fudge_factor = btScalar(1.05);
+ btVector3 p,pp,normalC;
+ const btScalar *normalR = 0;
+ btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33,
+ Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l;
+ int i,j,invert_normal,code;
+
+ // get vector from centers of box 1 to box 2, relative to box 1
+ p = p2 - p1;
+ dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1
+
+ // get side lengths / 2
+ A[0] = side1[0]*btScalar(0.5);
+ A[1] = side1[1]*btScalar(0.5);
+ A[2] = side1[2]*btScalar(0.5);
+ B[0] = side2[0]*btScalar(0.5);
+ B[1] = side2[1]*btScalar(0.5);
+ B[2] = side2[2]*btScalar(0.5);
+
+ // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
+ R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
+ R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
+ R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
+
+ Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13);
+ Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23);
+ Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33);
+
+ // for all 15 possible separating axes:
+ // * see if the axis separates the boxes. if so, return 0.
+ // * find the depth of the penetration along the separating axis (s2)
+ // * if this is the largest depth so far, record it.
+ // the normal vector will be set to the separating axis with the smallest
+ // depth. note: normalR is set to point to a column of R1 or R2 if that is
+ // the smallest depth normal so far. otherwise normalR is 0 and normalC is
+ // set to a vector relative to body 1. invert_normal is 1 if the sign of
+ // the normal should be flipped.
+
+#define TST(expr1,expr2,norm,cc) \
+ s2 = btFabs(expr1) - (expr2); \
+ if (s2 > 0) return 0; \
+ if (s2 > s) { \
+ s = s2; \
+ normalR = norm; \
+ invert_normal = ((expr1) < 0); \
+ code = (cc); \
+ }
+
+ s = -dInfinity;
+ invert_normal = 0;
+ code = 0;
+
+ // separating axis = u1,u2,u3
+ TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1);
+ TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2);
+ TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3);
+
+ // separating axis = v1,v2,v3
+ TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4);
+ TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5);
+ TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6);
+
+ // note: cross product axes need to be scaled when s is computed.
+ // normal (n1,n2,n3) is relative to box 1.
+#undef TST
+#define TST(expr1,expr2,n1,n2,n3,cc) \
+ s2 = btFabs(expr1) - (expr2); \
+ if (s2 > 0) return 0; \
+ l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \
+ if (l > 0) { \
+ s2 /= l; \
+ if (s2*fudge_factor > s) { \
+ s = s2; \
+ normalR = 0; \
+ normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \
+ invert_normal = ((expr1) < 0); \
+ code = (cc); \
+ } \
+ }
+
+ // separating axis = u1 x (v1,v2,v3)
+ TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7);
+ TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8);
+ TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9);
+
+ // separating axis = u2 x (v1,v2,v3)
+ TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10);
+ TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11);
+ TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12);
+
+ // separating axis = u3 x (v1,v2,v3)
+ TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13);
+ TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14);
+ TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15);
+
+#undef TST
+
+ if (!code) return 0;
+
+ // if we get to this point, the boxes interpenetrate. compute the normal
+ // in global coordinates.
+ if (normalR) {
+ normal[0] = normalR[0];
+ normal[1] = normalR[4];
+ normal[2] = normalR[8];
+ }
+ else {
+ dMULTIPLY0_331 (normal,R1,normalC);
+ }
+ if (invert_normal) {
+ normal[0] = -normal[0];
+ normal[1] = -normal[1];
+ normal[2] = -normal[2];
+ }
+ *depth = -s;
+
+ // compute contact point(s)
+
+ if (code > 6) {
+ // an edge from box 1 touches an edge from box 2.
+ // find a point pa on the intersecting edge of box 1
+ btVector3 pa;
+ btScalar sign;
+ for (i=0; i<3; i++) pa[i] = p1[i];
+ for (j=0; j<3; j++) {
+ sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0);
+ for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j];
+ }
+
+ // find a point pb on the intersecting edge of box 2
+ btVector3 pb;
+ for (i=0; i<3; i++) pb[i] = p2[i];
+ for (j=0; j<3; j++) {
+ sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0);
+ for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j];
+ }
+
+ btScalar alpha,beta;
+ btVector3 ua,ub;
+ for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4];
+ for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4];
+
+ dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta);
+ for (i=0; i<3; i++) pa[i] += ua[i]*alpha;
+ for (i=0; i<3; i++) pb[i] += ub[i]*beta;
+
+ {
+
+ //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]);
+ //contact[0].depth = *depth;
+ btVector3 pointInWorld;
+
+#ifdef USE_CENTER_POINT
+ for (i=0; i<3; i++)
+ pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5);
+ output.addContactPoint(-normal,pointInWorld,-*depth);
+#else
+ output.addContactPoint(-normal,pb,-*depth);
+#endif //
+ *return_code = code;
+ }
+ return 1;
+ }
+
+ // okay, we have a face-something intersection (because the separating
+ // axis is perpendicular to a face). define face 'a' to be the reference
+ // face (i.e. the normal vector is perpendicular to this) and face 'b' to be
+ // the incident face (the closest face of the other box).
+
+ const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb;
+ if (code <= 3) {
+ Ra = R1;
+ Rb = R2;
+ pa = p1;
+ pb = p2;
+ Sa = A;
+ Sb = B;
+ }
+ else {
+ Ra = R2;
+ Rb = R1;
+ pa = p2;
+ pb = p1;
+ Sa = B;
+ Sb = A;
+ }
+
+ // nr = normal vector of reference face dotted with axes of incident box.
+ // anr = absolute values of nr.
+ btVector3 normal2,nr,anr;
+ if (code <= 3) {
+ normal2[0] = normal[0];
+ normal2[1] = normal[1];
+ normal2[2] = normal[2];
+ }
+ else {
+ normal2[0] = -normal[0];
+ normal2[1] = -normal[1];
+ normal2[2] = -normal[2];
+ }
+ dMULTIPLY1_331 (nr,Rb,normal2);
+ anr[0] = btFabs (nr[0]);
+ anr[1] = btFabs (nr[1]);
+ anr[2] = btFabs (nr[2]);
+
+ // find the largest compontent of anr: this corresponds to the normal
+ // for the indident face. the other axis numbers of the indicent face
+ // are stored in a1,a2.
+ int lanr,a1,a2;
+ if (anr[1] > anr[0]) {
+ if (anr[1] > anr[2]) {
+ a1 = 0;
+ lanr = 1;
+ a2 = 2;
+ }
+ else {
+ a1 = 0;
+ a2 = 1;
+ lanr = 2;
+ }
+ }
+ else {
+ if (anr[0] > anr[2]) {
+ lanr = 0;
+ a1 = 1;
+ a2 = 2;
+ }
+ else {
+ a1 = 0;
+ a2 = 1;
+ lanr = 2;
+ }
+ }
+
+ // compute center point of incident face, in reference-face coordinates
+ btVector3 center;
+ if (nr[lanr] < 0) {
+ for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr];
+ }
+ else {
+ for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr];
+ }
+
+ // find the normal and non-normal axis numbers of the reference box
+ int codeN,code1,code2;
+ if (code <= 3) codeN = code-1; else codeN = code-4;
+ if (codeN==0) {
+ code1 = 1;
+ code2 = 2;
+ }
+ else if (codeN==1) {
+ code1 = 0;
+ code2 = 2;
+ }
+ else {
+ code1 = 0;
+ code2 = 1;
+ }
+
+ // find the four corners of the incident face, in reference-face coordinates
+ btScalar quad[8]; // 2D coordinate of incident face (x,y pairs)
+ btScalar c1,c2,m11,m12,m21,m22;
+ c1 = dDOT14 (center,Ra+code1);
+ c2 = dDOT14 (center,Ra+code2);
+ // optimize this? - we have already computed this data above, but it is not
+ // stored in an easy-to-index format. for now it's quicker just to recompute
+ // the four dot products.
+ m11 = dDOT44 (Ra+code1,Rb+a1);
+ m12 = dDOT44 (Ra+code1,Rb+a2);
+ m21 = dDOT44 (Ra+code2,Rb+a1);
+ m22 = dDOT44 (Ra+code2,Rb+a2);
+ {
+ btScalar k1 = m11*Sb[a1];
+ btScalar k2 = m21*Sb[a1];
+ btScalar k3 = m12*Sb[a2];
+ btScalar k4 = m22*Sb[a2];
+ quad[0] = c1 - k1 - k3;
+ quad[1] = c2 - k2 - k4;
+ quad[2] = c1 - k1 + k3;
+ quad[3] = c2 - k2 + k4;
+ quad[4] = c1 + k1 + k3;
+ quad[5] = c2 + k2 + k4;
+ quad[6] = c1 + k1 - k3;
+ quad[7] = c2 + k2 - k4;
+ }
+
+ // find the size of the reference face
+ btScalar rect[2];
+ rect[0] = Sa[code1];
+ rect[1] = Sa[code2];
+
+ // intersect the incident and reference faces
+ btScalar ret[16];
+ int n = intersectRectQuad2 (rect,quad,ret);
+ if (n < 1) return 0; // this should never happen
+
+ // convert the intersection points into reference-face coordinates,
+ // and compute the contact position and depth for each point. only keep
+ // those points that have a positive (penetrating) depth. delete points in
+ // the 'ret' array as necessary so that 'point' and 'ret' correspond.
+ btScalar point[3*8]; // penetrating contact points
+ btScalar dep[8]; // depths for those points
+ btScalar det1 = 1.f/(m11*m22 - m12*m21);
+ m11 *= det1;
+ m12 *= det1;
+ m21 *= det1;
+ m22 *= det1;
+ int cnum = 0; // number of penetrating contact points found
+ for (j=0; j < n; j++) {
+ btScalar k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
+ btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
+ for (i=0; i<3; i++) point[cnum*3+i] =
+ center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2];
+ dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3);
+ if (dep[cnum] >= 0) {
+ ret[cnum*2] = ret[j*2];
+ ret[cnum*2+1] = ret[j*2+1];
+ cnum++;
+ }
+ }
+ if (cnum < 1) return 0; // this should never happen
+
+ // we can't generate more contacts than we actually have
+ if (maxc > cnum) maxc = cnum;
+ if (maxc < 1) maxc = 1;
+
+ if (cnum <= maxc) {
+ // we have less contacts than we need, so we use them all
+ for (j=0; j < cnum; j++) {
+
+ //AddContactPoint...
+
+ //dContactGeom *con = CONTACT(contact,skip*j);
+ //for (i=0; i<3; i++) con->pos[i] = point[j*3+i] + pa[i];
+ //con->depth = dep[j];
+
+ btVector3 pointInWorld;
+ for (i=0; i<3; i++)
+ pointInWorld[i] = point[j*3+i] + pa[i];
+ output.addContactPoint(-normal,pointInWorld,-dep[j]);
+
+ }
+ }
+ else {
+ // we have more contacts than are wanted, some of them must be culled.
+ // find the deepest point, it is always the first contact.
+ int i1 = 0;
+ btScalar maxdepth = dep[0];
+ for (i=1; i maxdepth) {
+ maxdepth = dep[i];
+ i1 = i;
+ }
+ }
+
+ int iret[8];
+ cullPoints2 (cnum,ret,maxc,i1,iret);
+
+ for (j=0; j < maxc; j++) {
+// dContactGeom *con = CONTACT(contact,skip*j);
+ // for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i];
+ // con->depth = dep[iret[j]];
+
+ btVector3 posInWorld;
+ for (i=0; i<3; i++)
+ posInWorld[i] = point[iret[j]*3+i] + pa[i];
+ output.addContactPoint(-normal,posInWorld,-dep[iret[j]]);
+ }
+ cnum = maxc;
+ }
+
+ *return_code = code;
+ return cnum;
+}
+
+void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/)
+{
+
+ const btTransform& transformA = input.m_transformA;
+ const btTransform& transformB = input.m_transformB;
+
+ int skip = 0;
+ dContactGeom *contact = 0;
+
+ dMatrix3 R1;
+ dMatrix3 R2;
+
+ for (int j=0;j<3;j++)
+ {
+ R1[0+4*j] = transformA.getBasis()[j].x();
+ R2[0+4*j] = transformB.getBasis()[j].x();
+
+ R1[1+4*j] = transformA.getBasis()[j].y();
+ R2[1+4*j] = transformB.getBasis()[j].y();
+
+
+ R1[2+4*j] = transformA.getBasis()[j].z();
+ R2[2+4*j] = transformB.getBasis()[j].z();
+
+ }
+
+
+
+ btVector3 normal;
+ btScalar depth;
+ int return_code;
+ int maxc = 4;
+
+
+ dBoxBox2 (transformA.getOrigin(),
+ R1,
+ 2.f*m_box1->getHalfExtentsWithMargin(),
+ transformB.getOrigin(),
+ R2,
+ 2.f*m_box2->getHalfExtentsWithMargin(),
+ normal, &depth, &return_code,
+ maxc, contact, skip,
+ output
+ );
+
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
new file mode 100644
index 00000000000..605294d47bd
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
@@ -0,0 +1,44 @@
+/*
+ * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
+ * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
+ * All rights reserved. Email: russ@q12.org Web: www.q12.org
+
+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 BOX_BOX_DETECTOR_H
+#define BOX_BOX_DETECTOR_H
+
+
+class btBoxShape;
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+
+/// btBoxBoxDetector wraps the ODE box-box collision detector
+/// re-distributed under the Zlib license with permission from Russell L. Smith
+struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
+{
+ btBoxShape* m_box1;
+ btBoxShape* m_box2;
+
+public:
+
+ btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2);
+
+ virtual ~btBoxBoxDetector() {};
+
+ virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+
+};
+
+#endif //BT_BOX_BOX_DETECTOR_H
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
new file mode 100644
index 00000000000..fad770ac26d
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
@@ -0,0 +1,47 @@
+/*
+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_CONFIGURATION
+#define BT_COLLISION_CONFIGURATION
+struct btCollisionAlgorithmCreateFunc;
+
+class btStackAlloc;
+class btPoolAllocator;
+
+///btCollisionConfiguration allows to configure Bullet collision detection
+///stack allocator size, default collision algorithms and persistent manifold pool size
+///todo: describe the meaning
+class btCollisionConfiguration
+{
+
+public:
+
+ virtual ~btCollisionConfiguration()
+ {
+ }
+
+ ///memory pools
+ virtual btPoolAllocator* getPersistentManifoldPool() = 0;
+
+ virtual btPoolAllocator* getCollisionAlgorithmPool() = 0;
+
+ virtual btStackAlloc* getStackAllocator() = 0;
+
+ virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0;
+
+};
+
+#endif //BT_COLLISION_CONFIGURATION
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
index d51a59af7f0..c6728918d16 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef COLLISION_CREATE_FUNC
#define COLLISION_CREATE_FUNC
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btAlignedObjectArray.h"
typedef btAlignedObjectArray btCollisionObjectArray;
class btCollisionAlgorithm;
class btCollisionObject;
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
index b535fac6563..a031a9f9784 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
@@ -19,69 +19,39 @@ subject to the following restrictions:
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.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"
int gNumManifold = 0;
+#ifdef BT_DEBUG
#include
+#endif
-
-btCollisionDispatcher::btCollisionDispatcher(bool noDefaultAlgorithms):
-m_count(0),
-m_useIslands(true),
-m_convexConvexCreateFunc(0),
-m_convexConcaveCreateFunc(0),
-m_swappedConvexConcaveCreateFunc(0),
-m_compoundCreateFunc(0),
-m_swappedCompoundCreateFunc(0),
-m_emptyCreateFunc(0)
-{
- (void)noDefaultAlgorithms;
- int i;
- setNearCallback(defaultNearCallback);
-
- m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc;
- for (i=0;igetCollisionAlgorithmPool();
+
+ m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
for (i=0;igetCollisionAlgorithmCreateFunc(i,j);
assert(m_doubleDispatch[i][j]);
}
}
@@ -89,8 +59,6 @@ btCollisionDispatcher::btCollisionDispatcher ():
};
-#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
-
void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
{
@@ -99,12 +67,6 @@ void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int prox
btCollisionDispatcher::~btCollisionDispatcher()
{
- delete m_convexConvexCreateFunc;
- delete m_convexConcaveCreateFunc;
- delete m_swappedConvexConcaveCreateFunc;
- delete m_compoundCreateFunc;
- delete m_swappedCompoundCreateFunc;
- delete m_emptyCreateFunc;
}
btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1)
@@ -117,7 +79,18 @@ btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1)
btCollisionObject* body0 = (btCollisionObject*)b0;
btCollisionObject* body1 = (btCollisionObject*)b1;
- btPersistentManifold* manifold = new btPersistentManifold (body0,body1);
+ void* mem = 0;
+
+ if (m_persistentManifoldPoolAllocator->getFreeCount())
+ {
+ mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
+ } else
+ {
+ mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
+
+ }
+ btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0);
+ manifold->m_index1a = m_manifoldsPtr.size();
m_manifoldsPtr.push_back(manifold);
return manifold;
@@ -137,13 +110,19 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
//printf("releaseManifold: gNumManifold %d\n",gNumManifold);
clearManifold(manifold);
- ///todo: this can be improved a lot, linear search might be slow part!
- int findIndex = m_manifoldsPtr.findLinearSearch(manifold);
- if (findIndex < m_manifoldsPtr.size())
+ 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_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
- m_manifoldsPtr.pop_back();
- delete manifold;
+ m_persistentManifoldPoolAllocator->freeMemory(manifold);
+ } else
+ {
+ btAlignedFree(manifold);
}
}
@@ -152,99 +131,19 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
{
-
-#ifdef USE_DISPATCH_REGISTRY_ARRAY
btCollisionAlgorithmConstructionInfo ci;
- ci.m_dispatcher = this;
+
+ ci.m_dispatcher1 = this;
ci.m_manifold = sharedManifold;
- btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]
- ->CreateCollisionAlgorithm(ci,body0,body1);
-#else
- btCollisionAlgorithm* algo = internalFindAlgorithm(body0,body1);
-#endif //USE_DISPATCH_REGISTRY_ARRAY
+ btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
+
return algo;
}
-#ifndef BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
-
-btCollisionAlgorithmCreateFunc* btCollisionDispatcher::internalFindCreateFunc(int proxyType0,int proxyType1)
-{
-
- if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
- {
- return m_convexConvexCreateFunc;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
- {
- return m_convexConcaveCreateFunc;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
- {
- return m_swappedConvexConcaveCreateFunc;
- }
-
- if (btBroadphaseProxy::isCompound(proxyType0))
- {
- return m_compoundCreateFunc;
- } else
- {
- if (btBroadphaseProxy::isCompound(proxyType1))
- {
- return m_swappedCompoundCreateFunc;
- }
- }
-
- //failed to find an algorithm
- return m_emptyCreateFunc;
-}
-
-#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
-#ifndef USE_DISPATCH_REGISTRY_ARRAY
-
-btCollisionAlgorithm* btCollisionDispatcher::internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
-{
- m_count++;
-
- btCollisionAlgorithmConstructionInfo ci;
- ci.m_dispatcher = this;
-
- if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConvex() )
- {
- return new btConvexConvexAlgorithm(sharedManifold,ci,body0,body1);
- }
-
- if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConcave())
- {
- return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false);
- }
-
- if (body1->getCollisionShape()->isConvex() && body0->getCollisionShape()->isConcave())
- {
- return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true);
- }
-
- if (body0->getCollisionShape()->isCompound())
- {
- return new btCompoundCollisionAlgorithm(ci,body0,body1,false);
- } else
- {
- if (body1->getCollisionShape()->isCompound())
- {
- return new btCompoundCollisionAlgorithm(ci,body0,body1,true);
- }
- }
-
- //failed to find an algorithm
- return new btEmptyAlgorithm(ci);
-
-}
-#endif //USE_DISPATCH_REGISTRY_ARRAY
bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1)
{
@@ -264,13 +163,19 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO
bool needsCollision = true;
- //broadphase filtering already deals with this
- if ((body0->isStaticObject() || body0->isKinematicObject()) &&
- (body1->isStaticObject() || body1->isKinematicObject()))
+#ifdef BT_DEBUG
+ if (!m_staticWarningReported)
{
- printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
+ //broadphase filtering already deals with this
+ if ((body0->isStaticObject() || body0->isKinematicObject()) &&
+ (body1->isStaticObject() || body1->isKinematicObject()))
+ {
+ m_staticWarningReported = true;
+ printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
+ }
}
-
+#endif //BT_DEBUG
+
if ((!body0->isActive()) && (!body1->isActive()))
needsCollision = false;
else if (!body0->checkCollideWith(body1))
@@ -286,23 +191,25 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO
///this is useful for the collision dispatcher.
class btCollisionPairCallback : public btOverlapCallback
{
- btDispatcherInfo& m_dispatchInfo;
+ const btDispatcherInfo& m_dispatchInfo;
btCollisionDispatcher* m_dispatcher;
public:
- btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
+ btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
:m_dispatchInfo(dispatchInfo),
m_dispatcher(dispatcher)
{
}
- btCollisionPairCallback& operator=(btCollisionPairCallback& other)
+ /*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
{
m_dispatchInfo = other.m_dispatchInfo;
m_dispatcher = other.m_dispatcher;
return *this;
}
+ */
+
virtual ~btCollisionPairCallback() {}
@@ -316,13 +223,14 @@ public:
};
-void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)
+
+void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
{
//m_blockedForChanges = true;
btCollisionPairCallback collisionCallback(dispatchInfo,this);
- pairCache->processAllOverlappingPairs(&collisionCallback);
+ pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
//m_blockedForChanges = false;
@@ -332,7 +240,7 @@ void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pa
//by default, Bullet will use this near callback
-void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo)
+void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
{
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
@@ -365,3 +273,26 @@ void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair,
}
}
+
+
+void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
+{
+ if (m_collisionAlgorithmPoolAllocator->getFreeCount())
+ {
+ return m_collisionAlgorithmPoolAllocator->allocate(size);
+ }
+
+ //warn user for overflow?
+ return btAlignedAlloc(static_cast(size), 16);
+}
+
+void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
+{
+ if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
+ {
+ m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
+ } else
+ {
+ btAlignedFree(ptr);
+ }
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
index ca5aba8f01c..a9c9cd414c1 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
@@ -16,17 +16,18 @@ subject to the following restrictions:
#ifndef COLLISION__DISPATCHER_H
#define COLLISION__DISPATCHER_H
-#include "../BroadphaseCollision/btDispatcher.h"
-#include "../NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-#include "../CollisionDispatch/btManifoldResult.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h"
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btAlignedObjectArray.h"
class btIDebugDraw;
class btOverlappingPairCache;
-
+class btPoolAllocator;
+class btCollisionConfiguration;
#include "btCollisionCreateFunc.h"
@@ -34,7 +35,7 @@ class btOverlappingPairCache;
class btCollisionDispatcher;
///user can override this nearcallback for collision filtering and more finegrained control over collision detection
-typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo);
+typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
@@ -46,26 +47,22 @@ class btCollisionDispatcher : public btDispatcher
btAlignedObjectArray m_manifoldsPtr;
bool m_useIslands;
+
+ bool m_staticWarningReported;
btManifoldResult m_defaultManifoldResult;
btNearCallback m_nearCallback;
+ btPoolAllocator* m_collisionAlgorithmPoolAllocator;
+
+ btPoolAllocator* m_persistentManifoldPoolAllocator;
+
btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
- btCollisionAlgorithmCreateFunc* internalFindCreateFunc(int proxyType0,int proxyType1);
- //default CreationFunctions, filling the m_doubleDispatch table
- btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
- btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
- btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
- btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
- btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
- btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
+ btCollisionConfiguration* m_collisionConfiguration;
-#ifndef USE_DISPATCH_REGISTRY_ARRAY
- btCollisionAlgorithm* internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0);
-#endif //USE_DISPATCH_REGISTRY_ARRAY
public:
@@ -92,11 +89,7 @@ public:
return m_manifoldsPtr[index];
}
- ///the default constructor creates/register default collision algorithms, for convex, compound and concave shape support
- btCollisionDispatcher ();
-
- ///a special constructor that doesn't create/register the default collision algorithms
- btCollisionDispatcher(bool noDefaultAlgorithms);
+ btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration);
virtual ~btCollisionDispatcher();
@@ -114,7 +107,7 @@ public:
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1);
- virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo);
+ virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
void setNearCallback(btNearCallback nearCallback)
{
@@ -127,7 +120,26 @@ public:
}
//by default, Bullet will use this near callback
- static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo);
+ static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
+
+ virtual void* allocateCollisionAlgorithm(int size);
+
+ virtual void freeCollisionAlgorithm(void* ptr);
+
+ btCollisionConfiguration* getCollisionConfiguration()
+ {
+ return m_collisionConfiguration;
+ }
+
+ const btCollisionConfiguration* getCollisionConfiguration() const
+ {
+ return m_collisionConfiguration;
+ }
+
+ void setCollisionConfiguration(btCollisionConfiguration* config)
+ {
+ m_collisionConfiguration = config;
+ }
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp
index d4c0a4e8cb3..eebd0c99fcb 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp
@@ -13,18 +13,25 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
+
#include "btCollisionObject.h"
btCollisionObject::btCollisionObject()
: m_broadphaseHandle(0),
m_collisionShape(0),
- m_collisionFlags(0),
+ m_rootCollisionShape(0),
+ m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
+ m_islandTag1(-1),
+ m_companionId(-1),
m_activationState1(1),
m_deactivationTime(btScalar(0.)),
+ m_friction(btScalar(0.5)),
+ m_restitution(btScalar(0.)),
m_userObjectPointer(0),
+ m_internalType(CO_COLLISION_OBJECT),
m_hitFraction(btScalar(1.)),
m_ccdSweptSphereRadius(btScalar(0.)),
- m_ccdSquareMotionThreshold(btScalar(0.)),
+ m_ccdMotionThreshold(btScalar(0.)),
m_checkCollideWith(false)
{
@@ -55,3 +62,4 @@ void btCollisionObject::activate(bool forceActivation)
}
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h
index 9fb6a67c4a3..7ef3787b3ac 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h
@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef COLLISION_OBJECT_H
#define COLLISION_OBJECT_H
-#include "../../LinearMath/btTransform.h"
+#include "LinearMath/btTransform.h"
//island management, m_activationState1
#define ACTIVE_TAG 1
@@ -27,7 +27,8 @@ subject to the following restrictions:
struct btBroadphaseProxy;
class btCollisionShape;
-#include "../../LinearMath/btMotionState.h"
+#include "LinearMath/btMotionState.h"
+#include "LinearMath/btAlignedAllocator.h"
@@ -50,6 +51,11 @@ protected:
btVector3 m_interpolationAngularVelocity;
btBroadphaseProxy* m_broadphaseHandle;
btCollisionShape* m_collisionShape;
+
+ ///m_rootCollisionShape is temporarily used to store the original collision shape
+ ///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes
+ ///If it is NULL, the m_collisionShape is not temporarily replaced.
+ btCollisionShape* m_rootCollisionShape;
int m_collisionFlags;
@@ -65,8 +71,9 @@ protected:
///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
void* m_userObjectPointer;
- ///m_internalOwner is reserved to point to Bullet's btRigidBody. Don't use this, use m_userObjectPointer instead.
- void* m_internalOwner;
+ ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody etc.
+ ///do not assign your own m_internalType unless you write a new dynamics object class.
+ int m_internalType;
///time of impact calculation
btScalar m_hitFraction;
@@ -74,21 +81,23 @@ protected:
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
btScalar m_ccdSweptSphereRadius;
- /// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold
- btScalar m_ccdSquareMotionThreshold;
+ /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
+ btScalar m_ccdMotionThreshold;
/// If some object should have elaborate collision filtering by sub-classes
bool m_checkCollideWith;
char m_pad[7];
- virtual bool checkCollideWithOverride(btCollisionObject* co)
+ virtual bool checkCollideWithOverride(btCollisionObject* /* co */)
{
return true;
}
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
enum CollisionFlags
{
CF_STATIC_OBJECT= 1,
@@ -97,29 +106,35 @@ public:
CF_CUSTOM_MATERIAL_CALLBACK = 8//this allows per-triangle material (friction/restitution)
};
+ enum CollisionObjectTypes
+ {
+ CO_COLLISION_OBJECT =1,
+ CO_RIGID_BODY,
+ CO_SOFT_BODY
+ };
- inline bool mergesSimulationIslands() const
+ SIMD_FORCE_INLINE bool mergesSimulationIslands() const
{
///static objects, kinematic and object without contact response don't merge islands
return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0);
}
- inline bool isStaticObject() const {
+ SIMD_FORCE_INLINE bool isStaticObject() const {
return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
}
- inline bool isKinematicObject() const
+ SIMD_FORCE_INLINE bool isKinematicObject() const
{
return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
}
- inline bool isStaticOrKinematicObject() const
+ SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const
{
return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ;
}
- inline bool hasContactResponse() const {
+ SIMD_FORCE_INLINE bool hasContactResponse() const {
return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0;
}
@@ -131,20 +146,35 @@ public:
void setCollisionShape(btCollisionShape* collisionShape)
{
m_collisionShape = collisionShape;
+ m_rootCollisionShape = collisionShape;
}
- const btCollisionShape* getCollisionShape() const
+ SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
{
return m_collisionShape;
}
- btCollisionShape* getCollisionShape()
+ SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
{
return m_collisionShape;
}
-
+ SIMD_FORCE_INLINE const btCollisionShape* getRootCollisionShape() const
+ {
+ return m_rootCollisionShape;
+ }
+ SIMD_FORCE_INLINE btCollisionShape* getRootCollisionShape()
+ {
+ return m_rootCollisionShape;
+ }
+
+ ///Avoid using this internal API call
+ ///internalSetTemporaryCollisionShape is used to temporary replace the actual collision shape by a child collision shape.
+ void internalSetTemporaryCollisionShape(btCollisionShape* collisionShape)
+ {
+ m_collisionShape = collisionShape;
+ }
int getActivationState() const { return m_activationState1;}
@@ -186,14 +216,9 @@ public:
}
///reserved for Bullet internal usage
- void* getInternalOwner()
+ int getInternalType() const
{
- return m_internalOwner;
- }
-
- const void* getInternalOwner() const
- {
- return m_internalOwner;
+ return m_internalType;
}
btTransform& getWorldTransform()
@@ -243,6 +268,15 @@ public:
m_interpolationWorldTransform = trans;
}
+ void setInterpolationLinearVelocity(const btVector3& linvel)
+ {
+ m_interpolationLinearVelocity = linvel;
+ }
+
+ void setInterpolationAngularVelocity(const btVector3& angvel)
+ {
+ m_interpolationAngularVelocity = angvel;
+ }
const btVector3& getInterpolationLinearVelocity() const
{
@@ -307,16 +341,22 @@ public:
m_ccdSweptSphereRadius = radius;
}
+ btScalar getCcdMotionThreshold() const
+ {
+ return m_ccdMotionThreshold;
+ }
+
btScalar getCcdSquareMotionThreshold() const
{
- return m_ccdSquareMotionThreshold;
+ return m_ccdMotionThreshold*m_ccdMotionThreshold;
}
- /// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold
- void setCcdSquareMotionThreshold(btScalar ccdSquareMotionThreshold)
+
+ /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
+ void setCcdMotionThreshold(btScalar ccdMotionThreshold)
{
- m_ccdSquareMotionThreshold = ccdSquareMotionThreshold;
+ m_ccdMotionThreshold = ccdMotionThreshold*ccdMotionThreshold;
}
///users can point to their objects, userPointer is not used by Bullet
@@ -331,6 +371,7 @@ public:
m_userObjectPointer = userPointer;
}
+
inline bool checkCollideWith(btCollisionObject* co)
{
if (m_checkCollideWith)
@@ -338,9 +379,6 @@ public:
return true;
}
-
-
-}
-;
+};
#endif //COLLISION_OBJECT_H
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
index 7dc7d8d2f68..d8674a320a7 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
@@ -4,8 +4,8 @@ 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,
+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.
@@ -18,59 +18,57 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
-
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
-#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" //for raycasting
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting
#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "LinearMath/btAabbUtil2.h"
#include "LinearMath/btQuickprof.h"
#include "LinearMath/btStackAlloc.h"
+
//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
-btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize)
+btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
:m_dispatcher1(dispatcher),
m_broadphasePairCache(pairCache),
-m_ownsDispatcher(false),
-m_ownsBroadphasePairCache(false)
+m_debugDrawer(0)
{
- m_stackAlloc = new btStackAlloc(stackSize);
+ m_stackAlloc = collisionConfiguration->getStackAllocator();
m_dispatchInfo.m_stackAllocator = m_stackAlloc;
}
btCollisionWorld::~btCollisionWorld()
{
- m_stackAlloc->destroy();
- delete m_stackAlloc;
//clean up remaining objects
int i;
for (i=0;igetBroadphaseHandle();
if (bp)
{
//
// only clear the cached algorithms
//
- getBroadphase()->cleanProxyFromPairs(bp);
- getBroadphase()->destroyProxy(bp);
+ getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
+ getBroadphase()->destroyProxy(bp,m_dispatcher1);
}
}
- if (m_ownsDispatcher)
- delete m_dispatcher1;
- if (m_ownsBroadphasePairCache)
- delete m_broadphasePairCache;
}
@@ -105,66 +103,105 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho
type,
collisionObject,
collisionFilterGroup,
- collisionFilterMask
+ collisionFilterMask,
+ m_dispatcher1,0
)) ;
-
+
}
+void btCollisionWorld::updateAabbs()
+{
+ BT_PROFILE("updateAabbs");
+
+ btTransform predictedTrans;
+ for ( int i=0;iisActive())
+ {
+ btPoint3 minAabb,maxAabb;
+ colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+ //need to increase the aabb for contact thresholds
+ btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
+ minAabb -= contactThreshold;
+ maxAabb += contactThreshold;
+
+ btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
+
+ //moving objects should be moderately sized, probably something wrong if not
+ if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12)))
+ {
+ bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
+ } else
+ {
+ //something went wrong, investigate
+ //this assert is unwanted in 3D modelers (danger of loosing work)
+ colObj->setActivationState(DISABLE_SIMULATION);
+
+ static bool reportMe = true;
+ if (reportMe && m_debugDrawer)
+ {
+ reportMe = false;
+ m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
+ m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n");
+ m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
+ m_debugDrawer->reportErrorWarning("Thanks.\n");
+ }
+ }
+ }
+ }
+
+}
void btCollisionWorld::performDiscreteCollisionDetection()
{
+ BT_PROFILE("performDiscreteCollisionDetection");
+
btDispatcherInfo& dispatchInfo = getDispatchInfo();
- BEGIN_PROFILE("perform Broadphase Collision Detection");
+ updateAabbs();
-
- //update aabb (of all moved objects)
-
- btVector3 aabbMin,aabbMax;
- for (int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax);
- m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax);
+ BT_PROFILE("calculateOverlappingPairs");
+ m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
}
- m_broadphasePairCache->refreshOverlappingPairs();
-
-
- END_PROFILE("perform Broadphase Collision Detection");
-
- BEGIN_PROFILE("performDiscreteCollisionDetection");
btDispatcher* dispatcher = getDispatcher();
- if (dispatcher)
- dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache,dispatchInfo);
-
- END_PROFILE("performDiscreteCollisionDetection");
+ {
+ BT_PROFILE("dispatchAllCollisionPairs");
+ if (dispatcher)
+ dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
+ }
}
+
void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
{
-
-
+
+
//bool removeFromBroadphase = false;
-
+
{
-
+
btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
if (bp)
{
//
// only clear the cached algorithms
//
- getBroadphase()->cleanProxyFromPairs(bp);
- getBroadphase()->destroyProxy(bp);
+ getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
+ getBroadphase()->destroyProxy(bp,m_dispatcher1);
collisionObject->setBroadphaseHandle(0);
}
}
@@ -181,192 +218,466 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback,
- short int collisionFilterMask,
- bool faceNormal)
+ RayResultCallback& resultCallback)
{
-
btSphereShape pointShape(btScalar(0.0));
pointShape.setMargin(0.f);
+ const btConvexShape* castShape = &pointShape;
- objectQuerySingle(&pointShape,rayFromTrans,rayToTrans,
- collisionObject,
- collisionShape,
- colObjWorldTransform,
- resultCallback,collisionFilterMask,faceNormal);
+ if (collisionShape->isConvex())
+ {
+ btConvexCast::CastResult castResult;
+ castResult.m_fraction = resultCallback.m_closestHitFraction;
+
+ btConvexShape* convexShape = (btConvexShape*) collisionShape;
+ btVoronoiSimplexSolver simplexSolver;
+#define USE_SUBSIMPLEX_CONVEX_CAST 1
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+ btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
+#else
+ //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
+ //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
+#endif //#USE_SUBSIMPLEX_CONVEX_CAST
+
+ if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+ {
+ //add hit
+ if (castResult.m_normal.length2() > btScalar(0.0001))
+ {
+ if (castResult.m_fraction < resultCallback.m_closestHitFraction)
+ {
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+ //rotate normal into worldspace
+ castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
+#endif //USE_SUBSIMPLEX_CONVEX_CAST
+
+ castResult.m_normal.normalize();
+ btCollisionWorld::LocalRayResult localRayResult
+ (
+ collisionObject,
+ 0,
+ castResult.m_normal,
+ castResult.m_fraction
+ );
+
+ bool normalInWorldSpace = true;
+ resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
+
+ }
+ }
+ }
+ } else {
+ if (collisionShape->isConcave())
+ {
+ if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ {
+ ///optimized version for btBvhTriangleMeshShape
+ btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
+ btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+ btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
+ btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
+
+ //ConvexCast::CastResult
+ struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
+ {
+ btCollisionWorld::RayResultCallback* m_resultCallback;
+ btCollisionObject* m_collisionObject;
+ btTriangleMeshShape* m_triangleMesh;
+
+ BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
+ btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
+ btTriangleRaycastCallback(from,to),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh)
+ {
+ }
+
+
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
+ {
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = partId;
+ shapeInfo.m_triangleIndex = triangleIndex;
+
+ btCollisionWorld::LocalRayResult rayResult
+ (m_collisionObject,
+ &shapeInfo,
+ hitNormalLocal,
+ hitFraction);
+
+ bool normalInWorldSpace = false;
+ return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
+ }
+
+ };
+
+ BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh);
+ rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+ triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal);
+ } else
+ {
+ btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape;
+
+ btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+
+ btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
+ btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
+
+ //ConvexCast::CastResult
+
+ struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
+ {
+ btCollisionWorld::RayResultCallback* m_resultCallback;
+ btCollisionObject* m_collisionObject;
+ btTriangleMeshShape* m_triangleMesh;
+
+ BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
+ btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
+ btTriangleRaycastCallback(from,to),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh)
+ {
+ }
+
+
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
+ {
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = partId;
+ shapeInfo.m_triangleIndex = triangleIndex;
+
+ btCollisionWorld::LocalRayResult rayResult
+ (m_collisionObject,
+ &shapeInfo,
+ hitNormalLocal,
+ hitFraction);
+
+ bool normalInWorldSpace = false;
+ return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
+
+
+ }
+
+ };
+
+
+ BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh);
+ rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+
+ btVector3 rayAabbMinLocal = rayFromLocal;
+ rayAabbMinLocal.setMin(rayToLocal);
+ btVector3 rayAabbMaxLocal = rayFromLocal;
+ rayAabbMaxLocal.setMax(rayToLocal);
+
+ triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
+ }
+ } else {
+ //todo: use AABB tree or other BVH acceleration structure!
+ if (collisionShape->isCompound())
+ {
+ const btCompoundShape* compoundShape = static_cast(collisionShape);
+ int i=0;
+ for (i=0;igetNumChildShapes();i++)
+ {
+ btTransform childTrans = compoundShape->getChildTransform(i);
+ const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
+ btTransform childWorldTrans = colObjWorldTransform * childTrans;
+ // replace collision shape so that callback can determine the triangle
+ btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape();
+ collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape);
+ rayTestSingle(rayFromTrans,rayToTrans,
+ collisionObject,
+ childCollisionShape,
+ childWorldTrans,
+ resultCallback);
+ // restore
+ collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
+ }
+ }
+ }
+ }
}
-void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans,
+void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback,
- short int collisionFilterMask,
- bool faceNormal)
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration)
{
-
-
if (collisionShape->isConvex())
+ {
+ btConvexCast::CastResult castResult;
+ castResult.m_allowedPenetration = allowedPenetration;
+ castResult.m_fraction = btScalar(1.);//??
+
+ btConvexShape* convexShape = (btConvexShape*) collisionShape;
+ btVoronoiSimplexSolver simplexSolver;
+ btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
+
+ btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver);
+ //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
+ //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
+
+ btConvexCast* castPtr = &convexCaster1;
+
+
+
+ if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+ {
+ //add hit
+ if (castResult.m_normal.length2() > btScalar(0.0001))
{
- btConvexCast::CastResult castResult;
- castResult.m_fraction = btScalar(1.);//??
-
- btConvexShape* convexShape = (btConvexShape*) collisionShape;
- btVoronoiSimplexSolver simplexSolver;
- btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
- //GjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
- //ContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
-
- if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+ if (castResult.m_fraction < resultCallback.m_closestHitFraction)
{
- //add hit
- if (castResult.m_normal.length2() > btScalar(0.0001))
- {
- castResult.m_normal.normalize();
- if (castResult.m_fraction < resultCallback.m_closestHitFraction)
- {
-
- btCollisionWorld::LocalRayResult localRayResult
+ castResult.m_normal.normalize();
+ btCollisionWorld::LocalConvexResult localConvexResult
(
- collisionObject,
+ collisionObject,
0,
castResult.m_normal,
+ castResult.m_hitPoint,
castResult.m_fraction
);
- resultCallback.AddSingleResult(localRayResult);
+ bool normalInWorldSpace = true;
+ resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
- }
- }
}
}
- else
+ }
+ } else {
+ if (collisionShape->isConcave())
+ {
+ if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
-
- if (collisionShape->isConcave())
- {
+ btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
+ btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+ btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
+ btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
+ // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
+ btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
- btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape;
-
- btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+ //ConvexCast::CastResult
+ struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
+ {
+ btCollisionWorld::ConvexResultCallback* m_resultCallback;
+ btCollisionObject* m_collisionObject;
+ btTriangleMeshShape* m_triangleMesh;
- btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
- btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
-
- //ConvexCast::CastResult
-
- struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
+ BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
+ btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
+ btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh)
{
- btCollisionWorld::RayResultCallback* m_resultCallback;
- btCollisionObject* m_collisionObject;
- btTriangleMeshShape* m_triangleMesh;
-
- BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,bool faceNormal,
- btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
- btTriangleRaycastCallback(from,to,faceNormal),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh)
- {
- }
-
-
- virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = partId;
- shapeInfo.m_triangleIndex = triangleIndex;
- shapeInfo.m_triangleShape = m_triangleMesh;
-
- btCollisionWorld::LocalRayResult rayResult
- (m_collisionObject,
- &shapeInfo,
- hitNormalLocal,
- hitFraction);
-
- return m_resultCallback->AddSingleResult(rayResult);
-
-
- }
-
- };
-
-
- BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,faceNormal,&resultCallback,collisionObject,triangleMesh);
- rcb.m_hitFraction = resultCallback.m_closestHitFraction;
-
- btVector3 rayAabbMinLocal = rayFromLocal;
- rayAabbMinLocal.setMin(rayToLocal);
- btVector3 rayAabbMaxLocal = rayFromLocal;
- rayAabbMaxLocal.setMax(rayToLocal);
-
- triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
-
- } else
- {
- //todo: use AABB tree or other BVH acceleration structure!
- if (collisionShape->isCompound())
- {
- const btCompoundShape* compoundShape = static_cast(collisionShape);
- int i=0;
- for (i=0;igetNumChildShapes();i++)
- {
- btTransform childTrans = compoundShape->getChildTransform(i);
- const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
- btTransform childWorldTrans = colObjWorldTransform * childTrans;
- objectQuerySingle(castShape, rayFromTrans,rayToTrans,
- collisionObject,
- childCollisionShape,
- childWorldTrans,
- resultCallback, collisionFilterMask, faceNormal);
-
- }
-
-
}
+
+
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
+ {
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = partId;
+ shapeInfo.m_triangleIndex = triangleIndex;
+ if (hitFraction <= m_resultCallback->m_closestHitFraction)
+ {
+
+ btCollisionWorld::LocalConvexResult convexResult
+ (m_collisionObject,
+ &shapeInfo,
+ hitNormalLocal,
+ hitPointLocal,
+ hitFraction);
+
+ bool normalInWorldSpace = true;
+
+
+ return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
+ }
+ return hitFraction;
}
+
+ };
+
+ BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform);
+ tccb.m_hitFraction = resultCallback.m_closestHitFraction;
+ btVector3 boxMinLocal, boxMaxLocal;
+ castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
+ triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal);
+ } else
+ {
+ btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
+ btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+ btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
+ btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
+ // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
+ btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
+
+ //ConvexCast::CastResult
+ struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
+ {
+ btCollisionWorld::ConvexResultCallback* m_resultCallback;
+ btCollisionObject* m_collisionObject;
+ btTriangleMeshShape* m_triangleMesh;
+
+ BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
+ btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
+ btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh)
+ {
+ }
+
+
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
+ {
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = partId;
+ shapeInfo.m_triangleIndex = triangleIndex;
+ if (hitFraction <= m_resultCallback->m_closestHitFraction)
+ {
+
+ btCollisionWorld::LocalConvexResult convexResult
+ (m_collisionObject,
+ &shapeInfo,
+ hitNormalLocal,
+ hitPointLocal,
+ hitFraction);
+
+ bool normalInWorldSpace = false;
+
+ return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
+ }
+ return hitFraction;
+ }
+
+ };
+
+ BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform);
+ tccb.m_hitFraction = resultCallback.m_closestHitFraction;
+ btVector3 boxMinLocal, boxMaxLocal;
+ castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
+
+ btVector3 rayAabbMinLocal = convexFromLocal;
+ rayAabbMinLocal.setMin(convexToLocal);
+ btVector3 rayAabbMaxLocal = convexFromLocal;
+ rayAabbMaxLocal.setMax(convexToLocal);
+ rayAabbMinLocal += boxMinLocal;
+ rayAabbMaxLocal += boxMaxLocal;
+ triangleMesh->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
}
+ } else {
+ //todo: use AABB tree or other BVH acceleration structure!
+ if (collisionShape->isCompound())
+ {
+ const btCompoundShape* compoundShape = static_cast