soc-2008-mxcurioni: merged changes to revision 16789

This commit is contained in:
Maxime Curioni
2008-09-28 17:07:08 +00:00
622 changed files with 56125 additions and 27181 deletions

View File

@@ -64,6 +64,7 @@ OPTION(WITH_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON)
OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF) OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF)
OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON)
OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF) OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF)
OPTION(WITH_WEBPLUGIN "Enable Web Plugin (Mozilla-Unix only)" OFF)
IF(NOT WITH_GAMEENGINE AND WITH_PLAYER) IF(NOT WITH_GAMEENGINE AND WITH_PLAYER)
MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE") MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE")
@@ -456,6 +457,13 @@ SUBDIRS(
# Blender Application # Blender Application
SUBDIRS(source/creator) SUBDIRS(source/creator)
#-----------------------------------------------------------------------------
# Blender WebPlugin
IF(WITH_WEBPLUGIN)
SET(MOZILLA_DIR "${CMAKE_SOURCE_DIR}/../gecko-sdk/" CACHE PATH "Gecko SDK path")
SET(WITH_PLAYER ON)
ENDIF(WITH_WEBPLUGIN)
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# Blender Player # Blender Player
IF(WITH_PLAYER) IF(WITH_PLAYER)

View File

@@ -241,6 +241,13 @@ if len(B.quickdebug) > 0 and printdebug != 0:
for l in B.quickdebug: for l in B.quickdebug:
print "\t" + l 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 # check target for blenderplayer. Set WITH_BF_PLAYER if found on cmdline
if 'blenderplayer' in B.targets: if 'blenderplayer' in B.targets:
env['WITH_BF_PLAYER'] = True env['WITH_BF_PLAYER'] = True
@@ -248,6 +255,31 @@ if 'blenderplayer' in B.targets:
if 'blendernogame' in B.targets: if 'blendernogame' in B.targets:
env['WITH_BF_GAMEENGINE'] = False 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
env['WITH_BF_DDS'] = False
env['WITH_BF_ZLIB'] = False
env['WITH_BF_SDL'] = False
env['WITH_BF_JPEG'] = False
env['WITH_BF_PNG'] = False
env['WITH_BF_ODE'] = False
env['WITH_BF_BULLET'] = False
env['WITH_BF_BINRELOC'] = False
env['BF_BUILDINFO'] = False
env['BF_NO_ELBEEM'] = True
# lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir # 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 = B.arguments.get('BF_BUILDDIR', '..'+os.sep+'build'+os.sep+platform+os.sep)
B.root_build_dir = env['BF_BUILDDIR'] B.root_build_dir = env['BF_BUILDDIR']
@@ -398,6 +430,26 @@ if env['OURPLATFORM']!='darwin':
source=[dp+os.sep+f for f in df] source=[dp+os.sep+f for f in df]
scriptinstall.append(env.Install(dir=dir,source=source)) scriptinstall.append(env.Install(dir=dir,source=source))
#-- icons
if env['OURPLATFORM']=='linux2':
iconlist = []
icontargetlist = []
for tp, tn, tf in os.walk('release/freedesktop/icons'):
if 'CVS' in tn:
tn.remove('CVS')
if '.svn' in tn:
tn.remove('.svn')
for f in tf:
print ">>>", env['BF_INSTALLDIR'], tp, f
iconlist.append(tp+os.sep+f)
icontargetlist.append(env['BF_INSTALLDIR']+tp[19:]+os.sep+f)
iconinstall = []
for targetdir,srcfile in zip(icontargetlist, iconlist):
td, tf = os.path.split(targetdir)
iconinstall.append(env.Install(dir=td, source=srcfile))
#-- plugins #-- plugins
pluglist = [] pluglist = []
plugtargetlist = [] plugtargetlist = []
@@ -446,6 +498,8 @@ textinstall = env.Install(dir=env['BF_INSTALLDIR'], source=textlist)
if env['OURPLATFORM']=='darwin': if env['OURPLATFORM']=='darwin':
allinstall = [blenderinstall, plugininstall, textinstall] allinstall = [blenderinstall, plugininstall, textinstall]
elif env['OURPLATFORM']=='linux2':
allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall, iconinstall]
else: else:
allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall] allinstall = [blenderinstall, dotblenderinstall, scriptinstall, plugininstall, textinstall]
@@ -496,6 +550,10 @@ if not env['WITH_BF_GAMEENGINE']:
blendernogame = env.Alias('blendernogame', B.program_list) blendernogame = env.Alias('blendernogame', B.program_list)
Depends(blendernogame,installtarget) Depends(blendernogame,installtarget)
if 'blenderlite' in B.targets:
blenderlite = env.Alias('blenderlite', B.program_list)
Depends(blenderlite,installtarget)
Depends(nsiscmd, allinstall) Depends(nsiscmd, allinstall)
Default(B.program_list) Default(B.program_list)

View File

@@ -86,6 +86,7 @@ IF(UNIX)
bf_oglrasterizer bf_oglrasterizer
bf_expressions bf_expressions
bf_scenegraph bf_scenegraph
bf_IK
bf_moto bf_moto
bf_soundsystem bf_soundsystem
bf_kernel bf_kernel

View File

@@ -88,9 +88,17 @@ if MAC_PROC == 'powerpc':
else : else :
BF_OPENAL = LIBDIR + '/openal' BF_OPENAL = LIBDIR + '/openal'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'openal' BF_OPENAL_LIB = 'openal'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' 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' WITH_BF_SDL = 'true'
BF_SDL = LIBDIR + '/sdl' #$(shell sdl-config --prefix) BF_SDL = LIBDIR + '/sdl' #$(shell sdl-config --prefix)
@@ -102,10 +110,13 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod' BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true' WITH_BF_OPENEXR = 'true'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '${LCGDIR}/openexr' BF_OPENEXR = '${LCGDIR}/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread' BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread'
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' 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' WITH_BF_DDS = 'true'

View File

@@ -6,18 +6,28 @@ BF_VERSE_INCLUDE = "#extern/verse/dist"
BF_PYTHON = '/usr' BF_PYTHON = '/usr'
BF_PYTHON_VERSION = '2.5' BF_PYTHON_VERSION = '2.5'
WITH_BF_STATICPYTHON = 'false'
BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}'
BF_PYTHON_BINARY = '${BF_PYTHON}/bin/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_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_LINKFLAGS = ['-Xlinker', '-export-dynamic']
BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/libpython${BF_PYTHON_VERSION}.a'
WITH_BF_OPENAL = 'true' WITH_BF_OPENAL = 'true'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = '/usr' BF_OPENAL = '/usr'
BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'openal' BF_OPENAL_LIB = 'openal'
BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
# some distros have a separate libalut # some distros have a separate libalut
# if you get linker complaints, you need to uncomment the line below # if you get linker complaints, you need to uncomment the line below
# BF_OPENAL_LIB = 'openal alut' # 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' WITH_BF_SDL = 'true'
BF_SDL = '/usr' #$(shell sdl-config --prefix) BF_SDL = '/usr' #$(shell sdl-config --prefix)
@@ -28,14 +38,17 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod' BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true' WITH_BF_OPENEXR = 'true'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '/usr' BF_OPENEXR = '/usr'
# when compiling with your own openexr lib you might need to set... # 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}/include'
BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = 'Half IlmImf Iex Imath ' 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' # BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
WITH_BF_DDS = 'true' WITH_BF_DDS = 'true'
WITH_BF_JPEG = 'true' WITH_BF_JPEG = 'true'

View File

@@ -19,10 +19,18 @@ BF_PYTHON_LIB = 'python25'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib'
WITH_BF_OPENAL = 'true' WITH_BF_OPENAL = 'true'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = LIBDIR + '/openal' BF_OPENAL = LIBDIR + '/openal'
BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'openal_static' BF_OPENAL_LIB = 'openal_static'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' 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' WITH_BF_SDL = 'true'
BF_SDL = LIBDIR + '/sdl' BF_SDL = LIBDIR + '/sdl'
@@ -39,10 +47,13 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod' BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true' WITH_BF_OPENEXR = 'true'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = LIBDIR + '/gcc/openexr' BF_OPENEXR = LIBDIR + '/gcc/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = ' Half IlmImf Iex ' BF_OPENEXR_LIB = ' Half IlmImf Iex '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' 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' WITH_BF_DDS = 'true'

View File

@@ -9,10 +9,12 @@ BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}/config' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}/config'
WITH_BF_OPENAL = 'false' WITH_BF_OPENAL = 'false'
# WITH_BF_STATICOPENAL = 'false'
#BF_OPENAL = LIBDIR + '/openal' #BF_OPENAL = LIBDIR + '/openal'
#BF_OPENAL_INC = '${BF_OPENAL}/include' #BF_OPENAL_INC = '${BF_OPENAL}/include'
#BF_OPENAL_LIB = 'openal' #BF_OPENAL_LIB = 'openal'
#BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' #BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
#BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
WITH_BF_SDL = 'true' WITH_BF_SDL = 'true'
BF_SDL = '/usr/local' #$(shell sdl-config --prefix) BF_SDL = '/usr/local' #$(shell sdl-config --prefix)
@@ -24,9 +26,12 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod' BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'false' WITH_BF_OPENEXR = 'false'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '/usr/local' BF_OPENEXR = '/usr/local'
BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = 'Half IlmImf Iex Imath ' 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' WITH_BF_DDS = 'true'

View File

@@ -9,10 +9,18 @@ BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_
BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic'] BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic']
WITH_BF_OPENAL = 'true' WITH_BF_OPENAL = 'true'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = '/usr/local' BF_OPENAL = '/usr/local'
BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
BF_OPENAL_LIB = 'openal' 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' WITH_BF_SDL = 'true'
BF_SDL = '/usr/local' #$(shell sdl-config --prefix) BF_SDL = '/usr/local' #$(shell sdl-config --prefix)
@@ -24,10 +32,13 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod' BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true' WITH_BF_OPENEXR = 'true'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = '/usr/local' BF_OPENEXR = '/usr/local'
BF_OPENEXR_INC = ['${BF_OPENEXR}/include', '${BF_OPENEXR}/include/OpenEXR' ] BF_OPENEXR_INC = ['${BF_OPENEXR}/include', '${BF_OPENEXR}/include/OpenEXR' ]
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
BF_OPENEXR_LIB = 'Half IlmImf Iex Imath ' 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' WITH_BF_DDS = 'true'

View File

@@ -12,10 +12,13 @@ BF_PYTHON_LIB = 'python25'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib'
WITH_BF_OPENAL = 'true' WITH_BF_OPENAL = 'true'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = LIBDIR + '/openal' BF_OPENAL = LIBDIR + '/openal'
BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_INC = '${BF_OPENAL}/include'
BF_OPENAL_LIB = 'dxguid openal_static' BF_OPENAL_LIB = 'dxguid openal_static'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' 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' WITH_BF_FFMPEG = 'false'
BF_FFMPEG_LIB = 'avformat swscale avcodec avutil xvidcore x264' BF_FFMPEG_LIB = 'avformat swscale avcodec avutil xvidcore x264'
@@ -37,10 +40,13 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod' BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true' WITH_BF_OPENEXR = 'true'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = LIBDIR + '/gcc/openexr' BF_OPENEXR = LIBDIR + '/gcc/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR'
BF_OPENEXR_LIB = ' Half IlmImf Iex ' BF_OPENEXR_LIB = ' Half IlmImf Iex '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' 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' WITH_BF_DDS = 'true'

View File

@@ -19,10 +19,18 @@ BF_PYTHON_LIB = 'python25'
BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib'
WITH_BF_OPENAL = 'true' WITH_BF_OPENAL = 'true'
WITH_BF_STATICOPENAL = 'false'
BF_OPENAL = LIBDIR + '/openal' BF_OPENAL = LIBDIR + '/openal'
BF_OPENAL_INC = '${BF_OPENAL}/include ${BF_OPENAL}/include/AL ' BF_OPENAL_INC = '${BF_OPENAL}/include ${BF_OPENAL}/include/AL '
BF_OPENAL_LIB = 'dxguid openal_static' BF_OPENAL_LIB = 'dxguid openal_static'
BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' 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' WITH_BF_ICONV = 'true'
BF_ICONV = LIBDIR + '/iconv' BF_ICONV = LIBDIR + '/iconv'
@@ -45,10 +53,13 @@ WITH_BF_FMOD = 'false'
BF_FMOD = LIBDIR + '/fmod' BF_FMOD = LIBDIR + '/fmod'
WITH_BF_OPENEXR = 'true' WITH_BF_OPENEXR = 'true'
WITH_BF_STATICOPENEXR = 'false'
BF_OPENEXR = LIBDIR + '/openexr' BF_OPENEXR = LIBDIR + '/openexr'
BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/IlmImf ${BF_OPENEXR}/include/Iex ${BF_OPENEXR}/include/Imath ' 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_LIB = ' Iex Half IlmImf Imath IlmThread '
BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib_msvc' 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' WITH_BF_DDS = 'true'

2
extern/SConscript vendored
View File

@@ -31,3 +31,5 @@ if env['WITH_BF_REDCODE'] and env['BF_REDCODE_LIB'] == '':
if env['OURPLATFORM'] == 'linux2': if env['OURPLATFORM'] == 'linux2':
SConscript(['binreloc/SConscript']); SConscript(['binreloc/SConscript']);
SConscript(['fftw/SConscript'])

View File

@@ -31,10 +31,12 @@ FILE(GLOB SRC
src/BulletCollision/BroadphaseCollision/*.cpp src/BulletCollision/BroadphaseCollision/*.cpp
src/BulletCollision/CollisionShapes/*.cpp src/BulletCollision/CollisionShapes/*.cpp
src/BulletCollision/NarrowPhaseCollision/*.cpp src/BulletCollision/NarrowPhaseCollision/*.cpp
src/BulletCollision/Gimpact/*.cpp
src/BulletCollision//CollisionDispatch/*.cpp src/BulletCollision//CollisionDispatch/*.cpp
src/BulletDynamics/ConstraintSolver/*.cpp src/BulletDynamics/ConstraintSolver/*.cpp
src/BulletDynamics/Vehicle/*.cpp src/BulletDynamics/Vehicle/*.cpp
src/BulletDynamics/Dynamics/*.cpp src/BulletDynamics/Dynamics/*.cpp
src/BulletSoftBody/*.cpp
) )
ADD_DEFINITIONS(-D_LIB) ADD_DEFINITIONS(-D_LIB)

View File

@@ -37,10 +37,12 @@ LinearMath \
BulletCollision/BroadphaseCollision \ BulletCollision/BroadphaseCollision \
BulletCollision/CollisionShapes \ BulletCollision/CollisionShapes \
BulletCollision/NarrowPhaseCollision \ BulletCollision/NarrowPhaseCollision \
BulletCollision/Gimpact \
BulletCollision//CollisionDispatch \ BulletCollision//CollisionDispatch \
BulletDynamics/ConstraintSolver \ BulletDynamics/ConstraintSolver \
BulletDynamics/Vehicle \ BulletDynamics/Vehicle \
BulletDynamics/Dynamics BulletDynamics/Dynamics \
BulletSoftBody
include nan_subdirs.mk include nan_subdirs.mk

View File

@@ -53,6 +53,7 @@ IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\NarrowPhaseCollision MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\NarrowPhaseCollision MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionDispatch MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionDispatch MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionShapes MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionShapes MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\Gimpact MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\ConstraintSolver MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\ConstraintSolver MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
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\Dynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
@@ -66,6 +67,7 @@ XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build
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
XCOPY /Y ..\..\src\BulletCollision\CollisionDispatch\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch XCOPY /Y ..\..\src\BulletCollision\CollisionDispatch\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
XCOPY /Y ..\..\src\BulletCollision\CollisionShapes\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes XCOPY /Y ..\..\src\BulletCollision\CollisionShapes\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
XCOPY /Y ..\..\src\BulletCollision\Gimpact\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
XCOPY /Y ..\..\src\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver XCOPY /Y ..\..\src\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
XCOPY /Y ..\..\src\BulletDynamics\Dynamics\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics XCOPY /Y ..\..\src\BulletDynamics\Dynamics\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
XCOPY /Y ..\..\src\BulletDynamics\Vehicle\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle XCOPY /Y ..\..\src\BulletDynamics\Vehicle\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle
@@ -133,6 +135,7 @@ IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\NarrowPhaseCollision MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\NarrowPhaseCollision MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionDispatch MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionDispatch MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionShapes MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionShapes MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\Gimpact MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\ConstraintSolver MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\ConstraintSolver MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
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\Dynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
@@ -146,6 +149,7 @@ XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build
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
XCOPY /Y ..\..\src\BulletCollision\CollisionDispatch\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch XCOPY /Y ..\..\src\BulletCollision\CollisionDispatch\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
XCOPY /Y ..\..\src\BulletCollision\CollisionShapes\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes XCOPY /Y ..\..\src\BulletCollision\CollisionShapes\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
XCOPY /Y ..\..\src\BulletCollision\Gimpact\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
XCOPY /Y ..\..\src\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver XCOPY /Y ..\..\src\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
XCOPY /Y ..\..\src\BulletDynamics\Dynamics\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics XCOPY /Y ..\..\src\BulletDynamics\Dynamics\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
XCOPY /Y ..\..\src\BulletDynamics\Vehicle\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle XCOPY /Y ..\..\src\BulletDynamics\Vehicle\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle
@@ -211,6 +215,7 @@ IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\NarrowPhaseCollision MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\NarrowPhaseCollision MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionDispatch MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionDispatch MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionShapes MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionShapes MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\Gimpact MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\ConstraintSolver MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\ConstraintSolver MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
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\Dynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
@@ -224,6 +229,7 @@ XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build
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
XCOPY /Y ..\..\src\BulletCollision\CollisionDispatch\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch XCOPY /Y ..\..\src\BulletCollision\CollisionDispatch\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
XCOPY /Y ..\..\src\BulletCollision\CollisionShapes\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes XCOPY /Y ..\..\src\BulletCollision\CollisionShapes\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
XCOPY /Y ..\..\src\BulletCollision\Gimpact\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
XCOPY /Y ..\..\src\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver XCOPY /Y ..\..\src\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
XCOPY /Y ..\..\src\BulletDynamics\Dynamics\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics XCOPY /Y ..\..\src\BulletDynamics\Dynamics\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
XCOPY /Y ..\..\src\BulletDynamics\Vehicle\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle XCOPY /Y ..\..\src\BulletDynamics\Vehicle\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle
@@ -291,6 +297,7 @@ IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\NarrowPhaseCollision MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\NarrowPhaseCollision MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionDispatch MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionDispatch MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionShapes MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\CollisionShapes MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletCollision\Gimpact MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics
IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\ConstraintSolver MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\ConstraintSolver MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
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\Dynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
@@ -304,6 +311,7 @@ XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build
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
XCOPY /Y ..\..\src\BulletCollision\CollisionDispatch\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch XCOPY /Y ..\..\src\BulletCollision\CollisionDispatch\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionDispatch
XCOPY /Y ..\..\src\BulletCollision\CollisionShapes\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes XCOPY /Y ..\..\src\BulletCollision\CollisionShapes\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\CollisionShapes
XCOPY /Y ..\..\src\BulletCollision\Gimpact\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\Gimpact
XCOPY /Y ..\..\src\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver XCOPY /Y ..\..\src\BulletDynamics\ConstraintSolver\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\ConstraintSolver
XCOPY /Y ..\..\src\BulletDynamics\Dynamics\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics XCOPY /Y ..\..\src\BulletDynamics\Dynamics\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics
XCOPY /Y ..\..\src\BulletDynamics\Vehicle\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle XCOPY /Y ..\..\src\BulletDynamics\Vehicle\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle
@@ -394,12 +402,24 @@ ECHO Done
<File <File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSequentialImpulseConstraintSolver.h"> RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSequentialImpulseConstraintSolver.h">
</File> </File>
<File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSliderConstraint.cpp">
</File>
<File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSliderConstraint.h">
</File>
<File <File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSolve2LinearConstraint.cpp"> RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSolve2LinearConstraint.cpp">
</File> </File>
<File <File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSolve2LinearConstraint.h"> RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSolve2LinearConstraint.h">
</File> </File>
<File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSolverBody.h">
</File>
<File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btSolverConstraint.h">
</File>
<File <File
RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btTypedConstraint.cpp"> RelativePath="..\..\src\BulletDynamics\ConstraintSolver\btTypedConstraint.cpp">
</File> </File>
@@ -410,6 +430,12 @@ ECHO Done
<Filter <Filter
Name="Dynamics" Name="Dynamics"
Filter=""> Filter="">
<File
RelativePath="..\..\src\BulletDynamics\Dynamics\btContinuousDynamicsWorld.cpp">
</File>
<File
RelativePath="..\..\src\BulletDynamics\Dynamics\btContinuousDynamicsWorld.h">
</File>
<File <File
RelativePath="..\..\src\BulletDynamics\Dynamics\btDiscreteDynamicsWorld.cpp"> RelativePath="..\..\src\BulletDynamics\Dynamics\btDiscreteDynamicsWorld.cpp">
</File> </File>
@@ -482,18 +508,45 @@ ECHO Done
<File <File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btCollisionAlgorithm.h"> RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btCollisionAlgorithm.h">
</File> </File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDbvt.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDbvt.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDbvtBroadphase.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDbvtBroadphase.h">
</File>
<File <File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDispatcher.cpp"> RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDispatcher.cpp">
</File> </File>
<File <File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDispatcher.h"> RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btDispatcher.h">
</File> </File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btMultiSapBroadphase.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btMultiSapBroadphase.h">
</File>
<File <File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btOverlappingPairCache.cpp"> RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btOverlappingPairCache.cpp">
</File> </File>
<File <File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btOverlappingPairCache.h"> RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btOverlappingPairCache.h">
</File> </File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btOverlappingPairCallback.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btQuantizedBvh.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btQuantizedBvh.h">
</File>
<File <File
RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btSimpleBroadphase.cpp"> RelativePath="..\..\src\BulletCollision\BroadphaseCollision\btSimpleBroadphase.cpp">
</File> </File>
@@ -534,6 +587,12 @@ ECHO Done
<File <File
RelativePath="..\..\src\BulletCollision\NarrowPhaseCollision\btGjkEpa.h"> RelativePath="..\..\src\BulletCollision\NarrowPhaseCollision\btGjkEpa.h">
</File> </File>
<File
RelativePath="..\..\src\BulletCollision\NarrowPhaseCollision\btGjkEpa2.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\NarrowPhaseCollision\btGjkEpa2.h">
</File>
<File <File
RelativePath="..\..\src\BulletCollision\NarrowPhaseCollision\btGjkEpaPenetrationDepthSolver.cpp"> RelativePath="..\..\src\BulletCollision\NarrowPhaseCollision\btGjkEpaPenetrationDepthSolver.cpp">
</File> </File>
@@ -589,6 +648,21 @@ ECHO Done
<Filter <Filter
Name="CollisionDispatch" Name="CollisionDispatch"
Filter=""> Filter="">
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btBoxBoxCollisionAlgorithm.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btBoxBoxCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btBoxBoxDetector.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btBoxBoxDetector.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btCollisionConfiguration.h">
</File>
<File <File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btCollisionCreateFunc.h"> RelativePath="..\..\src\BulletCollision\CollisionDispatch\btCollisionCreateFunc.h">
</File> </File>
@@ -628,6 +702,18 @@ ECHO Done
<File <File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btConvexConvexAlgorithm.h"> RelativePath="..\..\src\BulletCollision\CollisionDispatch\btConvexConvexAlgorithm.h">
</File> </File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btConvexPlaneCollisionAlgorithm.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btConvexPlaneCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btDefaultCollisionConfiguration.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btDefaultCollisionConfiguration.h">
</File>
<File <File
RelativePath="..\..\src\BulletCollision\CollisionDispatch\btEmptyCollisionAlgorithm.cpp"> RelativePath="..\..\src\BulletCollision\CollisionDispatch\btEmptyCollisionAlgorithm.cpp">
</File> </File>
@@ -731,6 +817,12 @@ ECHO Done
<File <File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btConvexHullShape.h"> RelativePath="..\..\src\BulletCollision\CollisionShapes\btConvexHullShape.h">
</File> </File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btConvexInternalShape.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btConvexInternalShape.h">
</File>
<File <File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btConvexShape.cpp"> RelativePath="..\..\src\BulletCollision\CollisionShapes\btConvexShape.cpp">
</File> </File>
@@ -761,12 +853,21 @@ ECHO Done
<File <File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btHeightfieldTerrainShape.h"> RelativePath="..\..\src\BulletCollision\CollisionShapes\btHeightfieldTerrainShape.h">
</File> </File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btMaterial.h">
</File>
<File <File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btMinkowskiSumShape.cpp"> RelativePath="..\..\src\BulletCollision\CollisionShapes\btMinkowskiSumShape.cpp">
</File> </File>
<File <File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btMinkowskiSumShape.h"> RelativePath="..\..\src\BulletCollision\CollisionShapes\btMinkowskiSumShape.h">
</File> </File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btMultimaterialTriangleMeshShape.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btMultimaterialTriangleMeshShape.h">
</File>
<File <File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btMultiSphereShape.cpp"> RelativePath="..\..\src\BulletCollision\CollisionShapes\btMultiSphereShape.cpp">
</File> </File>
@@ -785,6 +886,18 @@ ECHO Done
<File <File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btPolyhedralConvexShape.h"> RelativePath="..\..\src\BulletCollision\CollisionShapes\btPolyhedralConvexShape.h">
</File> </File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btScaledBvhTriangleMeshShape.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btScaledBvhTriangleMeshShape.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btShapeHull.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btShapeHull.h">
</File>
<File <File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btSphereShape.cpp"> RelativePath="..\..\src\BulletCollision\CollisionShapes\btSphereShape.cpp">
</File> </File>
@@ -827,6 +940,12 @@ ECHO Done
<File <File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleIndexVertexArray.h"> RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleIndexVertexArray.h">
</File> </File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleIndexVertexMaterialArray.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleIndexVertexMaterialArray.h">
</File>
<File <File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleMesh.cpp"> RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleMesh.cpp">
</File> </File>
@@ -842,6 +961,130 @@ ECHO Done
<File <File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleShape.h"> RelativePath="..\..\src\BulletCollision\CollisionShapes\btTriangleShape.h">
</File> </File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btUniformScalingShape.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\CollisionShapes\btUniformScalingShape.h">
</File>
</Filter>
<Filter
Name="Gimpact"
Filter="">
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btBoxCollision.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btClipPolygon.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btContactProcessing.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btContactProcessing.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGenericPoolAllocator.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGenericPoolAllocator.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGeometryOperations.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactBvh.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactBvh.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactCollisionAlgorithm.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactMassUtil.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactQuantizedBvh.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactQuantizedBvh.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactShape.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btGImpactShape.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btQuantization.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btTriangleShapeEx.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\btTriangleShapeEx.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_array.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_basic_geometry_operations.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_bitset.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_box_collision.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_box_set.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_box_set.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_clip_polygon.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_contact.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_contact.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_geom_types.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_geometry.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_hash_table.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_linear_math.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_math.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_memory.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_memory.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_radixsort.h">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_tri_collision.cpp">
</File>
<File
RelativePath="..\..\src\BulletCollision\Gimpact\gim_tri_collision.h">
</File>
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter
@@ -859,6 +1102,12 @@ ECHO Done
<File <File
RelativePath="..\..\src\LinearMath\btAlignedObjectArray.h"> RelativePath="..\..\src\LinearMath\btAlignedObjectArray.h">
</File> </File>
<File
RelativePath="..\..\src\LinearMath\btConvexHull.cpp">
</File>
<File
RelativePath="..\..\src\LinearMath\btConvexHull.h">
</File>
<File <File
RelativePath="..\..\src\LinearMath\btDefaultMotionState.h"> RelativePath="..\..\src\LinearMath\btDefaultMotionState.h">
</File> </File>
@@ -868,6 +1117,9 @@ ECHO Done
<File <File
RelativePath="..\..\src\LinearMath\btGeometryUtil.h"> RelativePath="..\..\src\LinearMath\btGeometryUtil.h">
</File> </File>
<File
RelativePath="..\..\src\LinearMath\btHashMap.h">
</File>
<File <File
RelativePath="..\..\src\LinearMath\btIDebugDraw.h"> RelativePath="..\..\src\LinearMath\btIDebugDraw.h">
</File> </File>
@@ -886,6 +1138,9 @@ ECHO Done
<File <File
RelativePath="..\..\src\LinearMath\btPoint3.h"> RelativePath="..\..\src\LinearMath\btPoint3.h">
</File> </File>
<File
RelativePath="..\..\src\LinearMath\btPoolAllocator.h">
</File>
<File <File
RelativePath="..\..\src\LinearMath\btQuadWord.h"> RelativePath="..\..\src\LinearMath\btQuadWord.h">
</File> </File>
@@ -904,9 +1159,6 @@ ECHO Done
<File <File
RelativePath="..\..\src\LinearMath\btScalar.h"> RelativePath="..\..\src\LinearMath\btScalar.h">
</File> </File>
<File
RelativePath="..\..\src\LinearMath\btSimdMinMax.h">
</File>
<File <File
RelativePath="..\..\src\LinearMath\btStackAlloc.h"> RelativePath="..\..\src\LinearMath\btStackAlloc.h">
</File> </File>
@@ -920,6 +1172,58 @@ ECHO Done
RelativePath="..\..\src\LinearMath\btVector3.h"> RelativePath="..\..\src\LinearMath\btVector3.h">
</File> </File>
</Filter> </Filter>
<Filter
Name="BulletSoftBody"
Filter="">
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBody.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBody.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyConcaveCollisionAlgorithm.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyConcaveCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyHelpers.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyHelpers.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyInternals.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyRigidBodyCollisionConfiguration.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftBodyRigidBodyCollisionConfiguration.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftRigidCollisionAlgorithm.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftRigidCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftRigidDynamicsWorld.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftRigidDynamicsWorld.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftSoftCollisionAlgorithm.cpp">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSoftSoftCollisionAlgorithm.h">
</File>
<File
RelativePath="..\..\src\BulletSoftBody\btSparseSDF.h">
</File>
</Filter>
</Filter> </Filter>
</Files> </Files>
<Globals> <Globals>

View File

@@ -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 *** *** These files in extern/bullet2 are NOT part of the Blender build yet ***

View File

@@ -23,15 +23,153 @@ subject to the following restrictions:
#ifndef BULLET_C_API_H #ifndef BULLET_C_API_H
#define 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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #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 #ifdef __cplusplus
} }
#endif #endif
#endif //BULLET_C_API_H #endif //BULLET_C_API_H

View File

@@ -21,640 +21,18 @@
#include <assert.h> #include <assert.h>
#ifdef DEBUG_BROADPHASE btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache)
#include <stdio.h> :btAxisSweep3Internal<unsigned short int>(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache)
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;i<numEdges+1;i++)
{
Edge* pEdge = m_pEdges[axis] + i;
Handle* pHandlePrev = getHandle(pEdge->m_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<Handle*>(proxy);
removeHandle(handle->m_handleId);
}
void btAxisSweep3::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)
{
Handle* handle = static_cast<Handle*>(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 // 1 handle is reserved as sentinel
btAssert(maxHandles > 1 && maxHandles < BP_MAX_HANDLES); btAssert(maxHandles > 1 && maxHandles < 32767);
// 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
}
} }
btAxisSweep3::~btAxisSweep3()
bt32BitAxisSweep3::bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache )
:btAxisSweep3Internal<unsigned int>(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache)
{ {
// 1 handle is reserved as sentinel
for (int i = 2; i >= 0; i--) btAssert(maxHandles > 1 && maxHandles < 2147483647);
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;i<m_overlappingPairArray.size();i++)
{
btBroadphasePair& pair = m_overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
previousPair = pair;
bool needsRemoval = false;
if (!isDuplicate)
{
bool hasOverlap = testOverlap(pair.m_pProxy0,pair.m_pProxy1);
if (hasOverlap)
{
needsRemoval = callback->processOverlap(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<Handle*>(proxy0);
const Handle* pHandleB = static_cast<Handle*>(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++;
}
} }

View File

@@ -19,34 +19,26 @@
#ifndef AXIS_SWEEP_3_H #ifndef AXIS_SWEEP_3_H
#define AXIS_SWEEP_3_H #define AXIS_SWEEP_3_H
#include "../../LinearMath/btPoint3.h" #include "LinearMath/btPoint3.h"
#include "../../LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
#include "btOverlappingPairCache.h" #include "btOverlappingPairCache.h"
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h" #include "btBroadphaseProxy.h"
#include "btOverlappingPairCallback.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
//#define DEBUG_BROADPHASE 1 //#define DEBUG_BROADPHASE 1
#define USE_OVERLAP_TEST_ON_REMOVES 1
/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. /// The internal templace class btAxisSweep3Internal implements the 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. /// It uses quantized integers to represent the begin and end points for each of the 3 axis.
/// The testOverlap check is optimized to check the array index, rather then the actual AABB coordinates/pos /// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
class btAxisSweep3 : public btOverlappingPairCache template <typename BP_FP_INT_TYPE>
class btAxisSweep3Internal : public btBroadphaseInterface
{ {
protected:
BP_FP_INT_TYPE m_bpHandleMask;
BP_FP_INT_TYPE m_handleSentinel;
public: public:
@@ -57,38 +49,48 @@ public:
BP_FP_INT_TYPE m_pos; // low bit is min/max BP_FP_INT_TYPE m_pos; // low bit is min/max
BP_FP_INT_TYPE m_handle; 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<BP_FP_INT_TYPE>(m_pos & 1);}
}; };
public: public:
class Handle : public btBroadphaseProxy class Handle : public btBroadphaseProxy
{ {
public: public:
BT_DECLARE_ALIGNED_ALLOCATOR();
// indexes into the edge arrays // indexes into the edge arrays
BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12 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; BP_FP_INT_TYPE m_pad;
//void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
inline void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} SIMD_FORCE_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 BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
}; // 24 bytes + 24 for Edge structures = 44 bytes total per entry }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
private: protected:
btPoint3 m_worldAabbMin; // overall system bounds btPoint3 m_worldAabbMin; // overall system bounds
btPoint3 m_worldAabbMax; // overall system bounds btPoint3 m_worldAabbMax; // overall system bounds
btVector3 m_quantize; // scaling factor for quantization btVector3 m_quantize; // scaling factor for quantization
BP_FP_INT_TYPE m_numHandles; // number of active handles 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 Handle* m_pHandles; // handles pool
BP_FP_INT_TYPE m_firstFreeHandle; // free handles list 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) Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
void* m_pEdgesRawPtr[3];
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; int m_invalidPair;
@@ -97,7 +99,7 @@ private:
void freeHandle(BP_FP_INT_TYPE handle); 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 #ifdef DEBUG_BROADPHASE
void debugPrintAxis(int axis,bool checkCardinality=true); 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 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 sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
void sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
void sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
void sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
public: 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);
BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask); virtual ~btAxisSweep3Internal();
void removeHandle(BP_FP_INT_TYPE handle);
void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax); BP_FP_INT_TYPE getNumHandles() const
inline Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} {
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,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); void processAllOverlappingPairs(btOverlapCallback* callback);
//Broadphase Interface //Broadphase Interface
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 destroyProxy(btBroadphaseProxy* proxy); virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
bool testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
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 <stdio.h>
template <typename BP_FP_INT_TYPE>
void btAxisSweep3<BP_FP_INT_TYPE>::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;i<numEdges+1;i++)
{
Edge* pEdge = m_pEdges[axis] + i;
Handle* pHandlePrev = getHandle(pEdge->m_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 <typename BP_FP_INT_TYPE>
btBroadphaseProxy* btAxisSweep3Internal<BP_FP_INT_TYPE>::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 <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
Handle* handle = static_cast<Handle*>(proxy);
removeHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), dispatcher);
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
{
Handle* handle = static_cast<Handle*>(proxy);
updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax,dispatcher);
}
template <typename BP_FP_INT_TYPE>
btAxisSweep3Internal<BP_FP_INT_TYPE>::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<BP_FP_INT_TYPE>(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<BP_FP_INT_TYPE>(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 <typename BP_FP_INT_TYPE>
btAxisSweep3Internal<BP_FP_INT_TYPE>::~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 <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::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 <typename BP_FP_INT_TYPE>
BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
{
assert(m_firstFreeHandle);
BP_FP_INT_TYPE handle = m_firstFreeHandle;
m_firstFreeHandle = getHandle(handle)->GetNextFree();
m_numHandles++;
return handle;
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
{
assert(handle > 0 && handle < m_maxHandles);
getHandle(handle)->SetNextFree(m_firstFreeHandle);
m_firstFreeHandle = handle;
m_numHandles--;
}
template <typename BP_FP_INT_TYPE>
BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::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<int>(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<BP_FP_INT_TYPE>(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<BP_FP_INT_TYPE>(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 <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::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<int>(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 <stdio.h>
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::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;i<overlappingPairArray.size();i++)
{
btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
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)
{
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 <typename BP_FP_INT_TYPE>
bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
const Handle* pHandleA = static_cast<Handle*>(proxy0);
const Handle* pHandleB = static_cast<Handle*>(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 <typename BP_FP_INT_TYPE>
bool btAxisSweep3Internal<BP_FP_INT_TYPE>::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 <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::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 <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::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 <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::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 <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::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 <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::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<unsigned short int>
{
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<unsigned int>
{
public:
bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0);
}; };

View File

@@ -20,20 +20,34 @@ subject to the following restrictions:
struct btDispatcherInfo; struct btDispatcherInfo;
class btDispatcher; class btDispatcher;
struct btBroadphaseProxy; #include "btBroadphaseProxy.h"
#include "../../LinearMath/btVector3.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 class btBroadphaseInterface
{ {
public: public:
virtual ~btBroadphaseInterface() {} virtual ~btBroadphaseInterface() {}
virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) =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)=0; virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0;
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)=0; virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy)=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;
}; };

View File

@@ -16,7 +16,8 @@ subject to the following restrictions:
#ifndef BROADPHASE_PROXY_H #ifndef BROADPHASE_PROXY_H
#define 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 /// btDispatcher uses these types
@@ -38,18 +39,22 @@ IMPLICIT_CONVEX_SHAPES_START_HERE,
CONE_SHAPE_PROXYTYPE, CONE_SHAPE_PROXYTYPE,
CONVEX_SHAPE_PROXYTYPE, CONVEX_SHAPE_PROXYTYPE,
CYLINDER_SHAPE_PROXYTYPE, CYLINDER_SHAPE_PROXYTYPE,
UNIFORM_SCALING_SHAPE_PROXYTYPE,
MINKOWSKI_SUM_SHAPE_PROXYTYPE, MINKOWSKI_SUM_SHAPE_PROXYTYPE,
MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE, MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
//concave shapes //concave shapes
CONCAVE_SHAPES_START_HERE, CONCAVE_SHAPES_START_HERE,
//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy! //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
TRIANGLE_MESH_SHAPE_PROXYTYPE, TRIANGLE_MESH_SHAPE_PROXYTYPE,
SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
///used for demo integration FAST/Swift collision library and Bullet ///used for demo integration FAST/Swift collision library and Bullet
FAST_CONCAVE_MESH_PROXYTYPE, FAST_CONCAVE_MESH_PROXYTYPE,
//terrain //terrain
TERRAIN_SHAPE_PROXYTYPE, TERRAIN_SHAPE_PROXYTYPE,
///Used for GIMPACT Trimesh integration ///Used for GIMPACT Trimesh integration
GIMPACT_SHAPE_PROXYTYPE, GIMPACT_SHAPE_PROXYTYPE,
///Multimaterial mesh
MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
EMPTY_SHAPE_PROXYTYPE, EMPTY_SHAPE_PROXYTYPE,
STATIC_PLANE_PROXYTYPE, STATIC_PLANE_PROXYTYPE,
@@ -57,14 +62,19 @@ CONCAVE_SHAPES_END_HERE,
COMPOUND_SHAPE_PROXYTYPE, COMPOUND_SHAPE_PROXYTYPE,
SOFTBODY_SHAPE_PROXYTYPE,
MAX_BROADPHASE_COLLISION_TYPES MAX_BROADPHASE_COLLISION_TYPES
}; };
///btBroadphaseProxy ///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
struct btBroadphaseProxy ///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 ///optional filtering to cull potential collisions
enum CollisionFilterGroups enum CollisionFilterGroups
{ {
@@ -73,44 +83,60 @@ struct btBroadphaseProxy
KinematicFilter = 4, KinematicFilter = 4,
DebrisFilter = 8, DebrisFilter = 8,
SensorTrigger = 16, 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 //Usually the client btCollisionObject or Rigidbody class
void* m_clientObject; void* m_clientObject;
short int m_collisionFilterGroup; short int m_collisionFilterGroup;
short int m_collisionFilterMask; short int m_collisionFilterMask;
//used for memory pools void* m_multiSapParentProxy;
btBroadphaseProxy() :m_clientObject(0){}
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_clientObject(userPtr),
m_collisionFilterGroup(collisionFilterGroup), m_collisionFilterGroup(collisionFilterGroup),
m_collisionFilterMask(collisionFilterMask) 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); 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); 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) && return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
(proxyType < CONCAVE_SHAPES_END_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); return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
} }
static inline bool isInfinite(int proxyType) static SIMD_FORCE_INLINE bool isInfinite(int proxyType)
{ {
return (proxyType == STATIC_PLANE_PROXYTYPE); return (proxyType == STATIC_PLANE_PROXYTYPE);
} }
@@ -124,8 +150,9 @@ struct btBroadphaseProxy;
/// contains a pair of aabb-overlapping objects ///The btBroadphasePair class contains a pair of aabb-overlapping objects.
struct btBroadphasePair ///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes.
ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
{ {
btBroadphasePair () btBroadphasePair ()
: :
@@ -136,6 +163,8 @@ struct btBroadphasePair
{ {
} }
BT_DECLARE_ALIGNED_ALLOCATOR();
btBroadphasePair(const btBroadphasePair& other) btBroadphasePair(const btBroadphasePair& other)
: m_pProxy0(other.m_pProxy0), : m_pProxy0(other.m_pProxy0),
m_pProxy1(other.m_pProxy1), m_pProxy1(other.m_pProxy1),
@@ -181,6 +210,7 @@ SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePa
*/ */
class btBroadphasePairSortPredicate class btBroadphasePairSortPredicate
{ {
public: public:

View File

@@ -18,6 +18,6 @@ subject to the following restrictions:
btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
{ {
m_dispatcher = ci.m_dispatcher; m_dispatcher = ci.m_dispatcher1;
} }

View File

@@ -16,7 +16,8 @@ subject to the following restrictions:
#ifndef COLLISION_ALGORITHM_H #ifndef COLLISION_ALGORITHM_H
#define COLLISION_ALGORITHM_H #define COLLISION_ALGORITHM_H
#include "../../LinearMath/btScalar.h" #include "LinearMath/btScalar.h"
#include "LinearMath/btAlignedObjectArray.h"
struct btBroadphaseProxy; struct btBroadphaseProxy;
class btDispatcher; class btDispatcher;
@@ -25,21 +26,22 @@ class btCollisionObject;
struct btDispatcherInfo; struct btDispatcherInfo;
class btPersistentManifold; class btPersistentManifold;
typedef btAlignedObjectArray<btPersistentManifold*> btManifoldArray;
struct btCollisionAlgorithmConstructionInfo struct btCollisionAlgorithmConstructionInfo
{ {
btCollisionAlgorithmConstructionInfo() btCollisionAlgorithmConstructionInfo()
:m_dispatcher(0), :m_dispatcher1(0),
m_manifold(0) m_manifold(0)
{ {
} }
btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp) btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp)
:m_dispatcher(dispatcher) :m_dispatcher1(dispatcher)
{ {
(void)temp; (void)temp;
} }
btDispatcher* m_dispatcher; btDispatcher* m_dispatcher1;
btPersistentManifold* m_manifold; btPersistentManifold* m_manifold;
int getDispatcherId(); int getDispatcherId();
@@ -71,6 +73,7 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
}; };

View File

@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef _DISPATCHER_H #ifndef _DISPATCHER_H
#define _DISPATCHER_H #define _DISPATCHER_H
#include "../../LinearMath/btScalar.h" #include "LinearMath/btScalar.h"
class btCollisionAlgorithm; class btCollisionAlgorithm;
struct btBroadphaseProxy; struct btBroadphaseProxy;
@@ -43,7 +43,9 @@ struct btDispatcherInfo
m_useContinuous(false), m_useContinuous(false),
m_debugDraw(0), m_debugDraw(0),
m_enableSatConvex(false), m_enableSatConvex(false),
m_enableSPU(false), m_enableSPU(true),
m_useEpa(true),
m_allowedCcdPenetration(btScalar(0.04)),
m_stackAllocator(0) m_stackAllocator(0)
{ {
@@ -51,17 +53,19 @@ struct btDispatcherInfo
btScalar m_timeStep; btScalar m_timeStep;
int m_stepCount; int m_stepCount;
int m_dispatchFunc; int m_dispatchFunc;
btScalar m_timeOfImpact; mutable btScalar m_timeOfImpact;
bool m_useContinuous; bool m_useContinuous;
class btIDebugDraw* m_debugDraw; class btIDebugDraw* m_debugDraw;
bool m_enableSatConvex; bool m_enableSatConvex;
bool m_enableSPU; bool m_enableSPU;
bool m_useEpa;
btScalar m_allowedCcdPenetration;
btStackAlloc* m_stackAllocator; btStackAlloc* m_stackAllocator;
}; };
/// btDispatcher can be used in combination with broadphase to dispatch overlapping pairs. ///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs.
/// For example for pairwise collision detection or user callbacks (game logic). ///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic).
class btDispatcher class btDispatcher
{ {
@@ -81,12 +85,18 @@ public:
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0; 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 int getNumManifolds() const = 0;
virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0; virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
virtual btPersistentManifold** getInternalManifoldPointer() = 0;
virtual void* allocateCollisionAlgorithm(int size) = 0;
virtual void freeCollisionAlgorithm(void* ptr) = 0;
}; };

View File

@@ -1,4 +1,3 @@
/* /*
Bullet Continuous Collision Detection and Physics Library Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
@@ -21,44 +20,43 @@ subject to the following restrictions:
#include "btDispatcher.h" #include "btDispatcher.h"
#include "btCollisionAlgorithm.h" #include "btCollisionAlgorithm.h"
#include <stdio.h>
int gOverlappingPairs = 0; int gOverlappingPairs = 0;
btOverlappingPairCache::btOverlappingPairCache(): int gRemovePairs =0;
m_blockedForChanges(false), int gAddedPairs =0;
m_overlapFilterCallback(0) int gFindPairs =0;
//m_NumOverlapBroadphasePair(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 //todo/test: show we erase/delete data, or is it automatic
} }
void btOverlappingPairCache::removeOverlappingPair(btBroadphasePair& findPair)
{
int findIndex = m_overlappingPairArray.findLinearSearch(findPair); void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
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)
{ {
if (pair.m_algorithm) if (pair.m_algorithm)
{ {
{ {
delete pair.m_algorithm;; pair.m_algorithm->~btCollisionAlgorithm();
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
pair.m_algorithm=0; pair.m_algorithm=0;
} }
} }
@@ -67,60 +65,20 @@ void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair)
void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
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)
{ {
class CleanPairCallback : public btOverlapCallback class CleanPairCallback : public btOverlapCallback
{ {
btBroadphaseProxy* m_cleanProxy; btBroadphaseProxy* m_cleanProxy;
btOverlappingPairCache* m_pairCache; btOverlappingPairCache* m_pairCache;
btDispatcher* m_dispatcher;
public: public:
CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache) CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
:m_cleanProxy(cleanProxy), :m_cleanProxy(cleanProxy),
m_pairCache(pairCache) m_pairCache(pairCache),
m_dispatcher(dispatcher)
{ {
} }
virtual bool processOverlap(btBroadphasePair& pair) virtual bool processOverlap(btBroadphasePair& pair)
@@ -128,22 +86,23 @@ void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy)
if ((pair.m_pProxy0 == m_cleanProxy) || if ((pair.m_pProxy0 == m_cleanProxy) ||
(pair.m_pProxy1 == m_cleanProxy)) (pair.m_pProxy1 == m_cleanProxy))
{ {
m_pairCache->cleanOverlappingPair(pair); m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
} }
return false; 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 class RemovePairCallback : public btOverlapCallback
@@ -166,12 +125,346 @@ void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseP
RemovePairCallback removeCallback(proxy); 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<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(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 <stdio.h>
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;i<curHashtableSize;i++)
{
const btBroadphasePair& pair = m_overlappingPairArray[i];
int proxyId1 = pair.m_pProxy0->getUid();
int proxyId2 = pair.m_pProxy1->getUid();
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(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<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(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<m_overlappingPairArray.size();++i)
{
if( (m_overlappingPairArray[i].m_pProxy0==proxy0)&&
(m_overlappingPairArray[i].m_pProxy1==proxy1))
{
printf("Adding duplicated %u<>%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<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(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<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(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<int>(getHash(static_cast<unsigned int>(last->m_pProxy0->getUid()), static_cast<unsigned int>(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 <stdio.h>
void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
{
int i;
// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
for (i=0;i<m_overlappingPairArray.size();)
{
btBroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*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 <stdio.h>
void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
{ {
int i; int i;
@@ -182,9 +475,9 @@ void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callb
btBroadphasePair* pair = &m_overlappingPairArray[i]; btBroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*pair)) 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(); m_overlappingPairArray.pop_back();
gOverlappingPairs--; gOverlappingPairs--;
} else } 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);
}

View File

@@ -1,4 +1,3 @@
/* /*
Bullet Continuous Collision Detection and Physics Library Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
@@ -20,9 +19,13 @@ subject to the following restrictions:
#include "btBroadphaseInterface.h" #include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h" #include "btBroadphaseProxy.h"
#include "../../LinearMath/btPoint3.h" #include "btOverlappingPairCallback.h"
#include "../../LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btPoint3.h"
#include "LinearMath/btAlignedObjectArray.h"
class btDispatcher;
typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
struct btOverlapCallback struct btOverlapCallback
{ {
@@ -30,6 +33,7 @@ struct btOverlapCallback
{} {}
//return true for deletion of the pair //return true for deletion of the pair
virtual bool processOverlap(btBroadphasePair& pair) = 0; virtual bool processOverlap(btBroadphasePair& pair) = 0;
}; };
struct btOverlapFilterCallback struct btOverlapFilterCallback
@@ -40,38 +44,261 @@ struct btOverlapFilterCallback
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0; 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<int>(((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<unsigned int>(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<int> m_hashTable;
btAlignedObjectArray<int> m_next;
};
///btSortedOverlappingPairCache maintains the objects with overlapping AABB
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase ///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
class btOverlappingPairCache : public btBroadphaseInterface class btSortedOverlappingPairCache : public btOverlappingPairCache
{ {
protected: protected:
//avoid brute-force finding all the time //avoid brute-force finding all the time
btAlignedObjectArray<btBroadphasePair> m_overlappingPairArray; btBroadphasePairArray m_overlappingPairArray;
//during the dispatch, check that user doesn't destroy/create proxy //during the dispatch, check that user doesn't destroy/create proxy
bool m_blockedForChanges; 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 //if set, use the callback instead of the built in filter in needBroadphaseCollision
btOverlapFilterCallback* m_overlapFilterCallback; btOverlapFilterCallback* m_overlapFilterCallback;
public: public:
btOverlappingPairCache(); btSortedOverlappingPairCache();
virtual ~btOverlappingPairCache(); 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); 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 inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
@@ -85,9 +312,18 @@ class btOverlappingPairCache : public btBroadphaseInterface
return collides; return collides;
} }
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
virtual void refreshOverlappingPairs() =0;
btBroadphasePair* getOverlappingPairArrayPtr() btBroadphasePair* getOverlappingPairArrayPtr()
{ {
@@ -114,7 +350,88 @@ class btOverlappingPairCache : public btBroadphaseInterface
m_overlapFilterCallback = callback; 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 #endif //OVERLAPPING_PAIR_CACHE_H

View File

@@ -14,83 +14,84 @@ subject to the following restrictions:
*/ */
#include "btSimpleBroadphase.h" #include "btSimpleBroadphase.h"
#include <BulletCollision/BroadphaseCollision/btDispatcher.h> #include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include <BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h> #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h" #include "LinearMath/btTransform.h"
#include "LinearMath/btMatrix3x3.h" #include "LinearMath/btMatrix3x3.h"
#include <new> #include <new>
extern int gOverlappingPairs;
void btSimpleBroadphase::validate() void btSimpleBroadphase::validate()
{ {
for (int i=0;i<m_numProxies;i++) for (int i=0;i<m_numHandles;i++)
{ {
for (int j=i+1;j<m_numProxies;j++) for (int j=i+1;j<m_numHandles;j++)
{ {
assert(m_pProxies[i] != m_pProxies[j]); btAssert(&m_pHandles[i] != &m_pHandles[j]);
} }
} }
} }
btSimpleBroadphase::btSimpleBroadphase(int maxProxies) btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
:btOverlappingPairCache(), :m_pairCache(overlappingPairCache),
m_firstFreeProxy(0), m_ownsPairCache(false),
m_numProxies(0), m_invalidPair(0)
m_maxProxies(maxProxies)
{ {
m_proxies = new btSimpleBroadphaseProxy[maxProxies]; if (!overlappingPairCache)
m_freeProxies = new int[maxProxies];
m_pProxies = new btSimpleBroadphaseProxy*[maxProxies];
int i;
for (i=0;i<m_maxProxies;i++)
{ {
m_freeProxies[i] = i; void* mem = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
m_pairCache = new (mem)btHashedOverlappingPairCache();
m_ownsPairCache = true;
} }
// allocate handles buffer and put all handles on free list
m_pHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy)*maxProxies,16);
m_pHandles = new(m_pHandlesRawPtr) btSimpleBroadphaseProxy[maxProxies];
m_maxHandles = maxProxies;
m_numHandles = 0;
m_firstFreeHandle = 0;
{
for (int i = m_firstFreeHandle; i < maxProxies; i++)
{
m_pHandles[i].SetNextFree(i + 1);
m_pHandles[i].m_uniqueId = i+2;//any UID will do, we just avoid too trivial values (0,1) for debugging purposes
}
m_pHandles[maxProxies - 1].SetNextFree(0);
}
} }
btSimpleBroadphase::~btSimpleBroadphase() btSimpleBroadphase::~btSimpleBroadphase()
{ {
delete[] m_proxies; btAlignedFree(m_pHandlesRawPtr);
delete []m_freeProxies;
delete [] m_pProxies;
/*int i; if (m_ownsPairCache)
for (i=m_numProxies-1;i>=0;i--)
{ {
BP_Proxy* proxy = m_pProxies[i]; m_pairCache->~btOverlappingPairCache();
destroyProxy(proxy); 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 ;-) 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]; int newHandleIndex = allocHandle();
btSimpleBroadphaseProxy* proxy = new (&m_proxies[freeIndex])btSimpleBroadphaseProxy(min,max,shapeType,userPtr,collisionFilterGroup,collisionFilterMask); btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy);
m_firstFreeProxy++;
btSimpleBroadphaseProxy* proxy1 = &m_proxies[0];
int index = int(proxy - proxy1);
btAssert(index == freeIndex);
m_pProxies[m_numProxies] = proxy;
m_numProxies++;
//validate();
return proxy; 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<btSimpleBroadphaseProxy*>(proxyOrg); btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
btSimpleBroadphaseProxy* proxy1 = &m_proxies[0]; freeHandle(proxy0);
int index = int(proxy0 - proxy1); m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher);
btAssert (index < m_maxProxies);
m_freeProxies[--m_firstFreeProxy] = index;
removeOverlappingPairsContainingProxy(proxyOrg);
for (i=0;i<m_numProxies;i++)
{
if (m_pProxies[i] == proxyOrg)
{
m_pProxies[i] = m_pProxies[m_numProxies-1];
break;
}
}
m_numProxies--;
//validate(); //validate();
} }
void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax) void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
{ {
btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy); btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
sbp->m_min = aabbMin; sbp->m_min = aabbMin;
@@ -186,37 +172,129 @@ public:
} }
}; };
void btSimpleBroadphase::refreshOverlappingPairs() void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{ {
//first check for new overlapping pairs //first check for new overlapping pairs
int i,j; int i,j;
for (i=0;i<m_numProxies;i++) if (m_numHandles >= 0)
{ {
btBroadphaseProxy* proxy0 = m_pProxies[i];
for (j=i+1;j<m_numProxies;j++) for (i=0;i<m_numHandles;i++)
{ {
btBroadphaseProxy* proxy1 = m_pProxies[j]; btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i];
for (j=i+1;j<m_numHandles;j++)
{
btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j];
btAssert(proxy0 != proxy1);
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
if (aabbOverlap(p0,p1)) if (aabbOverlap(p0,p1))
{ {
if ( !findPair(proxy0,proxy1)) if ( !m_pairCache->findPair(proxy0,proxy1))
{ {
addOverlappingPair(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;i<overlappingPairArray.size();i++)
{
btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
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)
{
m_pairCache->cleanOverlappingPair(pair,dispatcher);
CheckOverlapCallback checkOverlap; // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
// m_overlappingPairArray.pop_back();
pair.m_pProxy0 = 0;
pair.m_pProxy1 = 0;
m_invalidPair++;
gOverlappingPairs--;
}
processAllOverlappingPairs(&checkOverlap); }
///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
}
}
} }
bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
return aabbOverlap(p0,p1);
}

View File

@@ -24,35 +24,69 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy
{ {
btVector3 m_min; btVector3 m_min;
btVector3 m_max; btVector3 m_max;
int m_nextFree;
// int m_handleId;
btSimpleBroadphaseProxy() {}; btSimpleBroadphaseProxy() {};
btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask) btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy)
:btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask), :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy),
m_min(minpt),m_max(maxpt) m_min(minpt),m_max(maxpt)
{ {
(void)shapeType; (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 ///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead.
class btSimpleBroadphase : public btOverlappingPairCache ///It is a brute force aabb culling broadphase based on O(n^2) aabb checks
class btSimpleBroadphase : public btBroadphaseInterface
{ {
protected: protected:
btSimpleBroadphaseProxy* m_proxies; int m_numHandles; // number of active handles
int* m_freeProxies; int m_maxHandles; // max number of handles
int m_firstFreeProxy;
btSimpleBroadphaseProxy** m_pProxies; btSimpleBroadphaseProxy* m_pHandles; // handles pool
int m_numProxies;
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) inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
@@ -67,26 +101,48 @@ protected:
protected: protected:
virtual void refreshOverlappingPairs();
public: public:
btSimpleBroadphase(int maxProxies=16384); btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0);
virtual ~btSimpleBroadphase(); virtual ~btSimpleBroadphase();
static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1); 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);
}
}; };

View File

@@ -5,56 +5,149 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src }
ADD_LIBRARY(LibBulletCollision ADD_LIBRARY(LibBulletCollision
BroadphaseCollision/btAxisSweep3.cpp BroadphaseCollision/btAxisSweep3.cpp
BroadphaseCollision/btAxisSweep3.h
BroadphaseCollision/btBroadphaseProxy.cpp BroadphaseCollision/btBroadphaseProxy.cpp
BroadphaseCollision/btBroadphaseProxy.h
BroadphaseCollision/btCollisionAlgorithm.cpp BroadphaseCollision/btCollisionAlgorithm.cpp
BroadphaseCollision/btCollisionAlgorithm.h
BroadphaseCollision/btDispatcher.cpp 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.cpp
BroadphaseCollision/btOverlappingPairCache.h
BroadphaseCollision/btOverlappingPairCallback.h
BroadphaseCollision/btQuantizedBvh.cpp
BroadphaseCollision/btQuantizedBvh.h
BroadphaseCollision/btSimpleBroadphase.cpp BroadphaseCollision/btSimpleBroadphase.cpp
BroadphaseCollision/btSimpleBroadphase.h
CollisionDispatch/btCollisionDispatcher.cpp CollisionDispatch/btCollisionDispatcher.cpp
CollisionDispatch/btCollisionDispatcher.h
CollisionDispatch/btCollisionObject.cpp CollisionDispatch/btCollisionObject.cpp
CollisionDispatch/btCollisionObject.h
CollisionDispatch/btCollisionWorld.cpp CollisionDispatch/btCollisionWorld.cpp
CollisionDispatch/btCollisionWorld.h
CollisionDispatch/btCompoundCollisionAlgorithm.cpp CollisionDispatch/btCompoundCollisionAlgorithm.cpp
CollisionDispatch/btCompoundCollisionAlgorithm.h
CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
CollisionDispatch/btDefaultCollisionConfiguration.cpp
CollisionDispatch/btDefaultCollisionConfiguration.h
CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
CollisionDispatch/btSphereSphereCollisionAlgorithm.h
CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
CollisionDispatch/btBoxBoxCollisionAlgorithm.h
CollisionDispatch/btBoxBoxDetector.cpp
CollisionDispatch/btBoxBoxDetector.h
CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
CollisionDispatch/btSphereBoxCollisionAlgorithm.h
CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
CollisionDispatch/btConvexConvexAlgorithm.cpp CollisionDispatch/btConvexConvexAlgorithm.cpp
CollisionDispatch/btConvexConvexAlgorithm.h
CollisionDispatch/btEmptyCollisionAlgorithm.cpp CollisionDispatch/btEmptyCollisionAlgorithm.cpp
CollisionDispatch/btEmptyCollisionAlgorithm.h
CollisionDispatch/btManifoldResult.cpp CollisionDispatch/btManifoldResult.cpp
CollisionDispatch/btManifoldResult.h
CollisionDispatch/btSimulationIslandManager.cpp CollisionDispatch/btSimulationIslandManager.cpp
CollisionDispatch/btSimulationIslandManager.h
CollisionDispatch/btUnionFind.cpp CollisionDispatch/btUnionFind.cpp
CollisionDispatch/btUnionFind.h
CollisionDispatch/SphereTriangleDetector.cpp
CollisionDispatch/SphereTriangleDetector.h
CollisionShapes/btBoxShape.cpp CollisionShapes/btBoxShape.cpp
CollisionShapes/btBoxShape.h
CollisionShapes/btBvhTriangleMeshShape.cpp CollisionShapes/btBvhTriangleMeshShape.cpp
CollisionShapes/btBvhTriangleMeshShape.h
CollisionShapes/btCapsuleShape.cpp
CollisionShapes/btCapsuleShape.h
CollisionShapes/btCollisionShape.cpp CollisionShapes/btCollisionShape.cpp
CollisionShapes/btCollisionShape.h
CollisionShapes/btCompoundShape.cpp CollisionShapes/btCompoundShape.cpp
CollisionShapes/btCompoundShape.h
CollisionShapes/btConcaveShape.cpp CollisionShapes/btConcaveShape.cpp
CollisionShapes/btConcaveShape.h
CollisionShapes/btConeShape.cpp CollisionShapes/btConeShape.cpp
CollisionShapes/btConeShape.h
CollisionShapes/btConvexHullShape.cpp CollisionShapes/btConvexHullShape.cpp
CollisionShapes/btConvexHullShape.h
CollisionShapes/btConvexShape.cpp CollisionShapes/btConvexShape.cpp
CollisionShapes/btConvexShape.h
CollisionShapes/btConvexInternalShape.cpp
CollisionShapes/btConvexInternalShape.h
CollisionShapes/btConvexTriangleMeshShape.cpp CollisionShapes/btConvexTriangleMeshShape.cpp
CollisionShapes/btConvexTriangleMeshShape.h
CollisionShapes/btCylinderShape.cpp CollisionShapes/btCylinderShape.cpp
CollisionShapes/btCylinderShape.h
CollisionShapes/btEmptyShape.cpp CollisionShapes/btEmptyShape.cpp
CollisionShapes/btEmptyShape.h
CollisionShapes/btHeightfieldTerrainShape.cpp
CollisionShapes/btHeightfieldTerrainShape.h
CollisionShapes/btMinkowskiSumShape.cpp CollisionShapes/btMinkowskiSumShape.cpp
CollisionShapes/btMinkowskiSumShape.h
CollisionShapes/btMaterial.h
CollisionShapes/btMultimaterialTriangleMeshShape.cpp
CollisionShapes/btMultimaterialTriangleMeshShape.h
CollisionShapes/btMultiSphereShape.cpp CollisionShapes/btMultiSphereShape.cpp
CollisionShapes/btMultiSphereShape.h
CollisionShapes/btOptimizedBvh.cpp CollisionShapes/btOptimizedBvh.cpp
CollisionShapes/btOptimizedBvh.h
CollisionShapes/btPolyhedralConvexShape.cpp CollisionShapes/btPolyhedralConvexShape.cpp
CollisionShapes/btPolyhedralConvexShape.h
CollisionShapes/btScaledBvhTriangleMeshShape.cpp
CollisionShapes/btScaledBvhTriangleMeshShape.h
CollisionShapes/btTetrahedronShape.cpp CollisionShapes/btTetrahedronShape.cpp
CollisionShapes/btTetrahedronShape.h
CollisionShapes/btSphereShape.cpp CollisionShapes/btSphereShape.cpp
CollisionShapes/btSphereShape.h
CollisionShapes/btShapeHull.h
CollisionShapes/btShapeHull.cpp
CollisionShapes/btStaticPlaneShape.cpp CollisionShapes/btStaticPlaneShape.cpp
CollisionShapes/btStaticPlaneShape.h
CollisionShapes/btStridingMeshInterface.cpp CollisionShapes/btStridingMeshInterface.cpp
CollisionShapes/btStridingMeshInterface.h
CollisionShapes/btTriangleCallback.cpp CollisionShapes/btTriangleCallback.cpp
CollisionShapes/btTriangleCallback.h
CollisionShapes/btTriangleBuffer.cpp CollisionShapes/btTriangleBuffer.cpp
CollisionShapes/btTriangleBuffer.h
CollisionShapes/btTriangleIndexVertexArray.cpp CollisionShapes/btTriangleIndexVertexArray.cpp
CollisionShapes/btTriangleIndexVertexArray.h
CollisionShapes/btTriangleIndexVertexMaterialArray.h
CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
CollisionShapes/btTriangleMesh.cpp CollisionShapes/btTriangleMesh.cpp
CollisionShapes/btTriangleMesh.h
CollisionShapes/btTriangleMeshShape.cpp CollisionShapes/btTriangleMeshShape.cpp
CollisionShapes/btTriangleMeshShape.h
CollisionShapes/btUniformScalingShape.cpp
CollisionShapes/btUniformScalingShape.h
NarrowPhaseCollision/btContinuousConvexCollision.cpp NarrowPhaseCollision/btContinuousConvexCollision.cpp
NarrowPhaseCollision/btContinuousConvexCollision.h
NarrowPhaseCollision/btGjkEpa.cpp NarrowPhaseCollision/btGjkEpa.cpp
NarrowPhaseCollision/btGjkEpa.h
NarrowPhaseCollision/btGjkEpa2.cpp
NarrowPhaseCollision/btGjkEpa2.h
NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
NarrowPhaseCollision/btConvexCast.cpp NarrowPhaseCollision/btConvexCast.cpp
NarrowPhaseCollision/btConvexCast.h
NarrowPhaseCollision/btGjkConvexCast.cpp NarrowPhaseCollision/btGjkConvexCast.cpp
NarrowPhaseCollision/btGjkConvexCast.h
NarrowPhaseCollision/btGjkPairDetector.cpp NarrowPhaseCollision/btGjkPairDetector.cpp
NarrowPhaseCollision/btGjkPairDetector.h
NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
NarrowPhaseCollision/btPersistentManifold.cpp NarrowPhaseCollision/btPersistentManifold.cpp
NarrowPhaseCollision/btPersistentManifold.h
NarrowPhaseCollision/btRaycastCallback.cpp NarrowPhaseCollision/btRaycastCallback.cpp
NarrowPhaseCollision/btRaycastCallback.h
NarrowPhaseCollision/btSubSimplexConvexCast.cpp NarrowPhaseCollision/btSubSimplexConvexCast.cpp
NarrowPhaseCollision/btSubSimplexConvexCast.h
NarrowPhaseCollision/btVoronoiSimplexSolver.cpp NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
NarrowPhaseCollision/btVoronoiSimplexSolver.h
) )

View File

@@ -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; (void)debugDraw;
@@ -41,9 +41,18 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res
btTransform sphereInTr = transformB.inverseTimes(transformA); btTransform sphereInTr = transformB.inverseTimes(transformA);
if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact)) if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact))
{
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); output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
} }
}
} }
@@ -53,6 +62,8 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res
// See also geometrictools.com // See also geometrictools.com
// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv // 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) { btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) {
btVector3 diff = p - from; btVector3 diff = p - from;
btVector3 v = to - from; btVector3 v = to - from;

View File

@@ -16,8 +16,8 @@ subject to the following restrictions:
#ifndef SPHERE_TRIANGLE_DETECTOR_H #ifndef SPHERE_TRIANGLE_DETECTOR_H
#define SPHERE_TRIANGLE_DETECTOR_H #define SPHERE_TRIANGLE_DETECTOR_H
#include "../NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
#include "../../LinearMath/btPoint3.h" #include "LinearMath/btPoint3.h"
class btSphereShape; class btSphereShape;
@@ -28,7 +28,7 @@ class btTriangleShape;
/// sphere-triangle to match the btDiscreteCollisionDetectorInterface /// sphere-triangle to match the btDiscreteCollisionDetectorInterface
struct SphereTriangleDetector : public 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); SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle);

View File

@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef COLLISION_CREATE_FUNC #ifndef COLLISION_CREATE_FUNC
#define COLLISION_CREATE_FUNC #define COLLISION_CREATE_FUNC
#include "../../LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray; typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
class btCollisionAlgorithm; class btCollisionAlgorithm;
class btCollisionObject; class btCollisionObject;

View File

@@ -19,69 +19,39 @@ subject to the following restrictions:
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" #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/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "LinearMath/btPoolAllocator.h"
#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
int gNumManifold = 0; int gNumManifold = 0;
#ifdef BT_DEBUG
#include <stdio.h> #include <stdio.h>
#endif
btCollisionDispatcher::btCollisionDispatcher(bool noDefaultAlgorithms): btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
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;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
{
for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
{
m_doubleDispatch[i][j] = m_emptyCreateFunc;
}
}
}
//if you want to not link with the default collision algorithms, you can
//define BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
//in your Bullet library build system
#ifndef BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
btCollisionDispatcher::btCollisionDispatcher ():
m_count(0), m_count(0),
m_useIslands(true) m_useIslands(true),
m_staticWarningReported(false),
m_collisionConfiguration(collisionConfiguration)
{ {
int i; int i;
setNearCallback(defaultNearCallback); setNearCallback(defaultNearCallback);
//default CreationFunctions, filling the m_doubleDispatch table m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
m_convexConvexCreateFunc = new btConvexConvexAlgorithm::CreateFunc;
m_convexConcaveCreateFunc = new btConvexConcaveCollisionAlgorithm::CreateFunc; m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
m_swappedConvexConcaveCreateFunc = new btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
m_compoundCreateFunc = new btCompoundCollisionAlgorithm::CreateFunc;
m_swappedCompoundCreateFunc = new btCompoundCollisionAlgorithm::SwappedCreateFunc;
m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc;
for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++) for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
{ {
for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++) for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
{ {
m_doubleDispatch[i][j] = internalFindCreateFunc(i,j); m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
assert(m_doubleDispatch[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) void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
{ {
@@ -99,12 +67,6 @@ void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int prox
btCollisionDispatcher::~btCollisionDispatcher() 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) btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1)
@@ -117,7 +79,18 @@ btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1)
btCollisionObject* body0 = (btCollisionObject*)b0; btCollisionObject* body0 = (btCollisionObject*)b0;
btCollisionObject* body1 = (btCollisionObject*)b1; 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); m_manifoldsPtr.push_back(manifold);
return manifold; return manifold;
@@ -137,13 +110,19 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
//printf("releaseManifold: gNumManifold %d\n",gNumManifold); //printf("releaseManifold: gNumManifold %d\n",gNumManifold);
clearManifold(manifold); clearManifold(manifold);
///todo: this can be improved a lot, linear search might be slow part! int findIndex = manifold->m_index1a;
int findIndex = m_manifoldsPtr.findLinearSearch(manifold); btAssert(findIndex < m_manifoldsPtr.size());
if (findIndex < m_manifoldsPtr.size())
{
m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
m_manifoldsPtr[findIndex]->m_index1a = findIndex;
m_manifoldsPtr.pop_back(); m_manifoldsPtr.pop_back();
delete manifold;
manifold->~btPersistentManifold();
if (m_persistentManifoldPoolAllocator->validPtr(manifold))
{
m_persistentManifoldPoolAllocator->freeMemory(manifold);
} else
{
btAlignedFree(manifold);
} }
} }
@@ -153,98 +132,18 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
{ {
#ifdef USE_DISPATCH_REGISTRY_ARRAY
btCollisionAlgorithmConstructionInfo ci; btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher = this;
ci.m_dispatcher1 = this;
ci.m_manifold = sharedManifold; ci.m_manifold = sharedManifold;
btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()] btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
->CreateCollisionAlgorithm(ci,body0,body1);
#else
btCollisionAlgorithm* algo = internalFindAlgorithm(body0,body1);
#endif //USE_DISPATCH_REGISTRY_ARRAY
return algo; 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) bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1)
{ {
@@ -264,12 +163,18 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO
bool needsCollision = true; bool needsCollision = true;
#ifdef BT_DEBUG
if (!m_staticWarningReported)
{
//broadphase filtering already deals with this //broadphase filtering already deals with this
if ((body0->isStaticObject() || body0->isKinematicObject()) && if ((body0->isStaticObject() || body0->isKinematicObject()) &&
(body1->isStaticObject() || body1->isKinematicObject())) (body1->isStaticObject() || body1->isKinematicObject()))
{ {
m_staticWarningReported = true;
printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
} }
}
#endif //BT_DEBUG
if ((!body0->isActive()) && (!body1->isActive())) if ((!body0->isActive()) && (!body1->isActive()))
needsCollision = false; needsCollision = false;
@@ -286,23 +191,25 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO
///this is useful for the collision dispatcher. ///this is useful for the collision dispatcher.
class btCollisionPairCallback : public btOverlapCallback class btCollisionPairCallback : public btOverlapCallback
{ {
btDispatcherInfo& m_dispatchInfo; const btDispatcherInfo& m_dispatchInfo;
btCollisionDispatcher* m_dispatcher; btCollisionDispatcher* m_dispatcher;
public: public:
btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
:m_dispatchInfo(dispatchInfo), :m_dispatchInfo(dispatchInfo),
m_dispatcher(dispatcher) m_dispatcher(dispatcher)
{ {
} }
btCollisionPairCallback& operator=(btCollisionPairCallback& other) /*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
{ {
m_dispatchInfo = other.m_dispatchInfo; m_dispatchInfo = other.m_dispatchInfo;
m_dispatcher = other.m_dispatcher; m_dispatcher = other.m_dispatcher;
return *this; return *this;
} }
*/
virtual ~btCollisionPairCallback() {} 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; //m_blockedForChanges = true;
btCollisionPairCallback collisionCallback(dispatchInfo,this); btCollisionPairCallback collisionCallback(dispatchInfo,this);
pairCache->processAllOverlappingPairs(&collisionCallback); pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
//m_blockedForChanges = false; //m_blockedForChanges = false;
@@ -332,7 +240,7 @@ void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pa
//by default, Bullet will use this near callback //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* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->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_t>(size), 16);
}
void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
{
if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
{
m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
} else
{
btAlignedFree(ptr);
}
}

View File

@@ -16,17 +16,18 @@ subject to the following restrictions:
#ifndef COLLISION__DISPATCHER_H #ifndef COLLISION__DISPATCHER_H
#define COLLISION__DISPATCHER_H #define COLLISION__DISPATCHER_H
#include "../BroadphaseCollision/btDispatcher.h" #include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "../NarrowPhaseCollision/btPersistentManifold.h" #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "../CollisionDispatch/btManifoldResult.h" #include "BulletCollision/CollisionDispatch/btManifoldResult.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "../../LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
class btIDebugDraw; class btIDebugDraw;
class btOverlappingPairCache; class btOverlappingPairCache;
class btPoolAllocator;
class btCollisionConfiguration;
#include "btCollisionCreateFunc.h" #include "btCollisionCreateFunc.h"
@@ -34,7 +35,7 @@ class btOverlappingPairCache;
class btCollisionDispatcher; class btCollisionDispatcher;
///user can override this nearcallback for collision filtering and more finegrained control over collision detection ///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. ///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
@@ -47,25 +48,21 @@ class btCollisionDispatcher : public btDispatcher
bool m_useIslands; bool m_useIslands;
bool m_staticWarningReported;
btManifoldResult m_defaultManifoldResult; btManifoldResult m_defaultManifoldResult;
btNearCallback m_nearCallback; btNearCallback m_nearCallback;
btPoolAllocator* m_collisionAlgorithmPoolAllocator;
btPoolAllocator* m_persistentManifoldPoolAllocator;
btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
btCollisionAlgorithmCreateFunc* internalFindCreateFunc(int proxyType0,int proxyType1);
//default CreationFunctions, filling the m_doubleDispatch table btCollisionConfiguration* m_collisionConfiguration;
btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
#ifndef USE_DISPATCH_REGISTRY_ARRAY
btCollisionAlgorithm* internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0);
#endif //USE_DISPATCH_REGISTRY_ARRAY
public: public:
@@ -92,11 +89,7 @@ public:
return m_manifoldsPtr[index]; return m_manifoldsPtr[index];
} }
///the default constructor creates/register default collision algorithms, for convex, compound and concave shape support btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration);
btCollisionDispatcher ();
///a special constructor that doesn't create/register the default collision algorithms
btCollisionDispatcher(bool noDefaultAlgorithms);
virtual ~btCollisionDispatcher(); virtual ~btCollisionDispatcher();
@@ -114,7 +107,7 @@ public:
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1); 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) void setNearCallback(btNearCallback nearCallback)
{ {
@@ -127,7 +120,26 @@ public:
} }
//by default, Bullet will use this near callback //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;
}
}; };

View File

@@ -13,18 +13,25 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
*/ */
#include "btCollisionObject.h" #include "btCollisionObject.h"
btCollisionObject::btCollisionObject() btCollisionObject::btCollisionObject()
: m_broadphaseHandle(0), : m_broadphaseHandle(0),
m_collisionShape(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_activationState1(1),
m_deactivationTime(btScalar(0.)), m_deactivationTime(btScalar(0.)),
m_friction(btScalar(0.5)),
m_restitution(btScalar(0.)),
m_userObjectPointer(0), m_userObjectPointer(0),
m_internalType(CO_COLLISION_OBJECT),
m_hitFraction(btScalar(1.)), m_hitFraction(btScalar(1.)),
m_ccdSweptSphereRadius(btScalar(0.)), m_ccdSweptSphereRadius(btScalar(0.)),
m_ccdSquareMotionThreshold(btScalar(0.)), m_ccdMotionThreshold(btScalar(0.)),
m_checkCollideWith(false) m_checkCollideWith(false)
{ {
@@ -55,3 +62,4 @@ void btCollisionObject::activate(bool forceActivation)
} }

View File

@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef COLLISION_OBJECT_H #ifndef COLLISION_OBJECT_H
#define COLLISION_OBJECT_H #define COLLISION_OBJECT_H
#include "../../LinearMath/btTransform.h" #include "LinearMath/btTransform.h"
//island management, m_activationState1 //island management, m_activationState1
#define ACTIVE_TAG 1 #define ACTIVE_TAG 1
@@ -27,7 +27,8 @@ subject to the following restrictions:
struct btBroadphaseProxy; struct btBroadphaseProxy;
class btCollisionShape; class btCollisionShape;
#include "../../LinearMath/btMotionState.h" #include "LinearMath/btMotionState.h"
#include "LinearMath/btAlignedAllocator.h"
@@ -51,6 +52,11 @@ protected:
btBroadphaseProxy* m_broadphaseHandle; btBroadphaseProxy* m_broadphaseHandle;
btCollisionShape* m_collisionShape; 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; int m_collisionFlags;
int m_islandTag1; int m_islandTag1;
@@ -65,8 +71,9 @@ protected:
///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
void* m_userObjectPointer; void* m_userObjectPointer;
///m_internalOwner is reserved to point to Bullet's btRigidBody. Don't use this, use m_userObjectPointer instead. ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody etc.
void* m_internalOwner; ///do not assign your own m_internalType unless you write a new dynamics object class.
int m_internalType;
///time of impact calculation ///time of impact calculation
btScalar m_hitFraction; btScalar m_hitFraction;
@@ -74,21 +81,23 @@ protected:
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
btScalar m_ccdSweptSphereRadius; btScalar m_ccdSweptSphereRadius;
/// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
btScalar m_ccdSquareMotionThreshold; btScalar m_ccdMotionThreshold;
/// If some object should have elaborate collision filtering by sub-classes /// If some object should have elaborate collision filtering by sub-classes
bool m_checkCollideWith; bool m_checkCollideWith;
char m_pad[7]; char m_pad[7];
virtual bool checkCollideWithOverride(btCollisionObject* co) virtual bool checkCollideWithOverride(btCollisionObject* /* co */)
{ {
return true; return true;
} }
public: public:
BT_DECLARE_ALIGNED_ALLOCATOR();
enum CollisionFlags enum CollisionFlags
{ {
CF_STATIC_OBJECT= 1, CF_STATIC_OBJECT= 1,
@@ -97,29 +106,35 @@ public:
CF_CUSTOM_MATERIAL_CALLBACK = 8//this allows per-triangle material (friction/restitution) 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 ///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); 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; return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
} }
inline bool isKinematicObject() const SIMD_FORCE_INLINE bool isKinematicObject() const
{ {
return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0; 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 ; 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; return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0;
} }
@@ -128,24 +143,39 @@ public:
virtual ~btCollisionObject(); virtual ~btCollisionObject();
void setCollisionShape(btCollisionShape* collisionShape) virtual void setCollisionShape(btCollisionShape* collisionShape)
{
m_collisionShape = collisionShape;
m_rootCollisionShape = collisionShape;
}
SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
{
return m_collisionShape;
}
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; m_collisionShape = collisionShape;
} }
const btCollisionShape* getCollisionShape() const
{
return m_collisionShape;
}
btCollisionShape* getCollisionShape()
{
return m_collisionShape;
}
int getActivationState() const { return m_activationState1;} int getActivationState() const { return m_activationState1;}
void setActivationState(int newState); void setActivationState(int newState);
@@ -186,14 +216,9 @@ public:
} }
///reserved for Bullet internal usage ///reserved for Bullet internal usage
void* getInternalOwner() int getInternalType() const
{ {
return m_internalOwner; return m_internalType;
}
const void* getInternalOwner() const
{
return m_internalOwner;
} }
btTransform& getWorldTransform() btTransform& getWorldTransform()
@@ -243,6 +268,15 @@ public:
m_interpolationWorldTransform = trans; m_interpolationWorldTransform = trans;
} }
void setInterpolationLinearVelocity(const btVector3& linvel)
{
m_interpolationLinearVelocity = linvel;
}
void setInterpolationAngularVelocity(const btVector3& angvel)
{
m_interpolationAngularVelocity = angvel;
}
const btVector3& getInterpolationLinearVelocity() const const btVector3& getInterpolationLinearVelocity() const
{ {
@@ -307,16 +341,22 @@ public:
m_ccdSweptSphereRadius = radius; m_ccdSweptSphereRadius = radius;
} }
btScalar getCcdMotionThreshold() const
{
return m_ccdMotionThreshold;
}
btScalar getCcdSquareMotionThreshold() const 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 ///users can point to their objects, userPointer is not used by Bullet
@@ -331,6 +371,7 @@ public:
m_userObjectPointer = userPointer; m_userObjectPointer = userPointer;
} }
inline bool checkCollideWith(btCollisionObject* co) inline bool checkCollideWith(btCollisionObject* co)
{ {
if (m_checkCollideWith) if (m_checkCollideWith)
@@ -338,9 +379,6 @@ public:
return true; return true;
} }
};
}
;
#endif //COLLISION_OBJECT_H #endif //COLLISION_OBJECT_H

View File

@@ -18,37 +18,39 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h" #include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting #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/NarrowPhaseCollision/btRaycastCallback.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "LinearMath/btAabbUtil2.h" #include "LinearMath/btAabbUtil2.h"
#include "LinearMath/btQuickprof.h" #include "LinearMath/btQuickprof.h"
#include "LinearMath/btStackAlloc.h" #include "LinearMath/btStackAlloc.h"
//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor) //When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.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_dispatcher1(dispatcher),
m_broadphasePairCache(pairCache), m_broadphasePairCache(pairCache),
m_ownsDispatcher(false), m_debugDrawer(0)
m_ownsBroadphasePairCache(false)
{ {
m_stackAlloc = new btStackAlloc(stackSize); m_stackAlloc = collisionConfiguration->getStackAllocator();
m_dispatchInfo.m_stackAllocator = m_stackAlloc; m_dispatchInfo.m_stackAllocator = m_stackAlloc;
} }
btCollisionWorld::~btCollisionWorld() btCollisionWorld::~btCollisionWorld()
{ {
m_stackAlloc->destroy();
delete m_stackAlloc;
//clean up remaining objects //clean up remaining objects
int i; int i;
@@ -62,15 +64,11 @@ btCollisionWorld::~btCollisionWorld()
// //
// only clear the cached algorithms // only clear the cached algorithms
// //
getBroadphase()->cleanProxyFromPairs(bp); getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
getBroadphase()->destroyProxy(bp); getBroadphase()->destroyProxy(bp,m_dispatcher1);
} }
} }
if (m_ownsDispatcher)
delete m_dispatcher1;
if (m_ownsBroadphasePairCache)
delete m_broadphasePairCache;
} }
@@ -105,7 +103,8 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho
type, type,
collisionObject, collisionObject,
collisionFilterGroup, collisionFilterGroup,
collisionFilterMask collisionFilterMask,
m_dispatcher1,0
)) ; )) ;
@@ -114,41 +113,79 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho
} }
void btCollisionWorld::updateAabbs()
{
BT_PROFILE("updateAabbs");
btTransform predictedTrans;
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
//only update aabb of active objects
if (colObj->isActive())
{
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() void btCollisionWorld::performDiscreteCollisionDetection()
{ {
BT_PROFILE("performDiscreteCollisionDetection");
btDispatcherInfo& dispatchInfo = getDispatchInfo(); btDispatcherInfo& dispatchInfo = getDispatchInfo();
BEGIN_PROFILE("perform Broadphase Collision Detection"); updateAabbs();
//update aabb (of all moved objects)
btVector3 aabbMin,aabbMax;
for (int i=0;i<m_collisionObjects.size();i++)
{ {
m_collisionObjects[i]->getCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax); BT_PROFILE("calculateOverlappingPairs");
m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax); m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
} }
m_broadphasePairCache->refreshOverlappingPairs();
END_PROFILE("perform Broadphase Collision Detection");
BEGIN_PROFILE("performDiscreteCollisionDetection");
btDispatcher* dispatcher = getDispatcher(); btDispatcher* dispatcher = getDispatcher();
{
BT_PROFILE("dispatchAllCollisionPairs");
if (dispatcher) if (dispatcher)
dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache,dispatchInfo); dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
}
END_PROFILE("performDiscreteCollisionDetection");
} }
void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
{ {
@@ -163,8 +200,8 @@ void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
// //
// only clear the cached algorithms // only clear the cached algorithms
// //
getBroadphase()->cleanProxyFromPairs(bp); getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
getBroadphase()->destroyProxy(bp); getBroadphase()->destroyProxy(bp,m_dispatcher1);
collisionObject->setBroadphaseHandle(0); collisionObject->setBroadphaseHandle(0);
} }
} }
@@ -181,51 +218,40 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
btCollisionObject* collisionObject, btCollisionObject* collisionObject,
const btCollisionShape* collisionShape, const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform, const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback, RayResultCallback& resultCallback)
short int collisionFilterMask,
bool faceNormal)
{ {
btSphereShape pointShape(btScalar(0.0)); btSphereShape pointShape(btScalar(0.0));
pointShape.setMargin(0.f); pointShape.setMargin(0.f);
const btConvexShape* castShape = &pointShape;
objectQuerySingle(&pointShape,rayFromTrans,rayToTrans,
collisionObject,
collisionShape,
colObjWorldTransform,
resultCallback,collisionFilterMask,faceNormal);
}
void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback,
short int collisionFilterMask,
bool faceNormal)
{
if (collisionShape->isConvex()) if (collisionShape->isConvex())
{ {
btConvexCast::CastResult castResult; btConvexCast::CastResult castResult;
castResult.m_fraction = btScalar(1.);//?? castResult.m_fraction = resultCallback.m_closestHitFraction;
btConvexShape* convexShape = (btConvexShape*) collisionShape; btConvexShape* convexShape = (btConvexShape*) collisionShape;
btVoronoiSimplexSolver simplexSolver; btVoronoiSimplexSolver simplexSolver;
#define USE_SUBSIMPLEX_CONVEX_CAST 1
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver); btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
//GjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); #else
//ContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
//btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
#endif //#USE_SUBSIMPLEX_CONVEX_CAST
if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
{ {
//add hit //add hit
if (castResult.m_normal.length2() > btScalar(0.0001)) if (castResult.m_normal.length2() > btScalar(0.0001))
{ {
castResult.m_normal.normalize();
if (castResult.m_fraction < resultCallback.m_closestHitFraction) 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 btCollisionWorld::LocalRayResult localRayResult
( (
collisionObject, collisionObject,
@@ -234,18 +260,63 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
castResult.m_fraction castResult.m_fraction
); );
resultCallback.AddSingleResult(localRayResult); bool normalInWorldSpace = true;
resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
} }
} }
} }
} } else {
else
{
if (collisionShape->isConcave()) 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; btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape;
btTransform worldTocollisionObject = colObjWorldTransform.inverse(); btTransform worldTocollisionObject = colObjWorldTransform.inverse();
@@ -261,9 +332,9 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
btCollisionObject* m_collisionObject; btCollisionObject* m_collisionObject;
btTriangleMeshShape* m_triangleMesh; btTriangleMeshShape* m_triangleMesh;
BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,bool faceNormal, BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
btTriangleRaycastCallback(from,to,faceNormal), btTriangleRaycastCallback(from,to),
m_resultCallback(resultCallback), m_resultCallback(resultCallback),
m_collisionObject(collisionObject), m_collisionObject(collisionObject),
m_triangleMesh(triangleMesh) m_triangleMesh(triangleMesh)
@@ -276,7 +347,6 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
btCollisionWorld::LocalShapeInfo shapeInfo; btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = partId; shapeInfo.m_shapePart = partId;
shapeInfo.m_triangleIndex = triangleIndex; shapeInfo.m_triangleIndex = triangleIndex;
shapeInfo.m_triangleShape = m_triangleMesh;
btCollisionWorld::LocalRayResult rayResult btCollisionWorld::LocalRayResult rayResult
(m_collisionObject, (m_collisionObject,
@@ -284,7 +354,8 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
hitNormalLocal, hitNormalLocal,
hitFraction); hitFraction);
return m_resultCallback->AddSingleResult(rayResult); bool normalInWorldSpace = false;
return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
} }
@@ -292,7 +363,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
}; };
BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,faceNormal,&resultCallback,collisionObject,triangleMesh); BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh);
rcb.m_hitFraction = resultCallback.m_closestHitFraction; rcb.m_hitFraction = resultCallback.m_closestHitFraction;
btVector3 rayAabbMinLocal = rayFromLocal; btVector3 rayAabbMinLocal = rayFromLocal;
@@ -301,9 +372,8 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
rayAabbMaxLocal.setMax(rayToLocal); rayAabbMaxLocal.setMax(rayToLocal);
triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
}
} else } else {
{
//todo: use AABB tree or other BVH acceleration structure! //todo: use AABB tree or other BVH acceleration structure!
if (collisionShape->isCompound()) if (collisionShape->isCompound())
{ {
@@ -314,21 +384,219 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
btTransform childTrans = compoundShape->getChildTransform(i); btTransform childTrans = compoundShape->getChildTransform(i);
const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
btTransform childWorldTrans = colObjWorldTransform * childTrans; btTransform childWorldTrans = colObjWorldTransform * childTrans;
objectQuerySingle(castShape, rayFromTrans,rayToTrans, // replace collision shape so that callback can determine the triangle
btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape();
collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape);
rayTestSingle(rayFromTrans,rayToTrans,
collisionObject, collisionObject,
childCollisionShape, childCollisionShape,
childWorldTrans, childWorldTrans,
resultCallback, collisionFilterMask, faceNormal); resultCallback);
// restore
collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
} }
} }
} }
} }
} }
void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask, bool faceNormal) void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
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))
{
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
{
castResult.m_normal.normalize();
btCollisionWorld::LocalConvexResult localConvexResult
(
collisionObject,
0,
castResult.m_normal,
castResult.m_hitPoint,
castResult.m_fraction
);
bool normalInWorldSpace = true;
resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
}
}
}
} else {
if (collisionShape->isConcave())
{
if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
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 = 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<const btCompoundShape*>(collisionShape);
int i=0;
for (i=0;i<compoundShape->getNumChildShapes();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);
objectQuerySingle(castShape, convexFromTrans,convexToTrans,
collisionObject,
childCollisionShape,
childWorldTrans,
resultCallback, allowedPenetration);
// restore
collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
}
}
}
}
}
void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
{ {
@@ -344,29 +612,72 @@ void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& r
int i; int i;
for (i=0;i<m_collisionObjects.size();i++) for (i=0;i<m_collisionObjects.size();i++)
{ {
///terminate further ray tests, once the closestHitFraction reached zero
if (resultCallback.m_closestHitFraction == btScalar(0.f))
break;
btCollisionObject* collisionObject= m_collisionObjects[i]; btCollisionObject* collisionObject= m_collisionObjects[i];
//only perform raycast if filterMask matches //only perform raycast if filterMask matches
if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
btVector3 collisionObjectAabbMin,collisionObjectAabbMax; btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing btScalar hitLambda = resultCallback.m_closestHitFraction;
btVector3 hitNormal; btVector3 hitNormal;
if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
{
// before testing this object, verify that it is not filtered out
if (resultCallback.NeedRayCast(collisionObject))
{ {
rayTestSingle(rayFromTrans,rayToTrans, rayTestSingle(rayFromTrans,rayToTrans,
collisionObject, collisionObject,
collisionObject->getCollisionShape(), collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(), collisionObject->getWorldTransform(),
resultCallback, resultCallback);
collisionFilterMask,
faceNormal);
} }
} }
}
}
void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback) const
{
btTransform convexFromTrans,convexToTrans;
convexFromTrans = convexFromWorld;
convexToTrans = convexToWorld;
btVector3 castShapeAabbMin, castShapeAabbMax;
/* Compute AABB that encompasses angular movement */
{
btVector3 linVel, angVel;
btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
btTransform R;
R.setIdentity ();
R.setRotation (convexFromTrans.getRotation());
castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
}
/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
// do a ray-shape query using convexCaster (CCD)
int i;
for (i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* collisionObject= m_collisionObjects[i];
//only perform raycast if filterMask matches
if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
btVector3 hitNormal;
if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
{
objectQuerySingle(castShape, convexFromTrans,convexToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback,
getDispatchInfo().m_allowedCcdPenetration);
}
} }
} }

View File

@@ -68,12 +68,12 @@ class btStackAlloc;
class btCollisionShape; class btCollisionShape;
class btConvexShape; class btConvexShape;
class btBroadphaseInterface; class btBroadphaseInterface;
#include "../../LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
#include "../../LinearMath/btTransform.h" #include "LinearMath/btTransform.h"
#include "btCollisionObject.h" #include "btCollisionObject.h"
#include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray #include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray
#include "../BroadphaseCollision/btOverlappingPairCache.h" #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "../../LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
///CollisionWorld is interface and container for the collision detection ///CollisionWorld is interface and container for the collision detection
class btCollisionWorld class btCollisionWorld
@@ -90,18 +90,22 @@ protected:
btStackAlloc* m_stackAlloc; btStackAlloc* m_stackAlloc;
btOverlappingPairCache* m_broadphasePairCache; btBroadphaseInterface* m_broadphasePairCache;
btIDebugDraw* m_debugDrawer;
bool m_ownsDispatcher;
bool m_ownsBroadphasePairCache;
public: public:
//this constructor doesn't own the dispatcher and paircache/broadphase //this constructor doesn't own the dispatcher and paircache/broadphase
btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize = 2*1024*1024); btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
virtual ~btCollisionWorld(); virtual ~btCollisionWorld();
void setBroadphase(btBroadphaseInterface* pairCache)
{
m_broadphasePairCache = pairCache;
}
btBroadphaseInterface* getBroadphase() btBroadphaseInterface* getBroadphase()
{ {
@@ -110,7 +114,7 @@ public:
btOverlappingPairCache* getPairCache() btOverlappingPairCache* getPairCache()
{ {
return m_broadphasePairCache; return m_broadphasePairCache->getOverlappingPairCache();
} }
@@ -119,14 +123,32 @@ public:
return m_dispatcher1; return m_dispatcher1;
} }
const btDispatcher* getDispatcher() const
{
return m_dispatcher1;
}
virtual void updateAabbs();
virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
{
m_debugDrawer = debugDrawer;
}
virtual btIDebugDraw* getDebugDrawer()
{
return m_debugDrawer;
}
///LocalShapeInfo gives extra information for complex shapes ///LocalShapeInfo gives extra information for complex shapes
///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart ///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
struct LocalShapeInfo struct LocalShapeInfo
{ {
int m_shapePart; int m_shapePart;
int m_triangleIndex; int m_triangleIndex;
// needed in case of compound shape
const btCollisionShape* m_triangleShape; //const btCollisionShape* m_shapeTemp;
//const btTransform* m_shapeLocalTransform; //const btTransform* m_shapeLocalTransform;
}; };
@@ -153,32 +175,43 @@ public:
///RayResultCallback is used to report new raycast results ///RayResultCallback is used to report new raycast results
struct RayResultCallback struct RayResultCallback
{ {
btScalar m_closestHitFraction;
btCollisionObject* m_collisionObject;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
virtual ~RayResultCallback() virtual ~RayResultCallback()
{ {
} }
btScalar m_closestHitFraction; bool hasHit() const
bool HasHit()
{ {
return (m_closestHitFraction < btScalar(1.)); return (m_collisionObject != 0);
} }
RayResultCallback() RayResultCallback()
:m_closestHitFraction(btScalar(1.)) :m_closestHitFraction(btScalar(1.)),
m_collisionObject(0),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter)
{ {
} }
virtual bool NeedRayCast(btCollisionObject* object)
virtual bool needsCollision(btBroadphaseProxy* proxy0) const
{ {
return true; bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
return collides;
} }
virtual btScalar AddSingleResult(LocalRayResult& rayResult) = 0;
virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0;
}; };
struct ClosestRayResultCallback : public RayResultCallback struct ClosestRayResultCallback : public RayResultCallback
{ {
ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld) ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
:m_rayFromWorld(rayFromWorld), :m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld), m_rayToWorld(rayToWorld)
m_collisionObject(0)
{ {
} }
@@ -187,24 +220,121 @@ public:
btVector3 m_hitNormalWorld; btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld; btVector3 m_hitPointWorld;
btCollisionObject* m_collisionObject;
virtual btScalar AddSingleResult(LocalRayResult& rayResult) virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
{ {
//caller already does the filter on the m_closestHitFraction
//caller already does the filter on the m_closestHitFraction btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
assert(rayResult.m_hitFraction <= m_closestHitFraction);
m_closestHitFraction = rayResult.m_hitFraction; m_closestHitFraction = rayResult.m_hitFraction;
m_collisionObject = rayResult.m_collisionObject; m_collisionObject = rayResult.m_collisionObject;
if (normalInWorldSpace)
{
m_hitNormalWorld = rayResult.m_hitNormalLocal;
} else
{
///need to transform normal into worldspace
m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
}
m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
return rayResult.m_hitFraction; return rayResult.m_hitFraction;
} }
}; };
struct LocalConvexResult
{
LocalConvexResult(btCollisionObject* hitCollisionObject,
LocalShapeInfo* localShapeInfo,
const btVector3& hitNormalLocal,
const btVector3& hitPointLocal,
btScalar hitFraction
)
:m_hitCollisionObject(hitCollisionObject),
m_localShapeInfo(localShapeInfo),
m_hitNormalLocal(hitNormalLocal),
m_hitPointLocal(hitPointLocal),
m_hitFraction(hitFraction)
{
}
btCollisionObject* m_hitCollisionObject;
LocalShapeInfo* m_localShapeInfo;
btVector3 m_hitNormalLocal;
btVector3 m_hitPointLocal;
btScalar m_hitFraction;
};
///RayResultCallback is used to report new raycast results
struct ConvexResultCallback
{
btScalar m_closestHitFraction;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
ConvexResultCallback()
:m_closestHitFraction(btScalar(1.)),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter)
{
}
virtual ~ConvexResultCallback()
{
}
bool hasHit() const
{
return (m_closestHitFraction < btScalar(1.));
}
virtual bool needsCollision(btBroadphaseProxy* proxy0) const
{
bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
return collides;
}
virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0;
};
struct ClosestConvexResultCallback : public ConvexResultCallback
{
ClosestConvexResultCallback(const btVector3& convexFromWorld,const btVector3& convexToWorld)
:m_convexFromWorld(convexFromWorld),
m_convexToWorld(convexToWorld),
m_hitCollisionObject(0)
{
}
btVector3 m_convexFromWorld;//used to calculate hitPointWorld from hitFraction
btVector3 m_convexToWorld;
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
btCollisionObject* m_hitCollisionObject;
virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace)
{
//caller already does the filter on the m_closestHitFraction
btAssert(convexResult.m_hitFraction <= m_closestHitFraction);
m_closestHitFraction = convexResult.m_hitFraction;
m_hitCollisionObject = convexResult.m_hitCollisionObject;
if (normalInWorldSpace)
{
m_hitNormalWorld = convexResult.m_hitNormalLocal;
} else
{
///need to transform normal into worldspace
m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
}
m_hitPointWorld = convexResult.m_hitPointLocal;
return convexResult.m_hitFraction;
}
};
int getNumCollisionObjects() const int getNumCollisionObjects() const
{ {
@@ -213,7 +343,12 @@ public:
/// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
/// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1, bool faceNormal=false); void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
// convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback
// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback.
void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback) const;
/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
/// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
@@ -222,20 +357,16 @@ public:
btCollisionObject* collisionObject, btCollisionObject* collisionObject,
const btCollisionShape* collisionShape, const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform, const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback, RayResultCallback& resultCallback);
short int collisionFilterMask=-1,
bool faceNormal=false);
/// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest. /// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest.
static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans, static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans,
btCollisionObject* collisionObject, btCollisionObject* collisionObject,
const btCollisionShape* collisionShape, const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform, const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback, ConvexResultCallback& resultCallback, btScalar allowedPenetration);
short int collisionFilterMask=-1,
bool faceNormal=false);
void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1); void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter);
btCollisionObjectArray& getCollisionObjectArray() btCollisionObjectArray& getCollisionObjectArray()
{ {
@@ -257,6 +388,11 @@ public:
return m_dispatchInfo; return m_dispatchInfo;
} }
const btDispatcherInfo& getDispatchInfo() const
{
return m_dispatchInfo;
}
}; };

View File

@@ -16,11 +16,17 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" #include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
#include "LinearMath/btIDebugDraw.h"
#include "LinearMath/btAabbUtil2.h"
btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
:m_isSwapped(isSwapped) :btCollisionAlgorithm(ci),
m_isSwapped(isSwapped),
m_sharedManifold(ci.m_manifold)
{ {
m_ownsManifold = false;
btCollisionObject* colObj = m_isSwapped? body1 : body0; btCollisionObject* colObj = m_isSwapped? body1 : body0;
btCollisionObject* otherObj = m_isSwapped? body0 : body1; btCollisionObject* otherObj = m_isSwapped? body0 : body1;
assert (colObj->getCollisionShape()->isCompound()); assert (colObj->getCollisionShape()->isCompound());
@@ -32,11 +38,17 @@ btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlg
m_childCollisionAlgorithms.resize(numChildren); m_childCollisionAlgorithms.resize(numChildren);
for (i=0;i<numChildren;i++) for (i=0;i<numChildren;i++)
{ {
if (compoundShape->getDynamicAabbTree())
{
m_childCollisionAlgorithms[i] = 0;
} else
{
btCollisionShape* tmpShape = colObj->getCollisionShape();
btCollisionShape* childShape = compoundShape->getChildShape(i); btCollisionShape* childShape = compoundShape->getChildShape(i);
btCollisionShape* orgShape = colObj->getCollisionShape(); colObj->internalSetTemporaryCollisionShape( childShape );
colObj->setCollisionShape( childShape ); m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj,m_sharedManifold);
m_childCollisionAlgorithms[i] = ci.m_dispatcher->findAlgorithm(colObj,otherObj); colObj->internalSetTemporaryCollisionShape( tmpShape );
colObj->setCollisionShape( orgShape ); }
} }
} }
@@ -47,10 +59,109 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
int i; int i;
for (i=0;i<numChildren;i++) for (i=0;i<numChildren;i++)
{ {
delete m_childCollisionAlgorithms[i]; if (m_childCollisionAlgorithms[i])
{
m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
}
} }
} }
struct btCompoundLeafCallback : btDbvt::ICollide
{
public:
btCollisionObject* m_compoundColObj;
btCollisionObject* m_otherObj;
btDispatcher* m_dispatcher;
const btDispatcherInfo& m_dispatchInfo;
btManifoldResult* m_resultOut;
btCollisionAlgorithm** m_childCollisionAlgorithms;
btPersistentManifold* m_sharedManifold;
btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold)
:m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
m_childCollisionAlgorithms(childCollisionAlgorithms),
m_sharedManifold(sharedManifold)
{
}
void ProcessChildShape(btCollisionShape* childShape,int index)
{
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
//backup
btTransform orgTrans = m_compoundColObj->getWorldTransform();
btTransform orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(index);
btTransform newChildWorldTrans = orgTrans*childTrans ;
//perform an AABB check first
btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1);
if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
m_compoundColObj->setWorldTransform( newChildWorldTrans);
m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans);
//the contactpoint is still projected back using the original inverted worldtrans
btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape();
m_compoundColObj->internalSetTemporaryCollisionShape( childShape );
if (!m_childCollisionAlgorithms[index])
m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold);
m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut);
if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
btVector3 worldAabbMin,worldAabbMax;
m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
}
//revert back transform
m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape);
m_compoundColObj->setWorldTransform( orgTrans );
m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans);
}
}
void Process(const btDbvtNode* leaf)
{
int index = leaf->dataAsInt;
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
btCollisionShape* childShape = compoundShape->getChildShape(index);
if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
btVector3 worldAabbMin,worldAabbMax;
btTransform orgTrans = m_compoundColObj->getWorldTransform();
btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
}
ProcessChildShape(childShape,index);
}
};
void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{ {
btCollisionObject* colObj = m_isSwapped? body1 : body0; btCollisionObject* colObj = m_isSwapped? body1 : body0;
@@ -59,33 +170,69 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt
assert (colObj->getCollisionShape()->isCompound()); assert (colObj->getCollisionShape()->isCompound());
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape()); btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
//We will use the OptimizedBVH, AABB tree to cull potential child-overlaps btDbvt* tree = compoundShape->getDynamicAabbTree();
//If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals //use a dynamic aabb tree to cull potential child-overlaps
//given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means: btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
//determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
//then use each overlapping node AABB against Tree0
//and vise versa.
if (tree)
{
btVector3 localAabbMin,localAabbMax;
btTransform otherInCompoundSpace;
otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform();
otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
//process all children, that overlap with the given AABB bounds
tree->collideTV(tree->m_root,bounds,callback);
} else
{
//iterate over all children, perform an AABB check inside ProcessChildShape
int numChildren = m_childCollisionAlgorithms.size(); int numChildren = m_childCollisionAlgorithms.size();
int i; int i;
for (i=0;i<numChildren;i++) for (i=0;i<numChildren;i++)
{ {
//temporarily exchange parent btCollisionShape with childShape, and recurse callback.ProcessChildShape(compoundShape->getChildShape(i),i);
}
}
{
//iterate over all children, perform an AABB check inside ProcessChildShape
int numChildren = m_childCollisionAlgorithms.size();
int i;
btManifoldArray manifoldArray;
for (i=0;i<numChildren;i++)
{
if (m_childCollisionAlgorithms[i])
{
btCollisionShape* childShape = compoundShape->getChildShape(i); btCollisionShape* childShape = compoundShape->getChildShape(i);
//if not longer overlapping, remove the algorithm
//backup
btTransform orgTrans = colObj->getWorldTransform(); btTransform orgTrans = colObj->getWorldTransform();
btCollisionShape* orgShape = colObj->getCollisionShape(); btTransform orgInterpolationTrans = colObj->getInterpolationWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(i); const btTransform& childTrans = compoundShape->getChildTransform(i);
//btTransform newChildWorldTrans = orgTrans*childTrans ; btTransform newChildWorldTrans = orgTrans*childTrans ;
colObj->setWorldTransform( orgTrans*childTrans );
//the contactpoint is still projected back using the original inverted worldtrans //perform an AABB check first
colObj->setCollisionShape( childShape ); btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
m_childCollisionAlgorithms[i]->processCollision(colObj,otherObj,dispatchInfo,resultOut); childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
//revert back otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1);
colObj->setCollisionShape( orgShape);
colObj->setWorldTransform( orgTrans ); if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
m_childCollisionAlgorithms[i] = 0;
}
}
}
} }
} }
@@ -117,20 +264,20 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
//backup //backup
btTransform orgTrans = colObj->getWorldTransform(); btTransform orgTrans = colObj->getWorldTransform();
btCollisionShape* orgShape = colObj->getCollisionShape();
const btTransform& childTrans = compoundShape->getChildTransform(i); const btTransform& childTrans = compoundShape->getChildTransform(i);
//btTransform newChildWorldTrans = orgTrans*childTrans ; //btTransform newChildWorldTrans = orgTrans*childTrans ;
colObj->setWorldTransform( orgTrans*childTrans ); colObj->setWorldTransform( orgTrans*childTrans );
colObj->setCollisionShape( childShape ); btCollisionShape* tmpShape = colObj->getCollisionShape();
colObj->internalSetTemporaryCollisionShape( childShape );
btScalar frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut); btScalar frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
if (frac<hitFraction) if (frac<hitFraction)
{ {
hitFraction = frac; hitFraction = frac;
} }
//revert back //revert back
colObj->setCollisionShape( orgShape); colObj->internalSetTemporaryCollisionShape( tmpShape);
colObj->setWorldTransform( orgTrans); colObj->setWorldTransform( orgTrans);
} }
return hitFraction; return hitFraction;

View File

@@ -16,23 +16,26 @@ subject to the following restrictions:
#ifndef COMPOUND_COLLISION_ALGORITHM_H #ifndef COMPOUND_COLLISION_ALGORITHM_H
#define COMPOUND_COLLISION_ALGORITHM_H #define COMPOUND_COLLISION_ALGORITHM_H
#include "../BroadphaseCollision/btCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "../BroadphaseCollision/btDispatcher.h" #include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "../BroadphaseCollision/btBroadphaseInterface.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "../NarrowPhaseCollision/btPersistentManifold.h" #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
class btDispatcher; class btDispatcher;
#include "../BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "btCollisionCreateFunc.h" #include "btCollisionCreateFunc.h"
#include "../../LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
class btDispatcher;
/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes /// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
/// Place holder, not fully implemented yet
class btCompoundCollisionAlgorithm : public btCollisionAlgorithm class btCompoundCollisionAlgorithm : public btCollisionAlgorithm
{ {
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms; btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms;
bool m_isSwapped; bool m_isSwapped;
class btPersistentManifold* m_sharedManifold;
bool m_ownsManifold;
public: public:
btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
@@ -43,11 +46,22 @@ public:
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
int i;
for (i=0;i<m_childCollisionAlgorithms.size();i++)
{
if (m_childCollisionAlgorithms[i])
m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
}
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc struct CreateFunc :public btCollisionAlgorithmCreateFunc
{ {
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{ {
return new btCompoundCollisionAlgorithm(ci,body0,body1,false); void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false);
} }
}; };
@@ -55,7 +69,8 @@ public:
{ {
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{ {
return new btCompoundCollisionAlgorithm(ci,body0,body1,true); void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true);
} }
}; };

View File

@@ -29,7 +29,7 @@ subject to the following restrictions:
btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
: btCollisionAlgorithm(ci), : btCollisionAlgorithm(ci),
m_isSwapped(isSwapped), m_isSwapped(isSwapped),
m_btConvexTriangleCallback(ci.m_dispatcher,body0,body1,isSwapped) m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
{ {
} }
@@ -37,6 +37,13 @@ btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
{ {
} }
void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_btConvexTriangleCallback.m_manifoldPtr)
{
manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr);
}
}
btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
@@ -79,7 +86,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i
//aabb filter is already applied! //aabb filter is already applied!
btCollisionAlgorithmConstructionInfo ci; btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher = m_dispatcher; ci.m_dispatcher1 = m_dispatcher;
btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody); btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
@@ -110,12 +117,10 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i
btTriangleShape tm(triangle[0],triangle[1],triangle[2]); btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
tm.setMargin(m_collisionMarginTriangle); tm.setMargin(m_collisionMarginTriangle);
btCollisionShape* tmpShape = ob->getCollisionShape(); btCollisionShape* tmpShape = ob->getCollisionShape();
ob->setCollisionShape( &tm ); ob->internalSetTemporaryCollisionShape( &tm );
btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr);
btCollisionAlgorithm* colAlgo = ci.m_dispatcher->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr);
///this should use the btDispatcher, so the actual registered algorithm is used ///this should use the btDispatcher, so the actual registered algorithm is used
// btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody); // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody);
@@ -123,13 +128,12 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i
// cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex); // cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex);
// cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); // cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
delete colAlgo; colAlgo->~btCollisionAlgorithm();
ob->setCollisionShape( tmpShape ); ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
ob->internalSetTemporaryCollisionShape( tmpShape);
} }
} }
@@ -188,6 +192,7 @@ void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* bod
concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax()); concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
resultOut->refreshContactPoints();
} }

View File

@@ -16,13 +16,13 @@ subject to the following restrictions:
#ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H #ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H
#define CONVEX_CONCAVE_COLLISION_ALGORITHM_H #define CONVEX_CONCAVE_COLLISION_ALGORITHM_H
#include "../BroadphaseCollision/btCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "../BroadphaseCollision/btDispatcher.h" #include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "../BroadphaseCollision/btBroadphaseInterface.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "../CollisionShapes/btTriangleCallback.h" #include "BulletCollision/CollisionShapes/btTriangleCallback.h"
#include "../NarrowPhaseCollision/btPersistentManifold.h" #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
class btDispatcher; class btDispatcher;
#include "../BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "btCollisionCreateFunc.h" #include "btCollisionCreateFunc.h"
///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called. ///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
@@ -55,11 +55,11 @@ int m_triangleCount;
void clearCache(); void clearCache();
inline const btVector3& getAabbMin() const SIMD_FORCE_INLINE const btVector3& getAabbMin() const
{ {
return m_aabbMin; return m_aabbMin;
} }
inline const btVector3& getAabbMax() const SIMD_FORCE_INLINE const btVector3& getAabbMax() const
{ {
return m_aabbMax; return m_aabbMax;
} }
@@ -88,13 +88,16 @@ public:
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
void clearCache(); void clearCache();
struct CreateFunc :public btCollisionAlgorithmCreateFunc struct CreateFunc :public btCollisionAlgorithmCreateFunc
{ {
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{ {
return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false);
} }
}; };
@@ -102,7 +105,8 @@ public:
{ {
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{ {
return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true);
} }
}; };

View File

@@ -15,7 +15,7 @@ subject to the following restrictions:
#include "btConvexConvexAlgorithm.h" #include "btConvexConvexAlgorithm.h"
#include <stdio.h> //#include <stdio.h>
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
@@ -33,7 +33,6 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h" #include "BulletCollision/CollisionShapes/btSphereShape.h"
@@ -48,26 +47,16 @@ subject to the following restrictions:
btConvexConvexAlgorithm::CreateFunc::CreateFunc()
{
m_ownsSolvers = true;
m_simplexSolver = new btVoronoiSimplexSolver();
m_pdSolver = new btGjkEpaPenetrationDepthSolver;
}
btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
{ {
m_ownsSolvers = false;
m_simplexSolver = simplexSolver; m_simplexSolver = simplexSolver;
m_pdSolver = pdSolver; m_pdSolver = pdSolver;
} }
btConvexConvexAlgorithm::CreateFunc::~CreateFunc() btConvexConvexAlgorithm::CreateFunc::~CreateFunc()
{ {
if (m_ownsSolvers){
delete m_simplexSolver;
delete m_pdSolver;
}
} }
btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
@@ -152,6 +141,11 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
#endif #endif
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
} }

View File

@@ -16,12 +16,13 @@ subject to the following restrictions:
#ifndef CONVEX_CONVEX_ALGORITHM_H #ifndef CONVEX_CONVEX_ALGORITHM_H
#define CONVEX_CONVEX_ALGORITHM_H #define CONVEX_CONVEX_ALGORITHM_H
#include "../BroadphaseCollision/btCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "../NarrowPhaseCollision/btGjkPairDetector.h" #include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
#include "../NarrowPhaseCollision/btPersistentManifold.h" #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "../NarrowPhaseCollision/btVoronoiSimplexSolver.h" #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "btCollisionCreateFunc.h" #include "btCollisionCreateFunc.h"
#include "btCollisionDispatcher.h"
class btConvexPenetrationDepthSolver; class btConvexPenetrationDepthSolver;
@@ -46,6 +47,14 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
///should we use m_ownManifold to avoid adding duplicates?
if (m_manifoldPtr && m_ownManifold)
manifoldArray.push_back(m_manifoldPtr);
}
void setLowLevelOfDetail(bool useLowLevel); void setLowLevelOfDetail(bool useLowLevel);
@@ -58,15 +67,15 @@ public:
{ {
btConvexPenetrationDepthSolver* m_pdSolver; btConvexPenetrationDepthSolver* m_pdSolver;
btSimplexSolverInterface* m_simplexSolver; btSimplexSolverInterface* m_simplexSolver;
bool m_ownsSolvers;
CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
CreateFunc();
virtual ~CreateFunc(); virtual ~CreateFunc();
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{ {
return new btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver); void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver);
} }
}; };

View File

@@ -15,8 +15,9 @@ subject to the following restrictions:
#ifndef EMPTY_ALGORITH #ifndef EMPTY_ALGORITH
#define EMPTY_ALGORITH #define EMPTY_ALGORITH
#include "../BroadphaseCollision/btCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "btCollisionCreateFunc.h" #include "btCollisionCreateFunc.h"
#include "btCollisionDispatcher.h"
#define ATTRIBUTE_ALIGNED(a) #define ATTRIBUTE_ALIGNED(a)
@@ -33,13 +34,18 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
}
struct CreateFunc :public btCollisionAlgorithmCreateFunc struct CreateFunc :public btCollisionAlgorithmCreateFunc
{ {
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{ {
(void)body0; (void)body0;
(void)body1; (void)body1;
return new btEmptyAlgorithm(ci); void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
return new(mem) btEmptyAlgorithm(ci);
} }
}; };

View File

@@ -79,12 +79,30 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
} }
btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
newPt.m_positionWorldOnA = pointA;
newPt.m_positionWorldOnB = pointInWorld;
int insertIndex = m_manifoldPtr->getCacheEntry(newPt); int insertIndex = m_manifoldPtr->getCacheEntry(newPt);
newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1); newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1);
newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1); newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1);
//BP mod, store contact triangles.
newPt.m_partId0 = m_partId0;
newPt.m_partId1 = m_partId1;
newPt.m_index0 = m_index0;
newPt.m_index1 = m_index1;
///todo, check this for any side effects
if (insertIndex >= 0)
{
//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
} else
{
insertIndex = m_manifoldPtr->addManifoldPoint(newPt);
}
//User can override friction and/or restitution //User can override friction and/or restitution
if (gContactAddedCallback && if (gContactAddedCallback &&
//and if either of the two bodies requires custom material //and if either of the two bodies requires custom material
@@ -94,16 +112,8 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
//experimental feature info, for per-triangle material etc. //experimental feature info, for per-triangle material etc.
btCollisionObject* obj0 = isSwapped? m_body1 : m_body0; btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
btCollisionObject* obj1 = isSwapped? m_body0 : m_body1; btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
(*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1); (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0,m_partId0,m_index0,obj1,m_partId1,m_index1);
} }
if (insertIndex >= 0)
{
//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
} else
{
m_manifoldPtr->AddManifoldPoint(newPt);
}
} }

View File

@@ -18,12 +18,12 @@ subject to the following restrictions:
#define MANIFOLD_RESULT_H #define MANIFOLD_RESULT_H
class btCollisionObject; class btCollisionObject;
class btPersistentManifold; #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
class btManifoldPoint; class btManifoldPoint;
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
#include "../../LinearMath/btTransform.h" #include "LinearMath/btTransform.h"
typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1); typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1);
extern ContactAddedCallback gContactAddedCallback; extern ContactAddedCallback gContactAddedCallback;
@@ -60,6 +60,15 @@ public:
m_manifoldPtr = manifoldPtr; m_manifoldPtr = manifoldPtr;
} }
const btPersistentManifold* getPersistentManifold() const
{
return m_manifoldPtr;
}
btPersistentManifold* getPersistentManifold()
{
return m_manifoldPtr;
}
virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1) virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1)
{ {
m_partId0=partId0; m_partId0=partId0;
@@ -70,6 +79,22 @@ public:
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth);
SIMD_FORCE_INLINE void refreshContactPoints()
{
btAssert(m_manifoldPtr);
if (!m_manifoldPtr->getNumContacts())
return;
bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
if (isSwapped)
{
m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA);
} else
{
m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB);
}
}
}; };

View File

@@ -1,3 +1,17 @@
/*
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 "LinearMath/btScalar.h" #include "LinearMath/btScalar.h"
@@ -7,7 +21,7 @@
#include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" #include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
#include <stdio.h> //#include <stdio.h>
#include "LinearMath/btQuickprof.h" #include "LinearMath/btQuickprof.h"
btSimulationIslandManager::btSimulationIslandManager() btSimulationIslandManager::btSimulationIslandManager()
@@ -25,17 +39,17 @@ void btSimulationIslandManager::initUnionFind(int n)
} }
void btSimulationIslandManager::findUnions(btDispatcher* dispatcher) void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
{ {
{ {
for (int i=0;i<dispatcher->getNumManifolds();i++) btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr();
{
const btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
//static objects (invmass btScalar(0.)) don't merge !
const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0()); for (int i=0;i<colWorld->getPairCache()->getNumOverlappingPairs();i++)
const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1()); {
const btBroadphasePair& collisionPair = pairPtr[i];
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
((colObj1) && ((colObj1)->mergesSimulationIslands()))) ((colObj1) && ((colObj1)->mergesSimulationIslands())))
@@ -71,7 +85,7 @@ void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld
} }
// do the union find // do the union find
findUnions(dispatcher); findUnions(dispatcher,colWorld);
@@ -91,7 +105,7 @@ void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* col
for (i=0;i<colWorld->getCollisionObjectArray().size();i++) for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
{ {
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
if (collisionObject->mergesSimulationIslands()) if (!collisionObject->isStaticOrKinematicObject())
{ {
collisionObject->setIslandTag( m_unionFind.find(index) ); collisionObject->setIslandTag( m_unionFind.find(index) );
collisionObject->setCompanionId(-1); collisionObject->setCompanionId(-1);
@@ -129,29 +143,12 @@ class btPersistentManifoldSortPredicate
}; };
void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects)
//
// todo: this is random access, it can be walked 'cache friendly'!
//
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback)
{ {
BT_PROFILE("islandUnionFindAndQuickSort");
m_islandmanifold.resize(0);
/*if (0)
{
int maxNumManifolds = dispatcher->getNumManifolds();
btCollisionDispatcher* colDis = (btCollisionDispatcher*)dispatcher;
btPersistentManifold** manifold = colDis->getInternalManifoldPointer();
callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, 0);
return;
}
*/
BEGIN_PROFILE("islandUnionFindAndHeapSort");
//we are going to sort the unionfind array, and store the element id in the size //we are going to sort the unionfind array, and store the element id in the size
//afterwards, we clean unionfind, to make sure no-one uses it anymore //afterwards, we clean unionfind, to make sure no-one uses it anymore
@@ -183,7 +180,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
btCollisionObject* colObj0 = collisionObjects[i]; btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{ {
printf("error in island management\n"); // printf("error in island management\n");
} }
assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
@@ -210,7 +207,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
btCollisionObject* colObj0 = collisionObjects[i]; btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{ {
printf("error in island management\n"); // printf("error in island management\n");
} }
assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
@@ -231,7 +228,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
btCollisionObject* colObj0 = collisionObjects[i]; btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{ {
printf("error in island management\n"); // printf("error in island management\n");
} }
assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
@@ -247,10 +244,16 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
} }
} }
btAlignedObjectArray<btPersistentManifold*> islandmanifold;
int i; int i;
int maxNumManifolds = dispatcher->getNumManifolds(); int maxNumManifolds = dispatcher->getNumManifolds();
islandmanifold.reserve(maxNumManifolds);
#define SPLIT_ISLANDS 1
#ifdef SPLIT_ISLANDS
#endif //SPLIT_ISLANDS
for (i=0;i<maxNumManifolds ;i++) for (i=0;i<maxNumManifolds ;i++)
{ {
@@ -265,29 +268,52 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
{ {
//kinematic objects don't merge islands, but wake up all connected objects //kinematic objects don't merge islands, but wake up all connected objects
if (colObj0->isStaticOrKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
{ {
colObj1->activate(); colObj1->activate();
} }
if (colObj1->isStaticOrKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
{ {
colObj0->activate(); colObj0->activate();
} }
#ifdef SPLIT_ISLANDS
//filtering for response // //filtering for response
if (dispatcher->needsResponse(colObj0,colObj1)) if (dispatcher->needsResponse(colObj0,colObj1))
islandmanifold.push_back(manifold); m_islandmanifold.push_back(manifold);
#endif //SPLIT_ISLANDS
} }
} }
}
int numManifolds = int (islandmanifold.size());
//
// todo: this is random access, it can be walked 'cache friendly'!
//
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback)
{
buildIslands(dispatcher,collisionObjects);
int endIslandIndex=1;
int startIslandIndex;
int numElem = getUnionFind().getNumElements();
BT_PROFILE("processIslands");
#ifndef SPLIT_ISLANDS
btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1);
#else
// Sort manifolds, based on islands // Sort manifolds, based on islands
// Sort the vector using predicate and std::sort // Sort the vector using predicate and std::sort
//std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
int numManifolds = int (m_islandmanifold.size());
//we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) //we should do radix sort, it it much faster (O(n) instead of O (n log2(n))
islandmanifold.heapSort(btPersistentManifoldSortPredicate()); m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
//now process all active islands (sets of manifolds for now) //now process all active islands (sets of manifolds for now)
@@ -296,10 +322,9 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
//int islandId; //int islandId;
END_PROFILE("islandUnionFindAndHeapSort");
btAlignedObjectArray<btCollisionObject*> islandBodies;
// printf("Start Islands\n");
//traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex) for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
@@ -313,7 +338,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
{ {
int i = getUnionFind().getElement(endIslandIndex).m_sz; int i = getUnionFind().getElement(endIslandIndex).m_sz;
btCollisionObject* colObj0 = collisionObjects[i]; btCollisionObject* colObj0 = collisionObjects[i];
islandBodies.push_back(colObj0); m_islandBodies.push_back(colObj0);
if (!colObj0->isActive()) if (!colObj0->isActive())
islandSleeping = true; islandSleeping = true;
} }
@@ -325,12 +350,12 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
if (startManifoldIndex<numManifolds) if (startManifoldIndex<numManifolds)
{ {
int curIslandId = getIslandId(islandmanifold[startManifoldIndex]); int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
if (curIslandId == islandId) if (curIslandId == islandId)
{ {
startManifold = &islandmanifold[startManifoldIndex]; startManifold = &m_islandmanifold[startManifoldIndex];
for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(islandmanifold[endManifoldIndex]));endManifoldIndex++) for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
{ {
} }
@@ -342,7 +367,8 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
if (!islandSleeping) if (!islandSleeping)
{ {
callback->ProcessIsland(&islandBodies[0],islandBodies.size(),startManifold,numIslandManifolds, islandId); callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId);
// printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
} }
if (numIslandManifolds) if (numIslandManifolds)
@@ -350,8 +376,9 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
startManifoldIndex = endManifoldIndex; startManifoldIndex = endManifoldIndex;
} }
islandBodies.resize(0); m_islandBodies.resize(0);
} }
#endif //SPLIT_ISLANDS
} }

View File

@@ -16,18 +16,26 @@ subject to the following restrictions:
#ifndef SIMULATION_ISLAND_MANAGER_H #ifndef SIMULATION_ISLAND_MANAGER_H
#define SIMULATION_ISLAND_MANAGER_H #define SIMULATION_ISLAND_MANAGER_H
#include "../CollisionDispatch/btUnionFind.h" #include "BulletCollision/CollisionDispatch/btUnionFind.h"
#include "btCollisionCreateFunc.h" #include "btCollisionCreateFunc.h"
#include "LinearMath/btAlignedObjectArray.h"
class btCollisionObject; class btCollisionObject;
class btCollisionWorld; class btCollisionWorld;
class btDispatcher; class btDispatcher;
class btPersistentManifold;
///SimulationIslandManager creates and handles simulation islands, using btUnionFind ///SimulationIslandManager creates and handles simulation islands, using btUnionFind
class btSimulationIslandManager class btSimulationIslandManager
{ {
btUnionFind m_unionFind; btUnionFind m_unionFind;
btAlignedObjectArray<btPersistentManifold*> m_islandmanifold;
btAlignedObjectArray<btCollisionObject* > m_islandBodies;
public: public:
btSimulationIslandManager(); btSimulationIslandManager();
virtual ~btSimulationIslandManager(); virtual ~btSimulationIslandManager();
@@ -42,7 +50,7 @@ public:
virtual void storeIslandActivationState(btCollisionWorld* world); virtual void storeIslandActivationState(btCollisionWorld* world);
void findUnions(btDispatcher* dispatcher); void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld);
@@ -55,6 +63,8 @@ public:
void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback); void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback);
void buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects);
}; };
#endif //SIMULATION_ISLAND_MANAGER_H #endif //SIMULATION_ISLAND_MANAGER_H

View File

@@ -68,18 +68,25 @@ void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,b
btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius); btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius);
resultOut->setPersistentManifold(m_manifoldPtr);
if (dist < SIMD_EPSILON) if (dist < SIMD_EPSILON)
{ {
btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize(); btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize();
/// report a contact. internally this will be kept persistent, and contact reduction is done /// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist); resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist);
} }
if (m_ownManifold)
{
if (m_manifoldPtr->getNumContacts())
{
resultOut->refreshContactPoints();
}
}
} }
@@ -102,8 +109,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* box
btVector3 bounds[2]; btVector3 bounds[2];
btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape(); btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape();
bounds[0] = -boxShape->getHalfExtents(); bounds[0] = -boxShape->getHalfExtentsWithoutMargin();
bounds[1] = boxShape->getHalfExtents(); bounds[1] = boxShape->getHalfExtentsWithoutMargin();
margins = boxShape->getMargin();//also add sphereShape margin? margins = boxShape->getMargin();//also add sphereShape margin?
@@ -209,6 +216,10 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject*
btVector3 p0, tmp, prel, n[6], normal; btVector3 p0, tmp, prel, n[6], normal;
btScalar fSep = btScalar(-10000000.0), fSepThis; btScalar fSep = btScalar(-10000000.0), fSepThis;
// set p0 and normal to a default value to shup up GCC
p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) ); n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) );
n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) ); n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) );
n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) ); n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) );

View File

@@ -16,11 +16,13 @@ subject to the following restrictions:
#ifndef SPHERE_BOX_COLLISION_ALGORITHM_H #ifndef SPHERE_BOX_COLLISION_ALGORITHM_H
#define SPHERE_BOX_COLLISION_ALGORITHM_H #define SPHERE_BOX_COLLISION_ALGORITHM_H
#include "../BroadphaseCollision/btCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "../CollisionDispatch/btCollisionCreateFunc.h" #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold; class btPersistentManifold;
#include "../../LinearMath/btVector3.h" #include "btCollisionDispatcher.h"
#include "LinearMath/btVector3.h"
/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. /// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
/// Other features are frame-coherency (persistent data) and collision response. /// Other features are frame-coherency (persistent data) and collision response.
@@ -40,6 +42,14 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius ); btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius );
btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax); btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax);
@@ -48,12 +58,13 @@ public:
{ {
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{ {
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
if (!m_swapped) if (!m_swapped)
{ {
return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false);
} else } else
{ {
return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true);
} }
} }
}; };

View File

@@ -46,6 +46,8 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0
if (!m_manifoldPtr) if (!m_manifoldPtr)
return; return;
resultOut->setPersistentManifold(m_manifoldPtr);
btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape(); btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape();
btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape(); btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape();
@@ -54,23 +56,41 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0
btScalar radius0 = sphere0->getRadius(); btScalar radius0 = sphere0->getRadius();
btScalar radius1 = sphere1->getRadius(); btScalar radius1 = sphere1->getRadius();
#ifdef CLEAR_MANIFOLD
m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
#endif
///iff distance positive, don't generate a new contact ///iff distance positive, don't generate a new contact
if ( len > (radius0+radius1)) if ( len > (radius0+radius1))
{
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
return; return;
}
///distance (negative means penetration) ///distance (negative means penetration)
btScalar dist = len - (radius0+radius1); btScalar dist = len - (radius0+radius1);
btVector3 normalOnSurfaceB = diff / len; btVector3 normalOnSurfaceB(1,0,0);
if (len > SIMD_EPSILON)
{
normalOnSurfaceB = diff / len;
}
///point on A (worldspace) ///point on A (worldspace)
btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB; btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
///point on B (worldspace) ///point on B (worldspace)
btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB; btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
/// report a contact. internally this will be kept persistent, and contact reduction is done /// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
resultOut->addContactPoint(normalOnSurfaceB,pos1,dist); resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
} }
btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)

View File

@@ -16,9 +16,11 @@ subject to the following restrictions:
#ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H #ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H
#define SPHERE_SPHERE_COLLISION_ALGORITHM_H #define SPHERE_SPHERE_COLLISION_ALGORITHM_H
#include "../BroadphaseCollision/btCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "../CollisionDispatch/btCollisionCreateFunc.h" #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "btCollisionDispatcher.h"
class btPersistentManifold; class btPersistentManifold;
/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. /// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
@@ -39,6 +41,13 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
virtual ~btSphereSphereCollisionAlgorithm(); virtual ~btSphereSphereCollisionAlgorithm();
@@ -46,7 +55,8 @@ public:
{ {
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{ {
return new btSphereSphereCollisionAlgorithm(0,ci,body0,body1); void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1);
} }
}; };

View File

@@ -48,8 +48,11 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co
if (!m_manifoldPtr) if (!m_manifoldPtr)
return; return;
btSphereShape* sphere = (btSphereShape*)col0->getCollisionShape(); btCollisionObject* sphereObj = m_swapped? col1 : col0;
btTriangleShape* triangle = (btTriangleShape*)col1->getCollisionShape(); btCollisionObject* triObj = m_swapped? col0 : col1;
btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape();
btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape();
/// report a contact. internally this will be kept persistent, and contact reduction is done /// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr); resultOut->setPersistentManifold(m_manifoldPtr);
@@ -57,10 +60,15 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co
btDiscreteCollisionDetectorInterface::ClosestPointInput input; btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = btScalar(1e30);//todo: tighter bounds input.m_maximumDistanceSquared = btScalar(1e30);//todo: tighter bounds
input.m_transformA = col0->getWorldTransform(); input.m_transformA = sphereObj->getWorldTransform();
input.m_transformB = col1->getWorldTransform(); input.m_transformB = triObj->getWorldTransform();
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); bool swapResults = m_swapped;
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults);
if (m_ownManifold)
resultOut->refreshContactPoints();
} }

View File

@@ -16,10 +16,11 @@ subject to the following restrictions:
#ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H #ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
#define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H #define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
#include "../BroadphaseCollision/btCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "../CollisionDispatch/btCollisionCreateFunc.h" #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold; class btPersistentManifold;
#include "btCollisionDispatcher.h"
/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. /// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
/// Other features are frame-coherency (persistent data) and collision response. /// Other features are frame-coherency (persistent data) and collision response.
@@ -40,6 +41,13 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
virtual ~btSphereTriangleCollisionAlgorithm(); virtual ~btSphereTriangleCollisionAlgorithm();
@@ -49,7 +57,9 @@ public:
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{ {
return new btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped);
} }
}; };

View File

@@ -18,6 +18,7 @@ subject to the following restrictions:
btUnionFind::~btUnionFind() btUnionFind::~btUnionFind()
{ {
Free(); Free();
@@ -76,8 +77,7 @@ void btUnionFind::sortIslands()
// Sort the vector using predicate and std::sort // Sort the vector using predicate and std::sort
//std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate); //std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
//perhaps use radix sort? m_elements.quickSort(btUnionFindElementSortPredicate());
m_elements.heapSort(btUnionFindElementSortPredicate());
} }

View File

@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef UNION_FIND_H #ifndef UNION_FIND_H
#define UNION_FIND_H #define UNION_FIND_H
#include "../../LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
#define USE_PATH_COMPRESSION 1 #define USE_PATH_COMPRESSION 1
@@ -46,11 +46,11 @@ class btUnionFind
void reset(int N); void reset(int N);
inline int getNumElements() const SIMD_FORCE_INLINE int getNumElements() const
{ {
return int(m_elements.size()); return int(m_elements.size());
} }
inline bool isRoot(int x) const SIMD_FORCE_INLINE bool isRoot(int x) const
{ {
return (x == m_elements[x].m_id); return (x == m_elements[x].m_id);
} }

View File

@@ -15,35 +15,20 @@ subject to the following restrictions:
#include "btBoxShape.h" #include "btBoxShape.h"
btVector3 btBoxShape::getHalfExtents() const
{
return m_implicitShapeDimensions * m_localScaling;
}
//{ //{
void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{ {
btVector3 halfExtents = getHalfExtents(); btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
btMatrix3x3 abs_b = t.getBasis().absolute();
btPoint3 center = t.getOrigin();
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
abs_b[1].dot(halfExtents),
abs_b[2].dot(halfExtents));
extent += btVector3(getMargin(),getMargin(),getMargin());
aabbMin = center - extent;
aabbMax = center + extent;
} }
void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{ {
//btScalar margin = btScalar(0.); //btScalar margin = btScalar(0.);
btVector3 halfExtents = getHalfExtents(); btVector3 halfExtents = getHalfExtentsWithMargin();
btScalar lx=btScalar(2.)*(halfExtents.x()); btScalar lx=btScalar(2.)*(halfExtents.x());
btScalar ly=btScalar(2.)*(halfExtents.y()); btScalar ly=btScalar(2.)*(halfExtents.y());

View File

@@ -18,11 +18,11 @@ subject to the following restrictions:
#include "btPolyhedralConvexShape.h" #include "btPolyhedralConvexShape.h"
#include "btCollisionMargin.h" #include "btCollisionMargin.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "../../LinearMath/btPoint3.h" #include "LinearMath/btPoint3.h"
#include "../../LinearMath/btSimdMinMax.h" #include "LinearMath/btMinMax.h"
///btBoxShape implements both a feature based (vertex/edge/plane) and implicit (getSupportingVertex) Box ///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
class btBoxShape: public btPolyhedralConvexShape class btBoxShape: public btPolyhedralConvexShape
{ {
@@ -31,47 +31,52 @@ class btBoxShape: public btPolyhedralConvexShape
public: public:
btVector3 getHalfExtents() const; btVector3 getHalfExtentsWithMargin() const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
btVector3 margin(getMargin(),getMargin(),getMargin());
halfExtents += margin;
return halfExtents;
}
const btVector3& getHalfExtentsWithoutMargin() const
{
return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
}
virtual int getShapeType() const { return BOX_SHAPE_PROXYTYPE;} virtual int getShapeType() const { return BOX_SHAPE_PROXYTYPE;}
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
{ {
btVector3 halfExtents = getHalfExtentsWithoutMargin();
btVector3 margin(getMargin(),getMargin(),getMargin());
halfExtents += margin;
btVector3 halfExtents = getHalfExtents(); return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btVector3 supVertex; btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
supVertex = btPoint3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
return supVertex;
} }
virtual inline btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{ {
btVector3 halfExtents = getHalfExtents(); const btVector3& halfExtents = getHalfExtentsWithoutMargin();
btVector3 margin(getMargin(),getMargin(),getMargin());
halfExtents -= margin;
return btVector3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
} }
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{ {
btVector3 halfExtents = getHalfExtents(); const btVector3& halfExtents = getHalfExtentsWithoutMargin();
btVector3 margin(getMargin(),getMargin(),getMargin());
halfExtents -= margin;
for (int i=0;i<numVectors;i++) for (int i=0;i<numVectors;i++)
{ {
const btVector3& vec = vectors[i]; const btVector3& vec = vectors[i];
supportVerticesOut[i].setValue(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
} }
} }
@@ -79,14 +84,38 @@ public:
btBoxShape( const btVector3& boxHalfExtents) btBoxShape( const btVector3& boxHalfExtents)
{ {
m_implicitShapeDimensions = boxHalfExtents; btVector3 margin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
}; };
virtual void setMargin(btScalar collisionMargin)
{
//correct the m_implicitShapeDimensions for the margin
btVector3 oldMargin(getMargin(),getMargin(),getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
btConvexInternalShape::setMargin(collisionMargin);
btVector3 newMargin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
}
virtual void setLocalScaling(const btVector3& scaling)
{
btVector3 oldMargin(getMargin(),getMargin(),getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
btConvexInternalShape::setLocalScaling(scaling);
m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
}
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const
{ {
@@ -116,7 +145,7 @@ public:
virtual void getVertex(int i,btVector3& vtx) const virtual void getVertex(int i,btVector3& vtx) const
{ {
btVector3 halfExtents = getHalfExtents(); btVector3 halfExtents = getHalfExtentsWithoutMargin();
vtx = btVector3( vtx = btVector3(
halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1), halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
@@ -127,7 +156,7 @@ public:
virtual void getPlaneEquation(btVector4& plane,int i) const virtual void getPlaneEquation(btVector4& plane,int i) const
{ {
btVector3 halfExtents = getHalfExtents(); btVector3 halfExtents = getHalfExtentsWithoutMargin();
switch (i) switch (i)
{ {
@@ -234,7 +263,7 @@ public:
virtual bool isInside(const btPoint3& pt,btScalar tolerance) const virtual bool isInside(const btPoint3& pt,btScalar tolerance) const
{ {
btVector3 halfExtents = getHalfExtents(); btVector3 halfExtents = getHalfExtentsWithoutMargin();
//btScalar minDist = 2*tolerance; //btScalar minDist = 2*tolerance;
@@ -250,7 +279,7 @@ public:
//debugging //debugging
virtual char* getName()const virtual const char* getName()const
{ {
return "Box"; return "Box";
} }
@@ -291,3 +320,4 @@ public:
#endif //OBB_BOX_MINKOWSKI_H #endif //OBB_BOX_MINKOWSKI_H

View File

@@ -18,32 +18,56 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" #include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization. ///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. ///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression) btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression) :btTriangleMeshShape(meshInterface),
m_bvh(0),
m_useQuantizedAabbCompression(useQuantizedAabbCompression),
m_ownsBvh(false)
{ {
//construct bvh from meshInterface //construct bvh from meshInterface
#ifndef DISABLE_BVH #ifndef DISABLE_BVH
m_bvh = new btOptimizedBvh();
btVector3 bvhAabbMin,bvhAabbMax; btVector3 bvhAabbMin,bvhAabbMax;
if(meshInterface->hasPremadeAabb())
{
meshInterface->getPremadeAabb(&bvhAabbMin, &bvhAabbMax);
}
else
{
meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax); meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax);
}
if (buildBvh)
{
void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
m_bvh = new (mem) btOptimizedBvh();
m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
m_ownsBvh = true;
}
#endif //DISABLE_BVH #endif //DISABLE_BVH
} }
btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression) :btTriangleMeshShape(meshInterface),
m_bvh(0),
m_useQuantizedAabbCompression(useQuantizedAabbCompression),
m_ownsBvh(false)
{ {
//construct bvh from meshInterface //construct bvh from meshInterface
#ifndef DISABLE_BVH #ifndef DISABLE_BVH
m_bvh = new btOptimizedBvh(); if (buildBvh)
{
void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
m_bvh = new (mem) btOptimizedBvh();
m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
m_ownsBvh = true;
}
#endif //DISABLE_BVH #endif //DISABLE_BVH
@@ -58,16 +82,140 @@ void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btV
} }
void btBvhTriangleMeshShape::refitTree() void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
{ {
m_bvh->refit( m_meshInterface ); m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
recalcLocalAabb(); recalcLocalAabb();
} }
btBvhTriangleMeshShape::~btBvhTriangleMeshShape() btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
{ {
delete m_bvh; if (m_ownsBvh)
{
m_bvh->~btOptimizedBvh();
btAlignedFree(m_bvh);
}
}
void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
{
struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
btStridingMeshInterface* m_meshInterface;
btTriangleCallback* m_callback;
MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
:m_meshInterface(meshInterface),
m_callback(callback)
{
}
virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
{
btVector3 m_triangle[3];
const unsigned char *vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
const unsigned char *indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
m_meshInterface->getLockedReadOnlyVertexIndexBase(
&vertexbase,
numverts,
type,
stride,
&indexbase,
indexstride,
numfaces,
indicestype,
nodeSubPart);
unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
const btVector3& meshScaling = m_meshInterface->getScaling();
for (int j=2;j>=0;j--)
{
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
}
/* Perform ray vs. triangle collision here */
m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
}
};
MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
}
void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
{
struct MyNodeOverlapCallback : public btNodeOverlapCallback
{
btStridingMeshInterface* m_meshInterface;
btTriangleCallback* m_callback;
MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
:m_meshInterface(meshInterface),
m_callback(callback)
{
}
virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
{
btVector3 m_triangle[3];
const unsigned char *vertexbase;
int numverts;
PHY_ScalarType type;
int stride;
const unsigned char *indexbase;
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
m_meshInterface->getLockedReadOnlyVertexIndexBase(
&vertexbase,
numverts,
type,
stride,
&indexbase,
indexstride,
numfaces,
indicestype,
nodeSubPart);
unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
const btVector3& meshScaling = m_meshInterface->getScaling();
for (int j=2;j>=0;j--)
{
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
}
/* Perform ray vs. triangle collision here */
m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
}
};
MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
} }
//perform bvh tree traversal and report overlapping triangles to 'callback' //perform bvh tree traversal and report overlapping triangles to 'callback'
@@ -118,13 +266,14 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co
indicestype, indicestype,
nodeSubPart); nodeSubPart);
int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride); unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
const btVector3& meshScaling = m_meshInterface->getScaling(); const btVector3& meshScaling = m_meshInterface->getScaling();
for (int j=2;j>=0;j--) for (int j=2;j>=0;j--)
{ {
int graphicsindex = gfxbase[j]; int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
#ifdef DEBUG_TRIANGLE_MESH #ifdef DEBUG_TRIANGLE_MESH
@@ -157,17 +306,37 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co
} }
void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
{ {
if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
{ {
btTriangleMeshShape::setLocalScaling(scaling); btTriangleMeshShape::setLocalScaling(scaling);
delete m_bvh; if (m_ownsBvh)
{
m_bvh->~btOptimizedBvh();
btAlignedFree(m_bvh);
}
///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
m_bvh = new btOptimizedBvh(); void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
m_bvh = new(mem) btOptimizedBvh();
//rebuild the bvh... //rebuild the bvh...
m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
m_ownsBvh = true;
} }
} }
void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
{
btAssert(!m_bvh);
btAssert(!m_ownsBvh);
m_bvh = bvh;
m_ownsBvh = false;
// update the scaling without rebuilding the bvh
if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
{
btTriangleMeshShape::setLocalScaling(scaling);
}
}

View File

@@ -18,45 +18,55 @@ subject to the following restrictions:
#include "btTriangleMeshShape.h" #include "btTriangleMeshShape.h"
#include "btOptimizedBvh.h" #include "btOptimizedBvh.h"
#include "LinearMath/btAlignedAllocator.h"
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. ///The btBvhTriangleMeshShape is a static-triangle mesh shape with several optimizations, such as bounding volume hierarchy and cache friendly traversal for PlayStation 3 Cell SPU. It is recommended to enable useQuantizedAabbCompression for better memory usage.
///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method.
///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk.
///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example.
ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape
{ {
btOptimizedBvh* m_bvh; btOptimizedBvh* m_bvh;
bool m_useQuantizedAabbCompression; bool m_useQuantizedAabbCompression;
bool m_pad[12];////need padding due to alignment bool m_ownsBvh;
bool m_pad[11];////need padding due to alignment
public: public:
btBvhTriangleMeshShape() :btTriangleMeshShape(0) {}; BT_DECLARE_ALIGNED_ALLOCATOR();
btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression);
btBvhTriangleMeshShape() :btTriangleMeshShape(0),m_bvh(0),m_ownsBvh(false) {};
btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true);
virtual ~btBvhTriangleMeshShape(); virtual ~btBvhTriangleMeshShape();
bool getOwnsBvh () const
{
return m_ownsBvh;
}
/*
virtual int getShapeType() const virtual int getShapeType() const
{ {
return TRIANGLE_MESH_SHAPE_PROXYTYPE; return TRIANGLE_MESH_SHAPE_PROXYTYPE;
} }
*/
void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget);
void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax);
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
void refitTree(); void refitTree(const btVector3& aabbMin,const btVector3& aabbMax);
///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks ///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks
void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax); void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax);
//debugging //debugging
virtual char* getName()const {return "BVHTRIANGLEMESH";} virtual const char* getName()const {return "BVHTRIANGLEMESH";}
virtual void setLocalScaling(const btVector3& scaling); virtual void setLocalScaling(const btVector3& scaling);
@@ -65,6 +75,10 @@ public:
{ {
return m_bvh; return m_bvh;
} }
void setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1));
bool usesQuantizedAabbCompression() const bool usesQuantizedAabbCompression() const
{ {
return m_useQuantizedAabbCompression; return m_useQuantizedAabbCompression;

View File

@@ -21,6 +21,7 @@ subject to the following restrictions:
btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
{ {
m_upAxis = 1;
m_implicitShapeDimensions.setValue(radius,0.5f*height,radius); m_implicitShapeDimensions.setValue(radius,0.5f*height,radius);
} }
@@ -50,7 +51,9 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
{ {
btVector3 pos(0,getHalfHeight(),0); btVector3 pos(0,0,0);
pos[getUpAxis()] = getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx); newDot = vec.dot(vtx);
if (newDot > maxDot) if (newDot > maxDot)
@@ -60,7 +63,9 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
} }
} }
{ {
btVector3 pos(0,-getHalfHeight(),0); btVector3 pos(0,0,0);
pos[getUpAxis()] = -getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx); newDot = vec.dot(vtx);
if (newDot > maxDot) if (newDot > maxDot)
@@ -88,7 +93,8 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
btVector3 vtx; btVector3 vtx;
btScalar newDot; btScalar newDot;
{ {
btVector3 pos(0,getHalfHeight(),0); btVector3 pos(0,0,0);
pos[getUpAxis()] = getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx); newDot = vec.dot(vtx);
if (newDot > maxDot) if (newDot > maxDot)
@@ -98,7 +104,8 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
} }
} }
{ {
btVector3 pos(0,-getHalfHeight(),0); btVector3 pos(0,0,0);
pos[getUpAxis()] = -getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx); newDot = vec.dot(vtx);
if (newDot > maxDot) if (newDot > maxDot)
@@ -112,7 +119,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
} }
void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{ {
//as an approximation, take the inertia of the box that bounds the spheres //as an approximation, take the inertia of the box that bounds the spheres
@@ -122,7 +129,8 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
btScalar radius = getRadius(); btScalar radius = getRadius();
btVector3 halfExtents(radius,radius+getHalfHeight(),radius); btVector3 halfExtents(radius,radius,radius);
halfExtents[getUpAxis()]+=getHalfHeight();
btScalar margin = CONVEX_DISTANCE_MARGIN; btScalar margin = CONVEX_DISTANCE_MARGIN;
@@ -140,6 +148,22 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
} }
btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height)
{
m_upAxis = 0;
m_implicitShapeDimensions.setValue(0.5f*height, radius,radius);
}
btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height)
{
m_upAxis = 2;
m_implicitShapeDimensions.setValue(radius,radius,0.5f*height);
}

View File

@@ -16,20 +16,27 @@ subject to the following restrictions:
#ifndef BT_CAPSULE_SHAPE_H #ifndef BT_CAPSULE_SHAPE_H
#define BT_CAPSULE_SHAPE_H #define BT_CAPSULE_SHAPE_H
#include "btConvexShape.h" #include "btConvexInternalShape.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///btCapsuleShape represents a capsule around the Y axis ///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis.
///A more general solution that can represent capsules is the btMultiSphereShape ///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
class btCapsuleShape : public btConvexShape ///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres.
class btCapsuleShape : public btConvexInternalShape
{ {
protected:
int m_upAxis;
protected:
///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses.
btCapsuleShape() {};
public: public:
btCapsuleShape(btScalar radius,btScalar height); btCapsuleShape(btScalar radius,btScalar height);
///CollisionShape Interface ///CollisionShape Interface
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
/// btConvexShape Interface /// btConvexShape Interface
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
@@ -38,23 +45,76 @@ public:
virtual int getShapeType() const { return CAPSULE_SHAPE_PROXYTYPE; } virtual int getShapeType() const { return CAPSULE_SHAPE_PROXYTYPE; }
virtual char* getName()const virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
{
btVector3 halfExtents(getRadius(),getRadius(),getRadius());
halfExtents[m_upAxis] = getRadius() + getHalfHeight();
halfExtents += btVector3(getMargin(),getMargin(),getMargin());
btMatrix3x3 abs_b = t.getBasis().absolute();
btPoint3 center = t.getOrigin();
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
aabbMin = center - extent;
aabbMax = center + extent;
}
virtual const char* getName()const
{ {
return "CapsuleShape"; return "CapsuleShape";
} }
int getUpAxis() const
{
return m_upAxis;
}
btScalar getRadius() const btScalar getRadius() const
{ {
return m_implicitShapeDimensions.getX(); int radiusAxis = (m_upAxis+2)%3;
return m_implicitShapeDimensions[radiusAxis];
} }
btScalar getHalfHeight() const btScalar getHalfHeight() const
{ {
return m_implicitShapeDimensions.getY(); return m_implicitShapeDimensions[m_upAxis];
} }
}; };
///btCapsuleShapeX represents a capsule around the Z axis
///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
class btCapsuleShapeX : public btCapsuleShape
{
public:
btCapsuleShapeX(btScalar radius,btScalar height);
//debugging
virtual const char* getName()const
{
return "CapsuleX";
}
};
///btCapsuleShapeZ represents a capsule around the Z axis
///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
class btCapsuleShapeZ : public btCapsuleShape
{
public:
btCapsuleShapeZ(btScalar radius,btScalar height);
//debugging
virtual const char* getName()const
{
return "CapsuleZ";
}
};
#endif //BT_CAPSULE_SHAPE_H #endif //BT_CAPSULE_SHAPE_H

View File

@@ -21,7 +21,12 @@ subject to the following restrictions:
can be used by probes that are checking whether the can be used by probes that are checking whether the
library is actually installed. library is actually installed.
*/ */
extern "C" void btBulletCollisionProbe () {} extern "C"
{
void btBulletCollisionProbe ();
void btBulletCollisionProbe () {}
}
@@ -46,7 +51,7 @@ btScalar btCollisionShape::getAngularMotionDisc() const
return disc; return disc;
} }
void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const
{ {
//start with static aabb //start with static aabb
getAabb(curTrans,temporalAabbMin,temporalAabbMax); getAabb(curTrans,temporalAabbMin,temporalAabbMax);

View File

@@ -16,18 +16,21 @@ subject to the following restrictions:
#ifndef COLLISION_SHAPE_H #ifndef COLLISION_SHAPE_H
#define COLLISION_SHAPE_H #define COLLISION_SHAPE_H
#include "../../LinearMath/btTransform.h" #include "LinearMath/btTransform.h"
#include "../../LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
#include "../../LinearMath/btMatrix3x3.h" #include "LinearMath/btMatrix3x3.h"
#include "../../LinearMath/btPoint3.h" #include "LinearMath/btPoint3.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" //for the shape types #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types
///btCollisionShape provides interface for collision shapes that can be shared among btCollisionObjects. ///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects.
class btCollisionShape class btCollisionShape
{ {
void* m_userPointer;
public: public:
btCollisionShape() btCollisionShape() : m_userPointer(0)
{ {
} }
virtual ~btCollisionShape() virtual ~btCollisionShape()
@@ -45,30 +48,30 @@ public:
///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep) ///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep)
///result is conservative ///result is conservative
void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax); void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const;
#ifndef __SPU__ #ifndef __SPU__
inline bool isPolyhedral() const SIMD_FORCE_INLINE bool isPolyhedral() const
{ {
return btBroadphaseProxy::isPolyhedral(getShapeType()); return btBroadphaseProxy::isPolyhedral(getShapeType());
} }
inline bool isConvex() const SIMD_FORCE_INLINE bool isConvex() const
{ {
return btBroadphaseProxy::isConvex(getShapeType()); return btBroadphaseProxy::isConvex(getShapeType());
} }
inline bool isConcave() const SIMD_FORCE_INLINE bool isConcave() const
{ {
return btBroadphaseProxy::isConcave(getShapeType()); return btBroadphaseProxy::isConcave(getShapeType());
} }
inline bool isCompound() const SIMD_FORCE_INLINE bool isCompound() const
{ {
return btBroadphaseProxy::isCompound(getShapeType()); return btBroadphaseProxy::isCompound(getShapeType());
} }
///isInfinite is used to catch simulation error (aabb check) ///isInfinite is used to catch simulation error (aabb check)
inline bool isInfinite() const SIMD_FORCE_INLINE bool isInfinite() const
{ {
return btBroadphaseProxy::isInfinite(getShapeType()); return btBroadphaseProxy::isInfinite(getShapeType());
} }
@@ -76,11 +79,11 @@ public:
virtual int getShapeType() const=0; virtual int getShapeType() const=0;
virtual void setLocalScaling(const btVector3& scaling) =0; virtual void setLocalScaling(const btVector3& scaling) =0;
virtual const btVector3& getLocalScaling() const =0; virtual const btVector3& getLocalScaling() const =0;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) = 0; virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0;
//debugging support //debugging support
virtual char* getName()const =0 ; virtual const char* getName()const =0 ;
#endif //__SPU__ #endif //__SPU__
@@ -88,6 +91,18 @@ public:
virtual void setMargin(btScalar margin) = 0; virtual void setMargin(btScalar margin) = 0;
virtual btScalar getMargin() const = 0; virtual btScalar getMargin() const = 0;
///optional user data pointer
void setUserPointer(void* userPtr)
{
m_userPointer = userPtr;
}
void* getUserPointer() const
{
return m_userPointer;
}
}; };
#endif //COLLISION_SHAPE_H #endif //COLLISION_SHAPE_H

View File

@@ -14,29 +14,42 @@ subject to the following restrictions:
*/ */
#include "btCompoundShape.h" #include "btCompoundShape.h"
#include "btCollisionShape.h" #include "btCollisionShape.h"
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
btCompoundShape::btCompoundShape() btCompoundShape::btCompoundShape()
:m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)), :m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)),
m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)), m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)),
m_aabbTree(0),
m_collisionMargin(btScalar(0.)), m_collisionMargin(btScalar(0.)),
m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)) m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
m_dynamicAabbTree(0)
{ {
void* mem = btAlignedAlloc(sizeof(btDbvt),16);
m_dynamicAabbTree = new(mem) btDbvt();
btAssert(mem==m_dynamicAabbTree);
} }
btCompoundShape::~btCompoundShape() btCompoundShape::~btCompoundShape()
{ {
if (m_dynamicAabbTree)
{
m_dynamicAabbTree->~btDbvt();
btAlignedFree(m_dynamicAabbTree);
}
} }
void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
{ {
m_childTransforms.push_back(localTransform); //m_childTransforms.push_back(localTransform);
m_childShapes.push_back(shape); //m_childShapes.push_back(shape);
btCompoundShapeChild child;
child.m_transform = localTransform;
child.m_childShape = shape;
child.m_childShapeType = shape->getShapeType();
child.m_childMargin = shape->getMargin();
m_children.push_back(child);
//extend the local aabbMin/aabbMax //extend the local aabbMin/aabbMax
btVector3 localAabbMin,localAabbMax; btVector3 localAabbMin,localAabbMax;
@@ -53,14 +66,76 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio
} }
} }
if (m_dynamicAabbTree)
{
const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
int index = m_children.size()-1;
child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
}
} }
void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
{
btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
if (m_dynamicAabbTree)
{
m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node);
}
m_children.swap(childShapeIndex,m_children.size()-1);
m_children.pop_back();
}
void btCompoundShape::removeChildShape(btCollisionShape* shape)
{
// Find the children containing the shape specified, and remove those children.
//note: there might be multiple children using the same shape!
for(int i = m_children.size()-1; i >= 0 ; i--)
{
if(m_children[i].m_childShape == shape)
{
m_children.swap(i,m_children.size()-1);
m_children.pop_back();
//remove it from the m_dynamicAabbTree too
//m_dynamicAabbTree->remove(m_aabbProxies[i]);
//m_aabbProxies.swap(i,m_children.size()-1);
//m_aabbProxies.pop_back();
}
}
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
recalculateLocalAabb();
}
void btCompoundShape::recalculateLocalAabb()
{
// Recalculate the local aabb
// Brute force, it iterates over all the shapes left.
m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_localAabbMax = btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30));
//extend the local aabbMin/aabbMax
for (int j = 0; j < m_children.size(); j++)
{
btVector3 localAabbMin,localAabbMax;
m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax);
for (int i=0;i<3;i++)
{
if (m_localAabbMin[i] > localAabbMin[i])
m_localAabbMin[i] = localAabbMin[i];
if (m_localAabbMax[i] < localAabbMax[i])
m_localAabbMax[i] = localAabbMax[i];
}
}
}
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
{ {
btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
btMatrix3x3 abs_b = trans.getBasis().absolute(); btMatrix3x3 abs_b = trans.getBasis().absolute();
@@ -70,13 +145,12 @@ void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVect
btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
abs_b[1].dot(localHalfExtents), abs_b[1].dot(localHalfExtents),
abs_b[2].dot(localHalfExtents)); abs_b[2].dot(localHalfExtents));
extent += btVector3(getMargin(),getMargin(),getMargin()); aabbMin = center-extent;
aabbMax = center+extent;
aabbMin = center - extent;
aabbMax = center + extent;
} }
void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{ {
//approximation: take the inertia from the aabb for now //approximation: take the inertia from the aabb for now
btTransform ident; btTransform ident;
@@ -98,3 +172,60 @@ void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const
{
int n = m_children.size();
btScalar totalMass = 0;
btVector3 center(0, 0, 0);
for (int k = 0; k < n; k++)
{
center += m_children[k].m_transform.getOrigin() * masses[k];
totalMass += masses[k];
}
center /= totalMass;
principal.setOrigin(center);
btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0);
for (int k = 0; k < n; k++)
{
btVector3 i;
m_children[k].m_childShape->calculateLocalInertia(masses[k], i);
const btTransform& t = m_children[k].m_transform;
btVector3 o = t.getOrigin() - center;
//compute inertia tensor in coordinate system of compound shape
btMatrix3x3 j = t.getBasis().transpose();
j[0] *= i[0];
j[1] *= i[1];
j[2] *= i[2];
j = t.getBasis() * j;
//add inertia tensor
tensor[0] += j[0];
tensor[1] += j[1];
tensor[2] += j[2];
//compute inertia tensor of pointmass at o
btScalar o2 = o.length2();
j[0].setValue(o2, 0, 0);
j[1].setValue(0, o2, 0);
j[2].setValue(0, 0, o2);
j[0] += o * -o.x();
j[1] += o * -o.y();
j[2] += o * -o.z();
//add inertia tensor of pointmass
tensor[0] += masses[k] * j[0];
tensor[1] += masses[k] * j[1];
tensor[2] += masses[k] * j[2];
}
tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]);
}

View File

@@ -18,58 +18,97 @@ subject to the following restrictions:
#include "btCollisionShape.h" #include "btCollisionShape.h"
#include "../../LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
#include "../../LinearMath/btTransform.h" #include "LinearMath/btTransform.h"
#include "../../LinearMath/btMatrix3x3.h" #include "LinearMath/btMatrix3x3.h"
#include "btCollisionMargin.h" #include "btCollisionMargin.h"
#include "../../LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
class btOptimizedBvh; //class btOptimizedBvh;
struct btDbvt;
ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild
{
BT_DECLARE_ALIGNED_ALLOCATOR();
btTransform m_transform;
btCollisionShape* m_childShape;
int m_childShapeType;
btScalar m_childMargin;
struct btDbvtNode* m_node;
};
SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2)
{
return ( c1.m_transform == c2.m_transform &&
c1.m_childShape == c2.m_childShape &&
c1.m_childShapeType == c2.m_childShapeType &&
c1.m_childMargin == c2.m_childMargin );
}
/// btCompoundShape allows to store multiple other btCollisionShapes /// btCompoundShape allows to store multiple other btCollisionShapes
/// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape. /// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape.
class btCompoundShape : public btCollisionShape ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape
{ {
btAlignedObjectArray<btTransform> m_childTransforms; //btAlignedObjectArray<btTransform> m_childTransforms;
btAlignedObjectArray<btCollisionShape*> m_childShapes; //btAlignedObjectArray<btCollisionShape*> m_childShapes;
btAlignedObjectArray<btCompoundShapeChild> m_children;
btVector3 m_localAabbMin; btVector3 m_localAabbMin;
btVector3 m_localAabbMax; btVector3 m_localAabbMax;
btOptimizedBvh* m_aabbTree; //btOptimizedBvh* m_aabbTree;
btDbvt* m_dynamicAabbTree;
public: public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btCompoundShape(); btCompoundShape();
virtual ~btCompoundShape(); virtual ~btCompoundShape();
void addChildShape(const btTransform& localTransform,btCollisionShape* shape); void addChildShape(const btTransform& localTransform,btCollisionShape* shape);
/// Remove all children shapes that contain the specified shape
virtual void removeChildShape(btCollisionShape* shape);
void removeChildShapeByIndex(int childShapeindex);
int getNumChildShapes() const int getNumChildShapes() const
{ {
return int (m_childShapes.size()); return int (m_children.size());
} }
btCollisionShape* getChildShape(int index) btCollisionShape* getChildShape(int index)
{ {
return m_childShapes[index]; return m_children[index].m_childShape;
} }
const btCollisionShape* getChildShape(int index) const const btCollisionShape* getChildShape(int index) const
{ {
return m_childShapes[index]; return m_children[index].m_childShape;
} }
btTransform& getChildTransform(int index) btTransform getChildTransform(int index)
{ {
return m_childTransforms[index]; return m_children[index].m_transform;
} }
const btTransform& getChildTransform(int index) const const btTransform getChildTransform(int index) const
{ {
return m_childTransforms[index]; return m_children[index].m_transform;
}
btCompoundShapeChild* getChildList()
{
return &m_children[0];
} }
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
/** Re-calculate the local Aabb. Is called at the end of removeChildShapes.
Use this yourself if you modify the children or their transforms. */
virtual void recalculateLocalAabb();
virtual void setLocalScaling(const btVector3& scaling) virtual void setLocalScaling(const btVector3& scaling)
{ {
@@ -80,7 +119,7 @@ public:
return m_localScaling; return m_localScaling;
} }
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;} virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;}
@@ -92,7 +131,7 @@ public:
{ {
return m_collisionMargin; return m_collisionMargin;
} }
virtual char* getName()const virtual const char* getName()const
{ {
return "Compound"; return "Compound";
} }
@@ -100,11 +139,19 @@ public:
//this is optional, but should make collision queries faster, by culling non-overlapping nodes //this is optional, but should make collision queries faster, by culling non-overlapping nodes
void createAabbTreeFromChildren(); void createAabbTreeFromChildren();
const btOptimizedBvh* getAabbTree() const btDbvt* getDynamicAabbTree()
{ {
return m_aabbTree; return m_dynamicAabbTree;
} }
///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform
///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound
///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
///of the collision object by the principal transform.
void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const;
private: private:
btScalar m_collisionMargin; btScalar m_collisionMargin;
protected: protected:

View File

@@ -17,12 +17,12 @@ subject to the following restrictions:
#define CONCAVE_SHAPE_H #define CONCAVE_SHAPE_H
#include "btCollisionShape.h" #include "btCollisionShape.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "btTriangleCallback.h" #include "btTriangleCallback.h"
///Concave shape proves an interface concave shapes that can produce triangles that overlapping a given AABB. ///The btConcaveShape class provides an interface for non-moving (static) concave shapes.
///Static triangle mesh, infinite plane, height field/landscapes are example that implement this interface. ///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape.
class btConcaveShape : public btCollisionShape class btConcaveShape : public btCollisionShape
{ {
protected: protected:

View File

@@ -16,11 +16,11 @@ subject to the following restrictions:
#ifndef CONE_MINKOWSKI_H #ifndef CONE_MINKOWSKI_H
#define CONE_MINKOWSKI_H #define CONE_MINKOWSKI_H
#include "btConvexShape.h" #include "btConvexInternalShape.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///btConeShape implements a Cone shape, around the Y axis ///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis.
class btConeShape : public btConvexShape class btConeShape : public btConvexInternalShape
{ {
@@ -42,7 +42,7 @@ public:
btScalar getHeight() const { return m_height;} btScalar getHeight() const { return m_height;}
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
{ {
btTransform identity; btTransform identity;
identity.setIdentity(); identity.setIdentity();
@@ -72,7 +72,7 @@ public:
virtual int getShapeType() const { return CONE_SHAPE_PROXYTYPE; } virtual int getShapeType() const { return CONE_SHAPE_PROXYTYPE; }
virtual char* getName()const virtual const char* getName()const
{ {
return "Cone"; return "Cone";
} }

View File

@@ -36,6 +36,13 @@ btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int
} }
void btConvexHullShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
recalcLocalAabb();
}
void btConvexHullShape::addPoint(const btPoint3& point) void btConvexHullShape::addPoint(const btPoint3& point)
{ {
m_points.push_back(point); m_points.push_back(point);

View File

@@ -17,18 +17,17 @@ subject to the following restrictions:
#define CONVEX_HULL_SHAPE_H #define CONVEX_HULL_SHAPE_H
#include "btPolyhedralConvexShape.h" #include "btPolyhedralConvexShape.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "../../LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
///ConvexHullShape implements an implicit (getSupportingVertex) Convex Hull of a Point Cloud (vertices) ///The btConvexHullShape implements an implicit convex hull of an array of vertices.
///No connectivity is needed. localGetSupportingVertex iterates linearly though all vertices. ///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex.
///on modern hardware, due to cache coherency this isn't that bad. Complex algorithms tend to trash the cash.
///(memory is much slower then the cpu)
ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexShape ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexShape
{ {
btAlignedObjectArray<btPoint3> m_points; btAlignedObjectArray<btPoint3> m_points;
public: public:
BT_DECLARE_ALIGNED_ALLOCATOR();
///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory. ///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory.
@@ -43,7 +42,12 @@ public:
return &m_points[0]; return &m_points[0];
} }
int getNumPoints() const btPoint3* getPoints() const
{
return &m_points[0];
}
int getNumPoints() const
{ {
return m_points.size(); return m_points.size();
} }
@@ -56,7 +60,7 @@ public:
virtual int getShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; } virtual int getShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; }
//debugging //debugging
virtual char* getName()const {return "Convex";} virtual const char* getName()const {return "Convex";}
virtual int getNumVertices() const; virtual int getNumVertices() const;
@@ -67,7 +71,8 @@ public:
virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const; virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const;
virtual bool isInside(const btPoint3& pt,btScalar tolerance) const; virtual bool isInside(const btPoint3& pt,btScalar tolerance) const;
///in case we receive negative scaling
virtual void setLocalScaling(const btVector3& scaling);
}; };

View File

@@ -16,62 +16,3 @@ subject to the following restrictions:
#include "btConvexShape.h" #include "btConvexShape.h"
btConvexShape::btConvexShape()
: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
m_collisionMargin(CONVEX_DISTANCE_MARGIN)
{
}
void btConvexShape::setLocalScaling(const btVector3& scaling)
{
m_localScaling = scaling;
}
void btConvexShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const
{
btScalar margin = getMargin();
for (int i=0;i<3;i++)
{
btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
vec[i] = btScalar(1.);
btVector3 sv = localGetSupportingVertex(vec*trans.getBasis());
btVector3 tmp = trans(sv);
maxAabb[i] = tmp[i]+margin;
vec[i] = btScalar(-1.);
tmp = trans(localGetSupportingVertex(vec*trans.getBasis()));
minAabb[i] = tmp[i]-margin;
}
};
btVector3 btConvexShape::localGetSupportingVertex(const btVector3& vec)const
{
#ifndef __SPU__
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
if ( getMargin()!=btScalar(0.) )
{
btVector3 vecnorm = vec;
if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
{
vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
}
vecnorm.normalize();
supVertex+= getMargin() * vecnorm;
}
return supVertex;
#else
return btVector3(0,0,0);
#endif //__SPU__
}

View File

@@ -18,37 +18,25 @@ subject to the following restrictions:
#include "btCollisionShape.h" #include "btCollisionShape.h"
#include "../../LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
#include "../../LinearMath/btTransform.h" #include "LinearMath/btTransform.h"
#include "../../LinearMath/btMatrix3x3.h" #include "LinearMath/btMatrix3x3.h"
#include "btCollisionMargin.h" #include "btCollisionMargin.h"
#include "LinearMath/btAlignedAllocator.h"
//todo: get rid of this btConvexCastResult thing! //todo: get rid of this btConvexCastResult thing!
struct btConvexCastResult; struct btConvexCastResult;
#define MAX_PREFERRED_PENETRATION_DIRECTIONS 10 #define MAX_PREFERRED_PENETRATION_DIRECTIONS 10
/// btConvexShape is an abstract shape interface. /// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc.
/// The explicit part provides plane-equations, the implicit part provides GetClosestPoint interface. /// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector.
/// used in combination with GJK or btConvexCast
ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape
{ {
protected:
//local scaling. collisionMargin is not scaled !
btVector3 m_localScaling;
btVector3 m_implicitShapeDimensions;
btScalar m_collisionMargin;
btScalar m_padding[2];
public: public:
btConvexShape();
BT_DECLARE_ALIGNED_ALLOCATOR();
virtual ~btConvexShape() virtual ~btConvexShape()
{ {
@@ -56,7 +44,7 @@ public:
} }
virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; virtual btVector3 localGetSupportingVertex(const btVector3& vec)const =0;
#ifndef __SPU__ #ifndef __SPU__
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0; virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0;
@@ -64,63 +52,24 @@ public:
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0;
#endif //#ifndef __SPU__ #endif //#ifndef __SPU__
const btVector3& getImplicitShapeDimensions() const
{
return m_implicitShapeDimensions;
}
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
{
getAabbSlow(t,aabbMin,aabbMax);
}
virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
virtual void setLocalScaling(const btVector3& scaling) =0;
virtual const btVector3& getLocalScaling() const =0;
virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; virtual void setMargin(btScalar margin)=0;
virtual btScalar getMargin() const=0;
virtual void setLocalScaling(const btVector3& scaling); virtual int getNumPreferredPenetrationDirections() const=0;
virtual const btVector3& getLocalScaling() const
{
return m_localScaling;
}
const btVector3& getLocalScalingNV() const virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0;
{
return m_localScaling;
}
virtual void setMargin(btScalar margin) };
{
m_collisionMargin = margin;
}
virtual btScalar getMargin() const
{
return m_collisionMargin;
}
btScalar getMarginNV() const
{
return m_collisionMargin;
}
virtual int getNumPreferredPenetrationDirections() const
{
return 0;
}
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
{
(void)penetrationVector;
(void)index;
btAssert(0);
}
}
;

View File

@@ -19,9 +19,10 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" #include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface) btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb)
:m_stridingMesh(meshInterface) :m_stridingMesh(meshInterface)
{ {
if ( calcAabb )
recalcLocalAabb(); recalcLocalAabb();
} }
@@ -203,3 +204,113 @@ const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
{ {
return m_stridingMesh->getScaling(); return m_stridingMesh->getScaling();
} }
void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const
{
class CenterCallback: public btInternalTriangleIndexCallback
{
bool first;
btVector3 ref;
btVector3 sum;
btScalar volume;
public:
CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
{
}
virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
(void) triangleIndex;
(void) partId;
if (first)
{
ref = triangle[0];
first = false;
}
else
{
btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
volume += vol;
}
}
btVector3 getCenter()
{
return (volume > 0) ? sum / volume : ref;
}
btScalar getVolume()
{
return volume * btScalar(1. / 6);
}
};
class InertiaCallback: public btInternalTriangleIndexCallback
{
btMatrix3x3 sum;
btVector3 center;
public:
InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
{
}
virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
{
(void) triangleIndex;
(void) partId;
btMatrix3x3 i;
btVector3 a = triangle[0] - center;
btVector3 b = triangle[1] - center;
btVector3 c = triangle[2] - center;
btVector3 abc = a + b + c;
btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
for (int j = 0; j < 3; j++)
{
for (int k = 0; k <= j; k++)
{
i[j][k] = i[k][j] = volNeg * (center[j] * center[k]
+ btScalar(0.25) * (center[j] * abc[k] + center[k] * abc[j])
+ btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k])
+ btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j]));
}
}
btScalar i00 = -i[0][0];
btScalar i11 = -i[1][1];
btScalar i22 = -i[2][2];
i[0][0] = i11 + i22;
i[1][1] = i22 + i00;
i[2][2] = i00 + i11;
sum[0] += i[0];
sum[1] += i[1];
sum[2] += i[2];
}
btMatrix3x3& getInertia()
{
return sum;
}
};
CenterCallback centerCallback;
btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30));
m_stridingMesh->InternalProcessAllTriangles(&centerCallback, -aabbMax, aabbMax);
btVector3 center = centerCallback.getCenter();
principal.setOrigin(center);
volume = centerCallback.getVolume();
InertiaCallback inertiaCallback(center);
m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
btMatrix3x3& i = inertiaCallback.getInertia();
i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
inertia.setValue(i[0][0], i[1][1], i[2][2]);
inertia /= volume;
}

View File

@@ -3,20 +3,24 @@
#include "btPolyhedralConvexShape.h" #include "btPolyhedralConvexShape.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
/// btConvexTriangleMeshShape is a convex hull of a triangle mesh. If you just have a point cloud, you can use btConvexHullShape instead. /// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape.
/// It uses the btStridingMeshInterface instead of a point cloud. This can avoid the duplication of the triangle mesh data. /// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead.
class btConvexTriangleMeshShape : public btPolyhedralConvexShape class btConvexTriangleMeshShape : public btPolyhedralConvexShape
{ {
class btStridingMeshInterface* m_stridingMesh; class btStridingMeshInterface* m_stridingMesh;
public: public:
btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface); btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true);
class btStridingMeshInterface* getStridingMesh() class btStridingMeshInterface* getMeshInterface()
{
return m_stridingMesh;
}
const class btStridingMeshInterface* getMeshInterface() const
{ {
return m_stridingMesh; return m_stridingMesh;
} }
@@ -28,7 +32,7 @@ public:
virtual int getShapeType()const { return CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; } virtual int getShapeType()const { return CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; }
//debugging //debugging
virtual char* getName()const {return "ConvexTrimesh";} virtual const char* getName()const {return "ConvexTrimesh";}
virtual int getNumVertices() const; virtual int getNumVertices() const;
virtual int getNumEdges() const; virtual int getNumEdges() const;
@@ -42,6 +46,13 @@ public:
virtual void setLocalScaling(const btVector3& scaling); virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const; virtual const btVector3& getLocalScaling() const;
///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia"
///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the
///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
///of the collision object by the principal transform. This method also computes the volume of the convex mesh.
void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const;
}; };
@@ -49,3 +60,4 @@ public:
#endif //CONVEX_TRIANGLEMESH_SHAPE_H #endif //CONVEX_TRIANGLEMESH_SHAPE_H

View File

@@ -45,7 +45,7 @@ void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3&
} }
inline btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v)
{ {
const int cylinderUpAxis = 0; const int cylinderUpAxis = 0;
const int XX = 1; const int XX = 1;
@@ -163,24 +163,24 @@ const int ZZ = 1;
btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{ {
return CylinderLocalSupportX(getHalfExtents(),vec); return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec);
} }
btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{ {
return CylinderLocalSupportZ(getHalfExtents(),vec); return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec);
} }
btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{ {
return CylinderLocalSupportY(getHalfExtents(),vec); return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec);
} }
void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{ {
for (int i=0;i<numVectors;i++) for (int i=0;i<numVectors;i++)
{ {
supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtents(),vectors[i]); supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vectors[i]);
} }
} }
@@ -188,7 +188,7 @@ void btCylinderShapeZ::batchedUnitVectorGetSupportingVertexWithoutMargin(const b
{ {
for (int i=0;i<numVectors;i++) for (int i=0;i<numVectors;i++)
{ {
supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtents(),vectors[i]); supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vectors[i]);
} }
} }
@@ -199,7 +199,7 @@ void btCylinderShapeX::batchedUnitVectorGetSupportingVertexWithoutMargin(const b
{ {
for (int i=0;i<numVectors;i++) for (int i=0;i<numVectors;i++)
{ {
supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtents(),vectors[i]); supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vectors[i]);
} }
} }

View File

@@ -17,10 +17,10 @@ subject to the following restrictions:
#define CYLINDER_MINKOWSKI_H #define CYLINDER_MINKOWSKI_H
#include "btBoxShape.h" #include "btBoxShape.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#include "../../LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
/// implements cylinder shape interface /// The btCylinderShape class implements a cylinder shape primitive, centered around the origin. Its central axis aligned with the Y axis. btCylinderShapeX is aligned with the X axis and btCylinderShapeZ around the Z axis.
class btCylinderShape : public btBoxShape class btCylinderShape : public btBoxShape
{ {
@@ -60,7 +60,7 @@ public:
//use box inertia //use box inertia
// virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); // virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual int getShapeType() const virtual int getShapeType() const
{ {
@@ -74,11 +74,11 @@ public:
virtual btScalar getRadius() const virtual btScalar getRadius() const
{ {
return getHalfExtents().getX(); return getHalfExtentsWithMargin().getX();
} }
//debugging //debugging
virtual char* getName()const virtual const char* getName()const
{ {
return "CylinderY"; return "CylinderY";
} }
@@ -96,14 +96,14 @@ public:
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
//debugging //debugging
virtual char* getName()const virtual const char* getName()const
{ {
return "CylinderX"; return "CylinderX";
} }
virtual btScalar getRadius() const virtual btScalar getRadius() const
{ {
return getHalfExtents().getY(); return getHalfExtentsWithMargin().getY();
} }
}; };
@@ -121,14 +121,14 @@ public:
return 2; return 2;
} }
//debugging //debugging
virtual char* getName()const virtual const char* getName()const
{ {
return "CylinderZ"; return "CylinderZ";
} }
virtual btScalar getRadius() const virtual btScalar getRadius() const
{ {
return getHalfExtents().getX(); return getHalfExtentsWithMargin().getX();
} }
}; };

View File

@@ -40,7 +40,7 @@ void btEmptyShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aa
} }
void btEmptyShape::calculateLocalInertia(btScalar ,btVector3& ) void btEmptyShape::calculateLocalInertia(btScalar ,btVector3& ) const
{ {
btAssert(0); btAssert(0);
} }

View File

@@ -18,16 +18,16 @@ subject to the following restrictions:
#include "btConcaveShape.h" #include "btConcaveShape.h"
#include "../../LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
#include "../../LinearMath/btTransform.h" #include "LinearMath/btTransform.h"
#include "../../LinearMath/btMatrix3x3.h" #include "LinearMath/btMatrix3x3.h"
#include "btCollisionMargin.h" #include "btCollisionMargin.h"
/// btEmptyShape is a collision shape without actual collision detection. /// The btEmptyShape is a collision shape without actual collision detection shape, so most users should ignore this class.
///It can be replaced by another shape during runtime /// It can be replaced by another shape during runtime, but the inertia tensor should be recomputed.
class btEmptyShape : public btConcaveShape class btEmptyShape : public btConcaveShape
{ {
public: public:
@@ -49,12 +49,12 @@ public:
return m_localScaling; return m_localScaling;
} }
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual int getShapeType() const { return EMPTY_SHAPE_PROXYTYPE;} virtual int getShapeType() const { return EMPTY_SHAPE_PROXYTYPE;}
virtual char* getName()const virtual const char* getName()const
{ {
return "Empty"; return "Empty";
} }

View File

@@ -18,16 +18,18 @@ subject to the following restrictions:
#include "LinearMath/btTransformUtil.h" #include "LinearMath/btTransformUtil.h"
btHeightfieldTerrainShape::btHeightfieldTerrainShape(int width,int length,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges) btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
:m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), : m_heightStickWidth(heightStickWidth),
m_width(width), m_heightStickLength(heightStickLength),
m_length(length),
m_heightfieldDataUnknown(heightfieldData),
m_maxHeight(maxHeight), m_maxHeight(maxHeight),
m_upAxis(upAxis), m_width((btScalar)heightStickWidth-1),
m_length((btScalar)heightStickLength-1),
m_heightfieldDataUnknown(heightfieldData),
m_useFloatData(useFloatData), m_useFloatData(useFloatData),
m_flipQuadEdges(flipQuadEdges), m_flipQuadEdges(flipQuadEdges),
m_useDiamondSubdivision(false) m_useDiamondSubdivision(false),
m_upAxis(upAxis),
m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
{ {
@@ -43,25 +45,25 @@ m_useDiamondSubdivision(false)
case 0: case 0:
{ {
halfExtents.setValue( halfExtents.setValue(
m_maxHeight, btScalar(m_maxHeight),
m_width, btScalar(m_width), //?? don't know if this should change
m_length); btScalar(m_length));
break; break;
} }
case 1: case 1:
{ {
halfExtents.setValue( halfExtents.setValue(
m_width, btScalar(m_width),
m_maxHeight, btScalar(m_maxHeight),
m_length); btScalar(m_length));
break; break;
}; };
case 2: case 2:
{ {
halfExtents.setValue( halfExtents.setValue(
m_width, btScalar(m_width),
m_length, btScalar(m_length),
m_maxHeight btScalar(m_maxHeight)
); );
break; break;
} }
@@ -89,19 +91,15 @@ btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{ {
/*
aabbMin.setValue(-1e30f,-1e30f,-1e30f);
aabbMax.setValue(1e30f,1e30f,1e30f);
*/
btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5); btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
halfExtents += btVector3(getMargin(),getMargin(),getMargin());
btMatrix3x3 abs_b = t.getBasis().absolute(); btMatrix3x3 abs_b = t.getBasis().absolute();
btPoint3 center = t.getOrigin(); btPoint3 center = t.getOrigin();
btVector3 extent = btVector3(abs_b[0].dot(halfExtents), btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
abs_b[1].dot(halfExtents), abs_b[1].dot(halfExtents),
abs_b[2].dot(halfExtents)); abs_b[2].dot(halfExtents));
extent += btVector3(getMargin(),getMargin(),getMargin());
aabbMin = center - extent; aabbMin = center - extent;
aabbMax = center + extent; aabbMax = center + extent;
@@ -114,11 +112,11 @@ btScalar btHeightfieldTerrainShape::getHeightFieldValue(int x,int y) const
btScalar val = 0.f; btScalar val = 0.f;
if (m_useFloatData) if (m_useFloatData)
{ {
val = m_heightfieldDataFloat[(y*m_width)+x]; val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
} else } else
{ {
//assume unsigned short int //assume unsigned short int
unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_width)+x]; unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
val = heightFieldValue* (m_maxHeight/btScalar(65535)); val = heightFieldValue* (m_maxHeight/btScalar(65535));
} }
return val; return val;
@@ -133,8 +131,8 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
btAssert(x>=0); btAssert(x>=0);
btAssert(y>=0); btAssert(y>=0);
btAssert(x<m_width); btAssert(x<m_heightStickWidth);
btAssert(y<m_length); btAssert(y<m_heightStickLength);
btScalar height = getHeightFieldValue(x,y); btScalar height = getHeightFieldValue(x,y);
@@ -145,25 +143,25 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
{ {
vertex.setValue( vertex.setValue(
height, height,
(-m_width/2 ) + x, (-m_width/btScalar(2.0)) + x,
(-m_length/2 ) + y (-m_length/btScalar(2.0) ) + y
); );
break; break;
} }
case 1: case 1:
{ {
vertex.setValue( vertex.setValue(
(-m_width/2 ) + x, (-m_width/btScalar(2.0)) + x,
height, height,
(-m_length/2 ) + y (-m_length/btScalar(2.0)) + y
); );
break; break;
}; };
case 2: case 2:
{ {
vertex.setValue( vertex.setValue(
(-m_width/2 ) + x, (-m_width/btScalar(2.0)) + x,
(-m_length/2 ) + y, (-m_length/btScalar(2.0)) + y,
height height
); );
break; break;
@@ -180,20 +178,19 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
} }
void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point) const void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
{ {
btVector3 clampedPoint(point); btVector3 clampedPoint(point);
clampedPoint.setMax(m_localAabbMin); clampedPoint.setMax(m_localAabbMin);
clampedPoint.setMin(m_localAabbMax); clampedPoint.setMin(m_localAabbMax);
btVector3 v = (clampedPoint );// * m_quantization; btVector3 v = (clampedPoint);// - m_bvhAabbMin) * m_bvhQuantization;
out[0] = (int)(v.getX()); //TODO: optimization: check out how to removed this btFabs
out[1] = (int)(v.getY());
out[2] = (int)(v.getZ()); out[0] = (int)(v.getX() + v.getX() / btFabs(v.getX())* btScalar(0.5) );
//correct for out[1] = (int)(v.getY() + v.getY() / btFabs(v.getY())* btScalar(0.5) );
out[2] = (int)(v.getZ() + v.getZ() / btFabs(v.getZ())* btScalar(0.5) );
} }
@@ -212,24 +209,24 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]); btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]); btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
quantizeWithClamp(quantizedAabbMin, localAabbMin); quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
quantizeWithClamp(quantizedAabbMax, localAabbMax); quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
int startX=0; int startX=0;
int endX=m_width-1; int endX=m_heightStickWidth-1;
int startJ=0; int startJ=0;
int endJ=m_length-1; int endJ=m_heightStickLength-1;
switch (m_upAxis) switch (m_upAxis)
{ {
case 0: case 0:
{ {
quantizedAabbMin[1]+=m_width/2-1; quantizedAabbMin[1]+=m_heightStickWidth/2-1;
quantizedAabbMax[1]+=m_width/2+1; quantizedAabbMax[1]+=m_heightStickWidth/2+1;
quantizedAabbMin[2]+=m_length/2-1; quantizedAabbMin[2]+=m_heightStickLength/2-1;
quantizedAabbMax[2]+=m_length/2+1; quantizedAabbMax[2]+=m_heightStickLength/2+1;
if (quantizedAabbMin[1]>startX) if (quantizedAabbMin[1]>startX)
startX = quantizedAabbMin[1]; startX = quantizedAabbMin[1];
@@ -243,10 +240,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
} }
case 1: case 1:
{ {
quantizedAabbMin[0]+=m_width/2-1; quantizedAabbMin[0]+=m_heightStickWidth/2-1;
quantizedAabbMax[0]+=m_width/2+1; quantizedAabbMax[0]+=m_heightStickWidth/2+1;
quantizedAabbMin[2]+=m_length/2-1; quantizedAabbMin[2]+=m_heightStickLength/2-1;
quantizedAabbMax[2]+=m_length/2+1; quantizedAabbMax[2]+=m_heightStickLength/2+1;
if (quantizedAabbMin[0]>startX) if (quantizedAabbMin[0]>startX)
startX = quantizedAabbMin[0]; startX = quantizedAabbMin[0];
@@ -260,10 +257,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
}; };
case 2: case 2:
{ {
quantizedAabbMin[0]+=m_width/2-1; quantizedAabbMin[0]+=m_heightStickWidth/2-1;
quantizedAabbMax[0]+=m_width/2+1; quantizedAabbMax[0]+=m_heightStickWidth/2+1;
quantizedAabbMin[1]+=m_length/2-1; quantizedAabbMin[1]+=m_heightStickLength/2-1;
quantizedAabbMax[1]+=m_length/2+1; quantizedAabbMax[1]+=m_heightStickLength/2+1;
if (quantizedAabbMin[0]>startX) if (quantizedAabbMin[0]>startX)
startX = quantizedAabbMin[0]; startX = quantizedAabbMin[0];
@@ -290,7 +287,7 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
for(int x=startX; x<endX; x++) for(int x=startX; x<endX; x++)
{ {
btVector3 vertices[3]; btVector3 vertices[3];
if (m_flipQuadEdges || (m_useDiamondSubdivision && ((j+x) & 1))) if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
{ {
//first triangle //first triangle
getVertex(x,j,vertices[0]); getVertex(x,j,vertices[0]);
@@ -322,7 +319,7 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
} }
void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
{ {
//moving concave objects not supported //moving concave objects not supported

View File

@@ -18,7 +18,8 @@ subject to the following restrictions:
#include "btConcaveShape.h" #include "btConcaveShape.h"
///btHeightfieldTerrainShape simulates a 2D heightfield terrain ///The btHeightfieldTerrainShape simulates a 2D heightfield terrain collision shape. You can also use the more general btBvhTriangleMeshShape instead.
///An example implementation of btHeightfieldTerrainShape is provided in Demos/VehicleDemo/VehicleDemo.cpp
class btHeightfieldTerrainShape : public btConcaveShape class btHeightfieldTerrainShape : public btConcaveShape
{ {
protected: protected:
@@ -26,9 +27,11 @@ protected:
btVector3 m_localAabbMax; btVector3 m_localAabbMax;
///terrain data ///terrain data
int m_width; int m_heightStickWidth;
int m_length; int m_heightStickLength;
btScalar m_maxHeight; btScalar m_maxHeight;
btScalar m_width;
btScalar m_length;
union union
{ {
unsigned char* m_heightfieldDataUnsignedChar; unsigned char* m_heightfieldDataUnsignedChar;
@@ -45,7 +48,7 @@ protected:
btVector3 m_localScaling; btVector3 m_localScaling;
virtual btScalar getHeightFieldValue(int x,int y) const; virtual btScalar getHeightFieldValue(int x,int y) const;
void quantizeWithClamp(int* out, const btVector3& point) const; void quantizeWithClamp(int* out, const btVector3& point,int isMax) const;
void getVertex(int x,int y,btVector3& vertex) const; void getVertex(int x,int y,btVector3& vertex) const;
inline bool testQuantizedAabbAgainstQuantizedAabb(int* aabbMin1, int* aabbMax1,const int* aabbMin2,const int* aabbMax2) const inline bool testQuantizedAabbAgainstQuantizedAabb(int* aabbMin1, int* aabbMax1,const int* aabbMin2,const int* aabbMax2) const
@@ -58,7 +61,7 @@ protected:
} }
public: public:
btHeightfieldTerrainShape(int width,int height,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges); btHeightfieldTerrainShape(int heightStickWidth,int heightStickHeight,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
virtual ~btHeightfieldTerrainShape(); virtual ~btHeightfieldTerrainShape();
@@ -74,14 +77,14 @@ public:
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void setLocalScaling(const btVector3& scaling); virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const; virtual const btVector3& getLocalScaling() const;
//debugging //debugging
virtual char* getName()const {return "HEIGHTFIELD";} virtual const char* getName()const {return "HEIGHTFIELD";}
}; };

View File

@@ -26,9 +26,9 @@ m_shapeB(shapeB)
btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{ {
btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec*m_transA.getBasis())); btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(-vec*m_transA.getBasis()));
btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(vec*m_transB.getBasis())); btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(vec*m_transB.getBasis()));
return supVertexA + supVertexB; return supVertexA - supVertexB;
} }
void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
@@ -49,7 +49,7 @@ btScalar btMinkowskiSumShape::getMargin() const
} }
void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{ {
(void)mass; (void)mass;
btAssert(0); btAssert(0);

View File

@@ -16,11 +16,11 @@ subject to the following restrictions:
#ifndef MINKOWSKI_SUM_SHAPE_H #ifndef MINKOWSKI_SUM_SHAPE_H
#define MINKOWSKI_SUM_SHAPE_H #define MINKOWSKI_SUM_SHAPE_H
#include "btConvexShape.h" #include "btConvexInternalShape.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
/// btMinkowskiSumShape represents implicit (getSupportingVertex) based minkowski sum of two convex implicit shapes. /// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes.
class btMinkowskiSumShape : public btConvexShape class btMinkowskiSumShape : public btConvexInternalShape
{ {
btTransform m_transA; btTransform m_transA;
@@ -37,7 +37,7 @@ public:
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
void setTransformA(const btTransform& transA) { m_transA = transA;} void setTransformA(const btTransform& transA) { m_transA = transA;}
void setTransformB(const btTransform& transB) { m_transB = transB;} void setTransformB(const btTransform& transB) { m_transB = transB;}
@@ -53,7 +53,7 @@ public:
const btConvexShape* getShapeA() const { return m_shapeA;} const btConvexShape* getShapeA() const { return m_shapeA;}
const btConvexShape* getShapeB() const { return m_shapeB;} const btConvexShape* getShapeB() const { return m_shapeB;}
virtual char* getName()const virtual const char* getName()const
{ {
return "MinkowskiSum"; return "MinkowskiSum";
} }

View File

@@ -47,7 +47,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,cons
btVector3 vec = vec0; btVector3 vec = vec0;
btScalar lenSqr = vec.length2(); btScalar lenSqr = vec.length2();
if (lenSqr < btScalar(0.0001)) if (lenSqr < (SIMD_EPSILON*SIMD_EPSILON))
{ {
vec.setValue(1,0,0); vec.setValue(1,0,0);
} else } else
@@ -116,7 +116,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,cons
void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{ {
//as an approximation, take the inertia of the box that bounds the spheres //as an approximation, take the inertia of the box that bounds the spheres

View File

@@ -16,13 +16,14 @@ subject to the following restrictions:
#ifndef MULTI_SPHERE_MINKOWSKI_H #ifndef MULTI_SPHERE_MINKOWSKI_H
#define MULTI_SPHERE_MINKOWSKI_H #define MULTI_SPHERE_MINKOWSKI_H
#include "btConvexShape.h" #include "btConvexInternalShape.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
#define MAX_NUM_SPHERES 5 #define MAX_NUM_SPHERES 5
///btMultiSphereShape represents implicit convex hull of a collection of spheres (using getSupportingVertex) ///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes.
class btMultiSphereShape : public btConvexShape ///It is possible to animate the spheres for deformation.
class btMultiSphereShape : public btConvexInternalShape
{ {
@@ -39,7 +40,7 @@ public:
btMultiSphereShape (const btVector3& inertiaHalfExtents,const btVector3* positions,const btScalar* radi,int numSpheres); btMultiSphereShape (const btVector3& inertiaHalfExtents,const btVector3* positions,const btScalar* radi,int numSpheres);
///CollisionShape Interface ///CollisionShape Interface
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
/// btConvexShape Interface /// btConvexShape Interface
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
@@ -63,7 +64,7 @@ public:
virtual int getShapeType() const { return MULTI_SPHERE_SHAPE_PROXYTYPE; } virtual int getShapeType() const { return MULTI_SPHERE_SHAPE_PROXYTYPE; }
virtual char* getName()const virtual const char* getName()const
{ {
return "MultiSphere"; return "MultiSphere";
} }

View File

@@ -19,13 +19,12 @@ subject to the following restrictions:
#include "LinearMath/btIDebugDraw.h" #include "LinearMath/btIDebugDraw.h"
btOptimizedBvh::btOptimizedBvh()
btOptimizedBvh::btOptimizedBvh() : m_useQuantization(false),
m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
//m_traversalMode(TRAVERSAL_STACKLESS)
//m_traversalMode(TRAVERSAL_RECURSIVE)
{ {
}
btOptimizedBvh::~btOptimizedBvh()
{
} }
@@ -80,7 +79,7 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback
{ {
QuantizedNodeArray& m_triangleNodes; QuantizedNodeArray& m_triangleNodes;
const btOptimizedBvh* m_optimizedTree; // for quantization const btQuantizedBvh* m_optimizedTree; // for quantization
QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other) QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
{ {
@@ -89,14 +88,16 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
return *this; return *this;
} }
QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btOptimizedBvh* tree) QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btQuantizedBvh* tree)
:m_triangleNodes(triangleNodes),m_optimizedTree(tree) :m_triangleNodes(triangleNodes),m_optimizedTree(tree)
{ {
} }
virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
{ {
btAssert(partId==0); // The partId and triangle index must fit in the same (positive) integer
btAssert(partId < (1<<MAX_NUM_PARTS_IN_BITS));
btAssert(triangleIndex < (1<<(31-MAX_NUM_PARTS_IN_BITS)));
//negative indices are reserved for escapeIndex //negative indices are reserved for escapeIndex
btAssert(triangleIndex>=0); btAssert(triangleIndex>=0);
@@ -111,10 +112,29 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
aabbMin.setMin(triangle[2]); aabbMin.setMin(triangle[2]);
aabbMax.setMax(triangle[2]); aabbMax.setMax(triangle[2]);
m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMin[0],aabbMin); //PCK: add these checks for zero dimensions of aabb
m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMax[0],aabbMax); const btScalar MIN_AABB_DIMENSION = btScalar(0.002);
const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001);
if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION)
{
aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION);
aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION);
}
if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION)
{
aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION);
aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION);
}
if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION)
{
aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION);
aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION);
}
node.m_escapeIndexOrTriangleIndex = triangleIndex; m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
m_triangleNodes.push_back(node); m_triangleNodes.push_back(node);
} }
@@ -170,10 +190,45 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
subtree.m_rootNodeIndex = 0; subtree.m_rootNodeIndex = 0;
subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); 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();
} }
void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
{
if (m_useQuantization)
{
setQuantizationValues(aabbMin,aabbMax);
updateBvhNodes(meshInterface,0,m_curNodeIndex,0);
///now update all subtree headers
int i;
for (i=0;i<m_SubtreeHeaders.size();i++)
{
btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
}
} else
{
}
}
void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax) void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
{ {
//incrementally initialize quantization values //incrementally initialize quantization values
@@ -193,16 +248,17 @@ void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const b
unsigned short quantizedQueryAabbMin[3]; unsigned short quantizedQueryAabbMin[3];
unsigned short quantizedQueryAabbMax[3]; unsigned short quantizedQueryAabbMax[3];
quantizeWithClamp(&quantizedQueryAabbMin[0],aabbMin); quantize(&quantizedQueryAabbMin[0],aabbMin,0);
quantizeWithClamp(&quantizedQueryAabbMax[0],aabbMax); quantize(&quantizedQueryAabbMax[0],aabbMax,1);
int i; int i;
for (i=0;i<this->m_SubtreeHeaders.size();i++) for (i=0;i<this->m_SubtreeHeaders.size();i++)
{ {
btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); //PCK: unsigned instead of bool
if (overlap) unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
if (overlap != 0)
{ {
updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i); updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i);
@@ -212,36 +268,23 @@ void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const b
} }
///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 btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index) void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index)
{ {
(void)index; (void)index;
btAssert(m_useQuantization); btAssert(m_useQuantization);
int nodeSubPart=0; int curNodeSubPart=-1;
//get access info to trianglemesh data //get access info to trianglemesh data
const unsigned char *vertexbase; const unsigned char *vertexbase = 0;
int numverts; int numverts = 0;
PHY_ScalarType type; PHY_ScalarType type = PHY_INTEGER;
int stride; int stride = 0;
const unsigned char *indexbase; const unsigned char *indexbase = 0;
int indexstride; int indexstride = 0;
int numfaces; int numfaces = 0;
PHY_ScalarType indicestype; PHY_ScalarType indicestype = PHY_INTEGER;
meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
btVector3 triangleVerts[3]; btVector3 triangleVerts[3];
btVector3 aabbMin,aabbMax; btVector3 aabbMin,aabbMax;
@@ -256,16 +299,26 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f
if (curNode.isLeafNode()) if (curNode.isLeafNode())
{ {
//recalc aabb from triangle data //recalc aabb from triangle data
int nodeSubPart = curNode.getPartId();
int nodeTriangleIndex = curNode.getTriangleIndex(); int nodeTriangleIndex = curNode.getTriangleIndex();
if (nodeSubPart != curNodeSubPart)
{
if (curNodeSubPart >= 0)
meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
curNodeSubPart = nodeSubPart;
btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
}
//triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts, //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride); unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
for (int j=2;j>=0;j--) for (int j=2;j>=0;j--)
{ {
int graphicsindex = gfxbase[j]; int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
#ifdef DEBUG_PATCH_COLORS #ifdef DEBUG_PATCH_COLORS
btVector3 mycolor = color[index&3]; btVector3 mycolor = color[index&3];
@@ -292,8 +345,8 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f
aabbMin.setMin(triangleVerts[2]); aabbMin.setMin(triangleVerts[2]);
aabbMax.setMax(triangleVerts[2]); aabbMax.setMax(triangleVerts[2]);
quantizeWithClamp(&curNode.m_quantizedAabbMin[0],aabbMin); quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0);
quantizeWithClamp(&curNode.m_quantizedAabbMax[0],aabbMax); quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1);
} else } else
{ {
@@ -321,525 +374,17 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f
} }
meshInterface->unLockReadOnlyVertexBase(nodeSubPart); if (curNodeSubPart >= 0)
meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
} }
void btOptimizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin) ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
{ {
//enlarge the AABB to avoid division by zero when initializing the quantization values btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
m_bvhAabbMin = bvhAabbMin - clampValue; //we don't add additional data so just do a static upcast
m_bvhAabbMax = bvhAabbMax + clampValue; return static_cast<btOptimizedBvh*>(bvh);
btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
m_bvhQuantization = btVector3(btScalar(65535.0),btScalar(65535.0),btScalar(65535.0)) / aabbSize;
}
void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface)
{
if (m_useQuantization)
{
//calculate new aabb
btVector3 aabbMin,aabbMax;
meshInterface->calculateAabbBruteForce(aabbMin,aabbMax);
setQuantizationValues(aabbMin,aabbMax);
updateBvhNodes(meshInterface,0,m_curNodeIndex,0);
///now update all subtree headers
int i;
for (i=0;i<m_SubtreeHeaders.size();i++)
{
btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
}
} else
{
}
}
btOptimizedBvh::~btOptimizedBvh()
{
}
#ifdef DEBUG_TREE_BUILDING
int gStackDepth = 0;
int gMaxStackDepth = 0;
#endif //DEBUG_TREE_BUILDING
void btOptimizedBvh::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,btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)));
setInternalNodeAabbMin(m_curNodeIndex,btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30)));
for (i=startIndex;i<endIndex;i++)
{
mergeInternalNodeAabb(m_curNodeIndex,getAabbMin(i),getAabbMax(i));
}
m_curNodeIndex++;
//internalNode->m_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 btOptimizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex)
{
btAssert(m_useQuantization);
btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
int leftSubTreeSizeInBytes = leftSubTreeSize * sizeof(btQuantizedBvhNode);
btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
int rightSubTreeSizeInBytes = rightSubTreeSize * 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;
}
}
int btOptimizedBvh::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<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
means+=center;
}
means *= (btScalar(1.)/(btScalar)numIndices);
splitValue = means[splitAxis];
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
if (center[splitAxis] > 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));
btAssert(!unbal);
return splitIndex;
}
int btOptimizedBvh::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;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
means+=center;
}
means *= (btScalar(1.)/(btScalar)numIndices);
for (i=startIndex;i<endIndex;i++)
{
btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
btVector3 diff2 = center-means;
diff2 = diff2 * diff2;
variance += diff2;
}
variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
return variance.maxAxis();
}
void btOptimizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
//either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
if (m_useQuantization)
{
///quantize query AABB
unsigned short int quantizedQueryAabbMin[3];
unsigned short int quantizedQueryAabbMax[3];
quantizeWithClamp(quantizedQueryAabbMin,aabbMin);
quantizeWithClamp(quantizedQueryAabbMax,aabbMax);
switch (m_traversalMode)
{
case TRAVERSAL_STACKLESS:
walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,0,m_curNodeIndex);
break;
case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
walkStacklessQuantizedTreeCacheFriendly(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
break;
case TRAVERSAL_RECURSIVE:
{
const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
}
break;
default:
//unsupported
btAssert(0);
}
} else
{
walkStacklessTree(nodeCallback,aabbMin,aabbMax);
}
}
int maxIterations = 0;
void btOptimizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
btAssert(!m_useQuantization);
const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
int escapeIndex, curIndex = 0;
int walkIterations = 0;
bool aabbOverlap, isLeafNode;
while (curIndex < m_curNodeIndex)
{
//catch bugs in tree data
assert (walkIterations < m_curNodeIndex);
walkIterations++;
aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
isLeafNode = rootNode->m_escapeIndex == -1;
if (isLeafNode && aabbOverlap)
{
nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
}
if (aabbOverlap || 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 btOptimizedBvh::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 btOptimizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
{
btAssert(m_useQuantization);
bool aabbOverlap, isLeafNode;
aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax);
isLeafNode = currentNode->isLeafNode();
if (aabbOverlap)
{
if (isLeafNode)
{
nodeCallback->processNode(0,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 btOptimizedBvh::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;
const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
int escapeIndex;
bool aabbOverlap, isLeafNode;
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++;
aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
isLeafNode = rootNode->isLeafNode();
if (isLeafNode && aabbOverlap)
{
nodeCallback->processNode(0,rootNode->getTriangleIndex());
}
if (aabbOverlap || 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 btOptimizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
{
btAssert(m_useQuantization);
int i;
for (i=0;i<this->m_SubtreeHeaders.size();i++)
{
const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
if (overlap)
{
walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
subtree.m_rootNodeIndex,
subtree.m_rootNodeIndex+subtree.m_subtreeSize);
}
}
}
void btOptimizedBvh::reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
(void)nodeCallback;
(void)aabbMin;
(void)aabbMax;
//not yet, please use aabb
btAssert(0);
}
void btOptimizedBvh::quantizeWithClamp(unsigned short* out, const btVector3& point) const
{
btAssert(m_useQuantization);
btVector3 clampedPoint(point);
clampedPoint.setMax(m_bvhAabbMin);
clampedPoint.setMin(m_bvhAabbMax);
btVector3 v = (clampedPoint - m_bvhAabbMin) * m_bvhQuantization;
out[0] = (unsigned short)(v.getX()+0.5f);
out[1] = (unsigned short)(v.getY()+0.5f);
out[2] = (unsigned short)(v.getZ()+0.5f);
}
btVector3 btOptimizedBvh::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;
}
void btOptimizedBvh::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 btOptimizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex)
{
if (m_useQuantization)
{
m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
} else
{
m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
}
} }

View File

@@ -16,315 +16,48 @@ subject to the following restrictions:
#ifndef OPTIMIZED_BVH_H #ifndef OPTIMIZED_BVH_H
#define OPTIMIZED_BVH_H #define OPTIMIZED_BVH_H
#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h"
#include "../../LinearMath/btVector3.h"
//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
class btStridingMeshInterface; class btStridingMeshInterface;
//Note: currently we have 16 bytes per quantized node
#define MAX_SUBTREE_SIZE_IN_BYTES 2048
///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface.
///btQuantizedBvhNode is a compressed aabb node, 16 bytes. ATTRIBUTE_ALIGNED16(class) btOptimizedBvh : public btQuantizedBvh
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode
{ {
//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());
return m_escapeIndexOrTriangleIndex;
}
}
;
/// 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
{
//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: public:
//12 bytes BT_DECLARE_ALIGNED_ALLOCATOR();
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];
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<btOptimizedBvhNode> NodeArray;
typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
///OptimizedBvh store an AABB tree that can be quickly traversed on CPU (and SPU,GPU in future)
ATTRIBUTE_ALIGNED16(class) btOptimizedBvh
{
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;
enum btTraversalMode
{
TRAVERSAL_STACKLESS = 0,
TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
TRAVERSAL_RECURSIVE
};
btTraversalMode m_traversalMode;
BvhSubtreeInfoArray m_SubtreeHeaders;
///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)
{
quantizeWithClamp(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin);
} else
{
m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
}
}
void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
{
if (m_useQuantization)
{
quantizeWithClamp(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax);
} 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 setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
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];
quantizeWithClamp(quantizedAabbMin,newAabbMin);
quantizeWithClamp(quantizedAabbMax,newAabbMax);
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: 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 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;
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;
}
void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
public: public:
btOptimizedBvh(); btOptimizedBvh();
virtual ~btOptimizedBvh(); virtual ~btOptimizedBvh();
void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax); void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax);
void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; void refit(btStridingMeshInterface* triangles,const btVector3& aabbMin,const btVector3& aabbMax);
void reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
void quantizeWithClamp(unsigned short* out, const btVector3& point) const;
btVector3 unQuantize(const unsigned short* vecIn) const;
///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;
}
void refit(btStridingMeshInterface* triangles);
void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax); void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax);
void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index); void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index);
/// Data buffer MUST be 16 byte aligned
QuantizedNodeArray& getQuantizedNodeArray() virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian)
{ {
return m_quantizedContiguousNodes; return btQuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
} }
BvhSubtreeInfoArray& getSubtreeInfoArray() ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
{ static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
return m_SubtreeHeaders;
}
}
; };
#endif //OPTIMIZED_BVH_H #endif //OPTIMIZED_BVH_H

View File

@@ -13,7 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
*/ */
#include <BulletCollision/CollisionShapes/btPolyhedralConvexShape.h> #include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
btPolyhedralConvexShape::btPolyhedralConvexShape() btPolyhedralConvexShape::btPolyhedralConvexShape()
:m_localAabbMin(1,1,1), :m_localAabbMin(1,1,1),
@@ -95,7 +95,7 @@ void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(
void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{ {
//not yet, return box inertia //not yet, return box inertia
@@ -128,11 +128,47 @@ void btPolyhedralConvexShape::getAabb(const btTransform& trans,btVector3& aabbMi
void btPolyhedralConvexShape::setLocalScaling(const btVector3& scaling)
{
btConvexInternalShape::setLocalScaling(scaling);
recalcLocalAabb();
}
void btPolyhedralConvexShape::recalcLocalAabb() void btPolyhedralConvexShape::recalcLocalAabb()
{ {
m_isLocalAabbValid = true; m_isLocalAabbValid = true;
#if 1
static const btVector3 _directions[] =
{
btVector3( 1., 0., 0.),
btVector3( 0., 1., 0.),
btVector3( 0., 0., 1.),
btVector3( -1., 0., 0.),
btVector3( 0., -1., 0.),
btVector3( 0., 0., -1.)
};
btVector3 _supporting[] =
{
btVector3( 0., 0., 0.),
btVector3( 0., 0., 0.),
btVector3( 0., 0., 0.),
btVector3( 0., 0., 0.),
btVector3( 0., 0., 0.),
btVector3( 0., 0., 0.)
};
batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
for ( int i = 0; i < 3; ++i )
{
m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
}
#else
for (int i=0;i<3;i++) for (int i=0;i<3;i++)
{ {
btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
@@ -143,6 +179,8 @@ void btPolyhedralConvexShape::recalcLocalAabb()
tmp = localGetSupportingVertex(vec); tmp = localGetSupportingVertex(vec);
m_localAabbMin[i] = tmp[i]-m_collisionMargin; m_localAabbMin[i] = tmp[i]-m_collisionMargin;
} }
#endif
} }

View File

@@ -16,13 +16,14 @@ subject to the following restrictions:
#ifndef BU_SHAPE #ifndef BU_SHAPE
#define BU_SHAPE #define BU_SHAPE
#include "../../LinearMath/btPoint3.h" #include "LinearMath/btPoint3.h"
#include "../../LinearMath/btMatrix3x3.h" #include "LinearMath/btMatrix3x3.h"
#include "btConvexShape.h" #include "LinearMath/btAabbUtil2.h"
#include "btConvexInternalShape.h"
///PolyhedralConvexShape is an interface class for feature based (vertex/edge/face) convex shapes. ///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes.
class btPolyhedralConvexShape : public btConvexShape class btPolyhedralConvexShape : public btConvexInternalShape
{ {
protected: protected:
@@ -38,7 +39,7 @@ public:
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const
@@ -46,33 +47,14 @@ public:
//lazy evaluation of local aabb //lazy evaluation of local aabb
btAssert(m_isLocalAabbValid); btAssert(m_isLocalAabbValid);
btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax);
btAssert(m_localAabbMin.getX() <= m_localAabbMax.getX());
btAssert(m_localAabbMin.getY() <= m_localAabbMax.getY());
btAssert(m_localAabbMin.getZ() <= m_localAabbMax.getZ());
btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
btMatrix3x3 abs_b = trans.getBasis().absolute();
btPoint3 center = trans(localCenter);
btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
abs_b[1].dot(localHalfExtents),
abs_b[2].dot(localHalfExtents));
extent += btVector3(margin,margin,margin);
aabbMin = center - extent;
aabbMax = center + extent;
} }
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
virtual void setLocalScaling(const btVector3& scaling);
void recalcLocalAabb(); void recalcLocalAabb();
virtual int getNumVertices() const = 0 ; virtual int getNumVertices() const = 0 ;

View File

@@ -68,7 +68,7 @@ void btSphereShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& a
void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{ {
btScalar elem = btScalar(0.4) * mass * getMargin()*getMargin(); btScalar elem = btScalar(0.4) * mass * getMargin()*getMargin();
inertia.setValue(elem,elem,elem); inertia.setValue(elem,elem,elem);

View File

@@ -16,15 +16,17 @@ subject to the following restrictions:
#ifndef SPHERE_MINKOWSKI_H #ifndef SPHERE_MINKOWSKI_H
#define SPHERE_MINKOWSKI_H #define SPHERE_MINKOWSKI_H
#include "btConvexShape.h" #include "btConvexInternalShape.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///btSphereShape implements an implicit (getSupportingVertex) Sphere ///The btSphereShape implements an implicit sphere, centered around a local origin with radius.
ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexShape ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexInternalShape
{ {
public: public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btSphereShape (btScalar radius); btSphereShape (btScalar radius);
@@ -34,26 +36,26 @@ public:
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
virtual int getShapeType() const { return SPHERE_SHAPE_PROXYTYPE; } virtual int getShapeType() const { return SPHERE_SHAPE_PROXYTYPE; }
btScalar getRadius() const { return m_implicitShapeDimensions.getX();} btScalar getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX();}
//debugging //debugging
virtual char* getName()const {return "SPHERE";} virtual const char* getName()const {return "SPHERE";}
virtual void setMargin(btScalar margin) virtual void setMargin(btScalar margin)
{ {
btConvexShape::setMargin(margin); btConvexInternalShape::setMargin(margin);
} }
virtual btScalar getMargin() const virtual btScalar getMargin() const
{ {
//to improve gjk behaviour, use radius+margin as the full margin, so never get into the penetration case //to improve gjk behaviour, use radius+margin as the full margin, so never get into the penetration case
//this means, non-uniform scaling is not supported anymore //this means, non-uniform scaling is not supported anymore
return m_localScaling.getX() * getRadius() + btConvexShape::getMargin(); return getRadius();
} }

View File

@@ -19,10 +19,11 @@ subject to the following restrictions:
btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant) btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant)
:m_planeNormal(planeNormal), :m_planeNormal(planeNormal.normalized()),
m_planeConstant(planeConstant), m_planeConstant(planeConstant),
m_localScaling(btScalar(0.),btScalar(0.),btScalar(0.)) m_localScaling(btScalar(0.),btScalar(0.),btScalar(0.))
{ {
// btAssert( btFuzzyZero(m_planeNormal.length() - btScalar(1.)) );
} }
@@ -86,7 +87,7 @@ void btStaticPlaneShape::processAllTriangles(btTriangleCallback* callback,const
} }
void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{ {
(void)mass; (void)mass;

View File

@@ -19,8 +19,7 @@ subject to the following restrictions:
#include "btConcaveShape.h" #include "btConcaveShape.h"
///StaticPlaneShape simulates an 'infinite' plane by dynamically reporting triangles approximated by intersection of the plane with the AABB. ///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane.
///Assumed is that the other objects is not also infinite, so a reasonable sized AABB.
class btStaticPlaneShape : public btConcaveShape class btStaticPlaneShape : public btConcaveShape
{ {
protected: protected:
@@ -46,14 +45,23 @@ public:
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void setLocalScaling(const btVector3& scaling); virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const; virtual const btVector3& getLocalScaling() const;
const btVector3& getPlaneNormal() const
{
return m_planeNormal;
}
const btScalar& getPlaneConstant() const
{
return m_planeConstant;
}
//debugging //debugging
virtual char* getName()const {return "STATICPLANE";} virtual const char* getName()const {return "STATICPLANE";}
}; };

View File

@@ -51,7 +51,7 @@ void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleInde
{ {
for (gfxindex=0;gfxindex<numtriangles;gfxindex++) for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
{ {
int* tri_indices= (int*)(indexbase+gfxindex*indexstride); unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
graphicsbase = (btScalar*)(vertexbase+tri_indices[0]*stride); graphicsbase = (btScalar*)(vertexbase+tri_indices[0]*stride);
triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
graphicsbase = (btScalar*)(vertexbase+tri_indices[1]*stride); graphicsbase = (btScalar*)(vertexbase+tri_indices[1]*stride);
@@ -66,7 +66,7 @@ void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleInde
{ {
for (gfxindex=0;gfxindex<numtriangles;gfxindex++) for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
{ {
short int* tri_indices= (short int*)(indexbase+gfxindex*indexstride); unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
graphicsbase = (btScalar*)(vertexbase+tri_indices[0]*stride); graphicsbase = (btScalar*)(vertexbase+tri_indices[0]*stride);
triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
graphicsbase = (btScalar*)(vertexbase+tri_indices[1]*stride); graphicsbase = (btScalar*)(vertexbase+tri_indices[1]*stride);

View File

@@ -16,7 +16,7 @@ subject to the following restrictions:
#ifndef STRIDING_MESHINTERFACE_H #ifndef STRIDING_MESHINTERFACE_H
#define STRIDING_MESHINTERFACE_H #define STRIDING_MESHINTERFACE_H
#include "../../LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
#include "btTriangleCallback.h" #include "btTriangleCallback.h"
/// PHY_ScalarType enumerates possible scalar types. /// PHY_ScalarType enumerates possible scalar types.
@@ -29,7 +29,8 @@ typedef enum PHY_ScalarType {
PHY_FIXEDPOINT88 PHY_FIXEDPOINT88
} PHY_ScalarType; } PHY_ScalarType;
/// btStridingMeshInterface is the interface class for high performance access to triangle meshes /// The btStridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with btBvhTriangleMeshShape and some other collision shapes.
/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips.
/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory. /// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
class btStridingMeshInterface class btStridingMeshInterface
{ {
@@ -47,7 +48,7 @@ class btStridingMeshInterface
void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; virtual void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
///brute force method to calculate aabb ///brute force method to calculate aabb
void calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax); void calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax);
@@ -75,6 +76,10 @@ class btStridingMeshInterface
virtual void preallocateVertices(int numverts)=0; virtual void preallocateVertices(int numverts)=0;
virtual void preallocateIndices(int numindices)=0; virtual void preallocateIndices(int numindices)=0;
virtual bool hasPremadeAabb() const { return false; }
virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const {}
virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const {}
const btVector3& getScaling() const { const btVector3& getScaling() const {
return m_scaling; return m_scaling;
} }
@@ -84,6 +89,7 @@ class btStridingMeshInterface
} }
}; };
#endif //STRIDING_MESHINTERFACE_H #endif //STRIDING_MESHINTERFACE_H

View File

@@ -18,10 +18,10 @@ subject to the following restrictions:
#include "btPolyhedralConvexShape.h" #include "btPolyhedralConvexShape.h"
#include "../BroadphaseCollision/btBroadphaseProxy.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
///BU_Simplex1to4 implements feature based and implicit simplex of up to 4 vertices (tetrahedron, triangle, line, vertex). ///The btBU_Simplex1to4 implements tetrahedron, triangle, line, vertex collision shapes. In most cases it is better to use btConvexHullShape instead.
class btBU_Simplex1to4 : public btPolyhedralConvexShape class btBU_Simplex1to4 : public btPolyhedralConvexShape
{ {
protected: protected:
@@ -68,7 +68,7 @@ public:
///getName is for debugging ///getName is for debugging
virtual char* getName()const { return "btBU_Simplex1to4";} virtual const char* getName()const { return "btBU_Simplex1to4";}
}; };

View File

@@ -16,14 +16,7 @@ subject to the following restrictions:
#include "btTriangleBuffer.h" #include "btTriangleBuffer.h"
///example usage of this class:
// btTriangleBuffer triBuf;
// concaveShape->processAllTriangles(&triBuf,aabbMin, aabbMax);
// for (int i=0;i<triBuf.getNumTriangles();i++)
// {
// const btTriangle& tri = triBuf.getTriangle(i);
// //do something useful here with the triangle
// }

View File

@@ -17,7 +17,7 @@ subject to the following restrictions:
#define BT_TRIANGLE_BUFFER_H #define BT_TRIANGLE_BUFFER_H
#include "btTriangleCallback.h" #include "btTriangleCallback.h"
#include "../../LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
struct btTriangle struct btTriangle
{ {
@@ -29,6 +29,14 @@ struct btTriangle
}; };
///btTriangleBuffer can be useful to collect and store overlapping triangles between AABB and concave objects that support 'processAllTriangles' ///btTriangleBuffer can be useful to collect and store overlapping triangles between AABB and concave objects that support 'processAllTriangles'
///Example usage of this class:
/// btTriangleBuffer triBuf;
/// concaveShape->processAllTriangles(&triBuf,aabbMin, aabbMax);
/// for (int i=0;i<triBuf.getNumTriangles();i++)
/// {
/// const btTriangle& tri = triBuf.getTriangle(i);
/// //do something useful here with the triangle
/// }
class btTriangleBuffer : public btTriangleCallback class btTriangleBuffer : public btTriangleCallback
{ {

View File

@@ -16,9 +16,11 @@ subject to the following restrictions:
#ifndef TRIANGLE_CALLBACK_H #ifndef TRIANGLE_CALLBACK_H
#define TRIANGLE_CALLBACK_H #define TRIANGLE_CALLBACK_H
#include "../../LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
///The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles.
///This callback is called by processAllTriangles for all btConcaveShape derived class, such as btBvhTriangleMeshShape, btStaticPlaneShape and btHeightfieldTerrainShape.
class btTriangleCallback class btTriangleCallback
{ {
public: public:

View File

@@ -30,6 +30,11 @@ btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles,int* tri
} }
btTriangleIndexVertexArray::~btTriangleIndexVertexArray()
{
}
void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart)
{ {
btAssert(subpart< getNumSubParts() ); btAssert(subpart< getNumSubParts() );
@@ -38,14 +43,18 @@ void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertex
numverts = mesh.m_numVertices; numverts = mesh.m_numVertices;
(*vertexbase) = (unsigned char *) mesh.m_vertexBase; (*vertexbase) = (unsigned char *) mesh.m_vertexBase;
#ifdef BT_USE_DOUBLE_PRECISION
type = PHY_DOUBLE;
#else
type = PHY_FLOAT; type = PHY_FLOAT;
#endif
vertexStride = mesh.m_vertexStride; vertexStride = mesh.m_vertexStride;
numfaces = mesh.m_numTriangles; numfaces = mesh.m_numTriangles;
(*indexbase) = (unsigned char *)mesh.m_triangleIndexBase; (*indexbase) = (unsigned char *)mesh.m_triangleIndexBase;
indexstride = mesh.m_triangleIndexStride; indexstride = mesh.m_triangleIndexStride;
indicestype = PHY_INTEGER; indicestype = mesh.m_indexType;
} }
void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const
@@ -54,12 +63,34 @@ void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned
numverts = mesh.m_numVertices; numverts = mesh.m_numVertices;
(*vertexbase) = (const unsigned char *)mesh.m_vertexBase; (*vertexbase) = (const unsigned char *)mesh.m_vertexBase;
#ifdef BT_USE_DOUBLE_PRECISION
type = PHY_DOUBLE;
#else
type = PHY_FLOAT; type = PHY_FLOAT;
#endif
vertexStride = mesh.m_vertexStride; vertexStride = mesh.m_vertexStride;
numfaces = mesh.m_numTriangles; numfaces = mesh.m_numTriangles;
(*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase; (*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase;
indexstride = mesh.m_triangleIndexStride; indexstride = mesh.m_triangleIndexStride;
indicestype = PHY_INTEGER; indicestype = mesh.m_indexType;
}
bool btTriangleIndexVertexArray::hasPremadeAabb() const
{
return (m_hasAabb == 1);
}
void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax )
{
m_aabbMin = aabbMin;
m_aabbMax = aabbMax;
m_hasAabb = 1; // this is intentionally an int see notes in header
}
void btTriangleIndexVertexArray::getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const
{
*aabbMin = m_aabbMin;
*aabbMax = m_aabbMax;
} }

View File

@@ -17,48 +17,62 @@ subject to the following restrictions:
#define BT_TRIANGLE_INDEX_VERTEX_ARRAY_H #define BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
#include "btStridingMeshInterface.h" #include "btStridingMeshInterface.h"
#include "../../LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btScalar.h"
///IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements
///instead of the number of indices, we pass the number of triangles ///The btIndexedMesh indexes a single vertex and index array. Multiple btIndexedMesh objects can be passed into a btTriangleIndexVertexArray using addIndexedMesh.
///todo: explain with pictures ///Instead of the number of indices, we pass the number of triangles.
ATTRIBUTE_ALIGNED16( struct) btIndexedMesh ATTRIBUTE_ALIGNED16( struct) btIndexedMesh
{ {
BT_DECLARE_ALIGNED_ALLOCATOR();
int m_numTriangles; int m_numTriangles;
const unsigned char * m_triangleIndexBase; const unsigned char * m_triangleIndexBase;
int m_triangleIndexStride; int m_triangleIndexStride;
int m_numVertices; int m_numVertices;
const unsigned char * m_vertexBase; const unsigned char * m_vertexBase;
int m_vertexStride; int m_vertexStride;
int pad[2]; // The index type is set when adding an indexed mesh to the
// btTriangleIndexVertexArray, do not set it manually
PHY_ScalarType m_indexType;
int pad;
} }
; ;
typedef btAlignedObjectArray<btIndexedMesh> IndexedMeshArray; typedef btAlignedObjectArray<btIndexedMesh> IndexedMeshArray;
///TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays. ///The btTriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays.
///Additional meshes can be added using addIndexedMesh ///Additional meshes can be added using addIndexedMesh
///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays. ///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays.
///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray. ///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray.
ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface
{ {
protected:
IndexedMeshArray m_indexedMeshes; IndexedMeshArray m_indexedMeshes;
int m_pad[3]; int m_pad[2];
int m_hasAabb; // using int instead of bool to maintain alignment
btVector3 m_aabbMin;
btVector3 m_aabbMax;
public: public:
btTriangleIndexVertexArray() BT_DECLARE_ALIGNED_ALLOCATOR();
btTriangleIndexVertexArray() : m_hasAabb(0)
{ {
} }
//just to be backwards compatible virtual ~btTriangleIndexVertexArray();
btTriangleIndexVertexArray(int numTriangleIndices,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride);
void addIndexedMesh(const btIndexedMesh& mesh) //just to be backwards compatible
btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride);
void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
{ {
m_indexedMeshes.push_back(mesh); m_indexedMeshes.push_back(mesh);
m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType;
} }
@@ -91,6 +105,10 @@ public:
virtual void preallocateVertices(int numverts){(void) numverts;} virtual void preallocateVertices(int numverts){(void) numverts;}
virtual void preallocateIndices(int numindices){(void) numindices;} virtual void preallocateIndices(int numindices){(void) numindices;}
virtual bool hasPremadeAabb() const;
virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax );
virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const;
} }
; ;

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