Compare commits

..

29 Commits

Author SHA1 Message Date
baca8611e5 Merge branch 'master' into active-fcurve-keyframe 2020-09-01 12:38:05 -05:00
31705201dd Merge branch 'master' into active-fcurve-keyframe 2020-08-12 14:19:05 -04:00
ea4c327c97 Merge branch 'master' into active-fcurve-keyframe 2020-07-16 14:15:37 -04:00
e18fdef39f Deselect before set active on shift click 2020-07-10 09:35:39 -04:00
1fbd713265 Remove unecessary comment 2020-07-10 09:35:25 -04:00
736636ca49 Remove accidental changes 2020-07-10 09:15:48 -04:00
ff155a6677 Merge branch 'master' into active-fcurve-keyframe 2020-07-10 09:05:44 -04:00
d2a07a0bbf Merge branch 'master' into active-fcurve-keyframe 2020-07-07 21:46:27 -04:00
b890b97b67 Merge branch 'master' into active-fcurve-keyframe 2020-07-07 14:53:35 -04:00
ce170bdd4c Always draw active FCurve (and active keyframe) last (on top) 2020-06-24 20:20:42 -04:00
fc1fee9916 Merge branch 'master' into active-fcurve-keyframe 2020-06-24 16:10:53 -04:00
9d9efbb2f8 insert_vert_fcurve sets active keyframe 2020-06-09 11:11:33 -04:00
21d542d068 Activate keyframe before deselecting 2020-06-09 11:11:16 -04:00
aa5ad440a3 Merge branch 'master' into active-fcurve-keyframe 2020-06-09 09:45:28 -04:00
3fe313b954 Don't change active vertex or fcurve when dragging 2020-06-03 15:06:10 -04:00
2a7b44e33d Cleanup: Use const for FCurve 2020-06-03 15:05:42 -04:00
598cac0ce6 Clamp active keyframe to totvert when deleting 2020-06-03 15:05:26 -04:00
1fc49878f5 Changes from Julian 2020-06-03 13:48:48 -04:00
30a4fbf57b Merge branch 'master' into active-fcurve-keyframe 2020-06-03 13:41:42 -04:00
b49bcbe68e Remove dopesheet drawing changes 2020-05-19 10:38:15 -04:00
7ac3dc69a8 Merge branch 'master' into active-fcurve-keyframe 2020-05-19 10:29:16 -04:00
81bdaefbd7 Draw active keyframe differently in dopesheet 2020-05-18 12:53:48 -04:00
ba1efe851e Move active graph vertex drawing to separate functions 2020-05-18 12:52:55 -04:00
dc68db427a Change set active logic 2020-05-18 12:36:39 -04:00
03a8e74405 Merge branch 'master' into active-fcurve-keyframe 2020-05-18 09:27:27 -04:00
c452c66b70 Remove unintentional change 2020-05-14 17:08:17 -04:00
d4ddba4b59 Fix T76595: No Indication of Active Keyframe in Graph Editor
Currently there is a panel that says "Active Keyframe" for numerically editing one keyframe's values, but in the code there is no concept of the "active keyframe."

This patch adds an "active keyframe index" to each FCurve, and displays it with a theme color for the active vertex (which didn't exist before) if the FCurve is active.

{F8536092}

The active keyframe is not currently set for select operations other than basic click-select, which mirrors the behavior in the 3D view.

Differential Revision: https://developer.blender.org/D7737
2020-05-14 17:06:24 -04:00
83c9b99e76 Add active keyframe to FCurve, draw and mark with clickselect 2020-05-14 16:42:13 -04:00
09d9ef45c6 Add active vertex theme color for graph editor 2020-05-14 16:40:48 -04:00
1269 changed files with 65957 additions and 94182 deletions

View File

@@ -1,6 +1,3 @@
# The warnings below are disabled because they are too pedantic and not worth fixing.
# Some of them will be enabled as part of the Clang-Tidy task, see T78535.
Checks: >
-*,
readability-*,
@@ -15,7 +12,13 @@ Checks: >
-readability-misleading-indentation,
-readability-inconsistent-declaration-parameter-name,
-readability-redundant-preprocessor,
-readability-redundant-member-init,
-readability-const-return-type,
-readability-static-accessed-through-instance,
-readability-redundant-declaration,
-readability-qualified-auto,
-readability-use-anyofallof,
bugprone-*,
@@ -27,5 +30,7 @@ Checks: >
-bugprone-sizeof-expression,
-bugprone-integer-division,
-bugprone-incorrect-roundings,
-bugprone-copy-constructor-init,
WarningsAsErrors: '*'

View File

@@ -128,9 +128,7 @@ enable_testing()
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin CACHE INTERNAL "" FORCE)
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib CACHE INTERNAL "" FORCE)
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(GENERATOR_IS_MULTI_CONFIG)
if(MSVC)
set(TESTS_OUTPUT_DIR ${EXECUTABLE_OUTPUT_PATH}/tests/$<CONFIG>/ CACHE INTERNAL "" FORCE)
else()
set(TESTS_OUTPUT_DIR ${EXECUTABLE_OUTPUT_PATH}/tests/ CACHE INTERNAL "" FORCE)
@@ -512,21 +510,9 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
-fno-sanitize=alignment \
")
if(MSVC)
# clang-cl doesn't support all sanitizers, but leak and object-size give errors/warnings.
set(_asan_defaults "${_asan_defaults}")
elseif(APPLE)
# AppleClang doesn't support all sanitizers, but leak gives error.
if(CMAKE_BUILD_TYPE MATCHES "Debug")
# Silence the warning that object-size is not effective in -O0.
set(_asan_defaults "${_asan_defaults}")
else()
set(_asan_defaults "${_asan_defaults} -fsanitize=object-size")
endif()
else()
set(_asan_defaults "${_asan_defaults} -fsanitize=leak -fsanitize=object-size")
if(NOT MSVC) # not all sanitizers are supported with clang-cl, these two however are very vocal about it
set(_asan_defaults "${_asan_defaults} -fsanitize=leak -fsanitize=object-size" )
endif()
set(COMPILER_ASAN_CFLAGS "${_asan_defaults}" CACHE STRING "C flags for address sanitizer")
mark_as_advanced(COMPILER_ASAN_CFLAGS)
set(COMPILER_ASAN_CXXFLAGS "${_asan_defaults}" CACHE STRING "C++ flags for address sanitizer")
@@ -534,31 +520,16 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
unset(_asan_defaults)
if(MSVC)
find_library(
COMPILER_ASAN_LIBRARY NAMES clang_rt.asan-x86_64
if(NOT MSVC)
find_library(COMPILER_ASAN_LIBRARY asan ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
else()
find_library(
COMPILER_ASAN_LIBRARY NAMES clang_rt.asan-x86_64
PATHS
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/7.0.0/lib/windows
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/6.0.0/lib/windows
)
elseif(APPLE)
execute_process(COMMAND ${CMAKE_CXX_COMPILER}
-print-file-name=lib
OUTPUT_VARIABLE CLANG_LIB_DIR
)
string(STRIP "${CLANG_LIB_DIR}" CLANG_LIB_DIR)
find_library(
COMPILER_ASAN_LIBRARY NAMES libclang_rt.asan_osx_dynamic.dylib
PATHS
"${CLANG_LIB_DIR}/darwin/"
)
unset(CLANG_LIB_DIR)
else()
find_library(
COMPILER_ASAN_LIBRARY asan ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}
)
endif()
mark_as_advanced(COMPILER_ASAN_LIBRARY)
endif()
endif()
@@ -852,9 +823,6 @@ if(NOT CMAKE_BUILD_TYPE MATCHES "Release")
if(MSVC)
set(COMPILER_ASAN_LINKER_FLAGS "/FUNCTIONPADMIN:6")
endif()
if(APPLE)
set(COMPILER_ASAN_LINKER_FLAGS "-fno-omit-frame-pointer -fsanitize=address")
endif(APPLE)
if(COMPILER_ASAN_LIBRARY)
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS};${COMPILER_ASAN_LIBRARY}")
set(PLATFORM_LINKFLAGS "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")

View File

@@ -81,19 +81,11 @@ Static Source Code Checking
* check_splint: Run blenders source through splint (C only).
* check_sparse: Run blenders source through sparse (C only).
* check_smatch: Run blenders source through smatch (C only).
* check_descriptions: Check for duplicate/invalid descriptions.
Spell Checkers
* check_spelling_c: Check for spelling errors (C/C++ only),
* check_spelling_c: Check for spelling errors (C/C++ only).
* check_spelling_c_qtc: Same as check_spelling_c but outputs QtCreator tasks format.
* check_spelling_osl: Check for spelling errors (OSL only).
* check_spelling_py: Check for spelling errors (Python only).
Note that spell checkers can tak a 'CHECK_SPELLING_CACHE' filepath argument,
so re-running does not need to re-check unchanged files.
Example:
make check_spelling_c CHECK_SPELLING_CACHE=../spelling_cache.data
* check_descriptions: Check for duplicate/invalid descriptions.
Utilities
Not associated with building Blender.
@@ -465,17 +457,26 @@ check_spelling_c: .FORCE
cd "$(BUILD_DIR)" ; \
PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
--cache-file=$(CHECK_SPELLING_CACHE) \
"$(BLENDER_DIR)/source" \
"$(BLENDER_DIR)/intern/cycles" \
"$(BLENDER_DIR)/intern/guardedalloc" \
"$(BLENDER_DIR)/intern/ghost" \
check_spelling_c_qtc: .FORCE
cd "$(BUILD_DIR)" ; USE_QTC_TASK=1 \
PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
"$(BLENDER_DIR)/source" \
"$(BLENDER_DIR)/intern/cycles" \
"$(BLENDER_DIR)/intern/guardedalloc" \
"$(BLENDER_DIR)/intern/ghost" \
> \
"$(BLENDER_DIR)/check_spelling_c.tasks"
check_spelling_osl: .FORCE
cd "$(BUILD_DIR)" ;\
PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_spelling.py" \
--cache-file=$(CHECK_SPELLING_CACHE) \
"$(BLENDER_DIR)/intern/cycles/kernel/shaders"
check_descriptions: .FORCE

View File

@@ -25,13 +25,6 @@ else()
set(GMP_OPTIONS --enable-static --disable-shared )
endif()
if(APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64"))
set(GMP_OPTIONS
${GMP_OPTIONS}
--disable-assembly
)
endif()
ExternalProject_Add(external_gmp
URL ${GMP_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}

View File

@@ -21,7 +21,7 @@
# <pep8 compliant>
import sys
if sys.version_info.major < 3:
if not sys.version.startswith("3"):
print("\nPython3.x needed, found %s.\nAborting!\n" %
sys.version.partition(" ")[0])
sys.exit(1)

View File

@@ -154,11 +154,3 @@ if(NOT ${CMAKE_GENERATOR} MATCHES "Xcode")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
add_definitions("-DMACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
endif()
if(${CMAKE_GENERATOR} MATCHES "Xcode")
# Generate schemes in Blender.xcodeproj/xcshareddata/xcschemes/ early, at
# configuration time, not when Xcode is opened.
# This gets rid of "Manage schemes automatically" confirmation dialog that
# appears whenever CMake is run.
set(CMAKE_XCODE_GENERATE_SCHEME ON)
endif()

View File

@@ -149,8 +149,8 @@ include(build_files/cmake/platform/platform_win32_bundle_crt.cmake)
remove_cc_flag("/MDd" "/MD" "/Zi")
if(WITH_WINDOWS_PDB)
set(PDB_INFO_OVERRIDE_FLAGS "/Z7")
set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
set(PDB_INFO_OVERRIDE_FLAGS "/Z7")
set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
endif()
if(MSVC_CLANG) # Clangs version of cl doesn't support all flags

View File

@@ -5,14 +5,6 @@ if(WITH_WINDOWS_BUNDLE_CRT)
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
set(CMAKE_INSTALL_OPENMP_LIBRARIES ${WITH_OPENMP})
# This sometimes can change when updates are installed and the compiler version
# changes, so test if it exists and if not, give InstallRequiredSystemLibraries
# another chance to figure out the path.
if(MSVC_REDIST_DIR AND NOT EXISTS "${MSVC_REDIST_DIR}")
unset(MSVC_REDIST_DIR CACHE)
endif()
include(InstallRequiredSystemLibraries)
# Install the CRT to the blender.crt Sub folder.

View File

@@ -25,8 +25,8 @@ __all__ = (
import sys
if not sys.version_info.major < 3:
print("\nPython3.x or newer needed, found %s.\nAborting!\n" %
if not sys.version.startswith("3"):
print("\nPython3.x needed, found %s.\nAborting!\n" %
sys.version.partition(" ")[0])
sys.exit(1)

View File

@@ -270,7 +270,7 @@ AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, int sampl
return length;
}
AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate, void(*callback)(float, void*), void* data)
AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate)
{
try
{
@@ -280,7 +280,7 @@ AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned i
std::shared_ptr<IReader> reader = f->createQualityReader();
reader->seek(start);
std::shared_ptr<IWriter> writer = FileWriter::createWriter(filename, convCToDSpec(specs), static_cast<Container>(format), static_cast<Codec>(codec), bitrate);
FileWriter::writeReader(reader, writer, length, buffersize, callback, data);
FileWriter::writeReader(reader, writer, length, buffersize);
return nullptr;
}
@@ -290,7 +290,7 @@ AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned i
}
}
AUD_API const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate, void(*callback)(float, void*), void* data)
AUD_API const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate)
{
try
{
@@ -326,7 +326,7 @@ AUD_API const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start
std::shared_ptr<IReader> reader = f->createQualityReader();
reader->seek(start);
FileWriter::writeReader(reader, writers, length, buffersize, callback, data);
FileWriter::writeReader(reader, writers, length, buffersize);
return nullptr;
}

View File

@@ -68,15 +68,12 @@ extern AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, in
* \param format The file's container format.
* \param codec The codec used for encoding the audio data.
* \param bitrate The bitrate for encoding.
* \param callback A callback function that is called periodically during mixdown, reporting progress if length > 0. Can be NULL.
* \param data Pass through parameter that is passed to the callback.
* \return An error message or NULL in case of success.
*/
extern AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length,
unsigned int buffersize, const char* filename,
AUD_DeviceSpecs specs, AUD_Container format,
AUD_Codec codec, unsigned int bitrate,
void(*callback)(float, void*), void* data);
AUD_Codec codec, unsigned int bitrate);
/**
* Mixes a sound down into multiple files.
@@ -89,15 +86,12 @@ extern AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, uns
* \param format The file's container format.
* \param codec The codec used for encoding the audio data.
* \param bitrate The bitrate for encoding.
* \param callback A callback function that is called periodically during mixdown, reporting progress if length > 0. Can be NULL.
* \param data Pass through parameter that is passed to the callback.
* \return An error message or NULL in case of success.
*/
extern AUD_API const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length,
unsigned int buffersize, const char* filename,
AUD_DeviceSpecs specs, AUD_Container format,
AUD_Codec codec, unsigned int bitrate,
void(*callback)(float, void*), void* data);
AUD_Codec codec, unsigned int bitrate);
/**
* Opens a read device and prepares it for mixdown of the sound scene.

View File

@@ -63,7 +63,7 @@ public:
* \param length How many samples should be transferred.
* \param buffersize How many samples should be transferred at once.
*/
static void writeReader(std::shared_ptr<IReader> reader, std::shared_ptr<IWriter> writer, unsigned int length, unsigned int buffersize, void(*callback)(float, void*) = nullptr, void* data = nullptr);
static void writeReader(std::shared_ptr<IReader> reader, std::shared_ptr<IWriter> writer, unsigned int length, unsigned int buffersize);
/**
* Writes a reader to several writers.
@@ -72,7 +72,7 @@ public:
* \param length How many samples should be transferred.
* \param buffersize How many samples should be transferred at once.
*/
static void writeReader(std::shared_ptr<IReader> reader, std::vector<std::shared_ptr<IWriter> >& writers, unsigned int length, unsigned int buffersize, void(*callback)(float, void*) = nullptr, void* data = nullptr);
static void writeReader(std::shared_ptr<IReader> reader, std::vector<std::shared_ptr<IWriter> >& writers, unsigned int length, unsigned int buffersize);
};
AUD_NAMESPACE_END

View File

@@ -27,7 +27,7 @@ std::shared_ptr<IWriter> FileWriter::createWriter(std::string filename,DeviceSpe
return FileManager::createWriter(filename, specs, format, codec, bitrate);
}
void FileWriter::writeReader(std::shared_ptr<IReader> reader, std::shared_ptr<IWriter> writer, unsigned int length, unsigned int buffersize, void(*callback)(float, void*), void* data)
void FileWriter::writeReader(std::shared_ptr<IReader> reader, std::shared_ptr<IWriter> writer, unsigned int length, unsigned int buffersize)
{
Buffer buffer(buffersize * AUD_SAMPLE_SIZE(writer->getSpecs()));
sample_t* buf = buffer.getBuffer();
@@ -53,18 +53,10 @@ void FileWriter::writeReader(std::shared_ptr<IReader> reader, std::shared_ptr<IW
}
writer->write(len, buf);
if(callback)
{
float progress = -1;
if(length > 0)
progress = pos / float(length);
callback(progress, data);
}
}
}
void FileWriter::writeReader(std::shared_ptr<IReader> reader, std::vector<std::shared_ptr<IWriter> >& writers, unsigned int length, unsigned int buffersize, void(*callback)(float, void*), void* data)
void FileWriter::writeReader(std::shared_ptr<IReader> reader, std::vector<std::shared_ptr<IWriter> >& writers, unsigned int length, unsigned int buffersize)
{
Buffer buffer(buffersize * AUD_SAMPLE_SIZE(reader->getSpecs()));
Buffer buffer2(buffersize * sizeof(sample_t));
@@ -97,14 +89,6 @@ void FileWriter::writeReader(std::shared_ptr<IReader> reader, std::vector<std::s
writers[channel]->write(len, buf2);
}
if(callback)
{
float progress = -1;
if(length > 0)
progress = pos / float(length);
callback(progress, data);
}
}
}

View File

@@ -18,16 +18,6 @@
# All rights reserved.
# ***** END GPL LICENSE BLOCK *****
# avoid noisy warnings
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
remove_cc_flag(
"-Wall"
)
endif()
# Use double precision to make simulations of small objects stable.
add_definitions(-DBT_USE_DOUBLE_PRECISION)
set(INC
.
src
@@ -44,6 +34,7 @@ set(SRC
src/BulletCollision/BroadphaseCollision/btDbvt.cpp
src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
src/BulletCollision/BroadphaseCollision/btDispatcher.cpp
src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
@@ -91,14 +82,12 @@ set(SRC
src/BulletCollision/CollisionShapes/btCylinderShape.cpp
src/BulletCollision/CollisionShapes/btEmptyShape.cpp
src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
src/BulletCollision/CollisionShapes/btMiniSDF.cpp
src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
src/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp
src/BulletCollision/CollisionShapes/btShapeHull.cpp
src/BulletCollision/CollisionShapes/btSphereShape.cpp
src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
@@ -152,6 +141,7 @@ set(SRC
src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp
src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
src/BulletDynamics/Dynamics/Bullet-C-API.cpp
src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
src/BulletDynamics/Dynamics/btRigidBody.cpp
src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
@@ -184,7 +174,6 @@ set(SRC
src/LinearMath/btPolarDecomposition.cpp
src/LinearMath/btQuickprof.cpp
src/LinearMath/btSerializer.cpp
src/LinearMath/btSerializer64.cpp
src/LinearMath/btVector3.cpp
src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
@@ -194,6 +183,7 @@ set(SRC
src/BulletCollision/BroadphaseCollision/btDbvt.h
src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
src/BulletCollision/BroadphaseCollision/btDispatcher.h
src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
@@ -247,14 +237,12 @@ set(SRC
src/BulletCollision/CollisionShapes/btEmptyShape.h
src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
src/BulletCollision/CollisionShapes/btMaterial.h
src/BulletCollision/CollisionShapes/btMiniSDF.h
src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
src/BulletCollision/CollisionShapes/btMultiSphereShape.h
src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
src/BulletCollision/CollisionShapes/btOptimizedBvh.h
src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
src/BulletCollision/CollisionShapes/btSdfCollisionShape.h
src/BulletCollision/CollisionShapes/btShapeHull.h
src/BulletCollision/CollisionShapes/btSphereShape.h
src/BulletCollision/CollisionShapes/btStaticPlaneShape.h
@@ -416,6 +404,7 @@ set(SRC
src/btBulletCollisionCommon.h
src/btBulletDynamicsCommon.h
src/Bullet-C-Api.h
)
set(LIB

368
extern/bullet2/patches/blender.patch vendored Normal file
View File

@@ -0,0 +1,368 @@
diff --git a/extern/bullet2/src/LinearMath/btVector3.h b/extern/bullet2/src/LinearMath/btVector3.h
index 839b19c..3058195 100644
--- a/extern/bullet2/src/LinearMath/btVector3.h
+++ b/extern/bullet2/src/LinearMath/btVector3.h
@@ -39,7 +39,7 @@ subject to the following restrictions:
#endif
-#define BT_SHUFFLE(x,y,z,w) ((w)<<6 | (z)<<4 | (y)<<2 | (x))
+#define BT_SHUFFLE(x,y,z,w) (((w) << 6 | (z) << 4 | (y) << 2 | (x)) & 0xff)
//#define bt_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
#define bt_pshufd_ps( _a, _mask ) _mm_shuffle_ps((_a), (_a), (_mask) )
#define bt_splat3_ps( _a, _i ) bt_pshufd_ps((_a), BT_SHUFFLE(_i,_i,_i, 3) )
diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h
--- a/extern/bullet2/src/LinearMath/btScalar.h
+++ b/extern/bullet2/src/LinearMath/btScalar.h
@@ -16,6 +16,9 @@
#ifndef BT_SCALAR_H
#define BT_SCALAR_H
+#if defined(_MSC_VER) && defined(__clang__) /* clang supplies it's own overloads already */
+#define BT_NO_SIMD_OPERATOR_OVERLOADS
+#endif
#ifdef BT_MANAGED_CODE
//Aligned data types not supported in managed code
@@ -83,7 +86,7 @@
#ifdef BT_USE_SSE
#if (_MSC_FULL_VER >= 170050727)//Visual Studio 2012 can compile SSE4/FMA3 (but SSE4/FMA3 is not enabled by default)
- #define BT_ALLOW_SSE4
+ //#define BT_ALLOW_SSE4 //disable this cause blender targets sse2
#endif //(_MSC_FULL_VER >= 160040219)
//BT_USE_SSE_IN_API is disabled under Windows by default, because
@@ -102,7 +105,7 @@
#endif //__MINGW32__
#ifdef BT_DEBUG
- #ifdef _MSC_VER
+ #if defined(_MSC_VER) && !defined(__clang__)
#include <stdio.h>
#define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak(); }}
#else//_MSC_VER
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
index be9eca6..ec40c96 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
@@ -15,7 +15,7 @@ subject to the following restrictions:
/**
- * @mainpage Bullet Documentation
+ * @page Bullet Documentation
*
* @section intro_sec Introduction
* Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ).
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
index 36dd043..57eb817 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
@@ -579,14 +579,10 @@ btCollisionShape* btCollisionWorldImporter::convertCollisionShape( btCollisionS
btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData;
btCompoundShape* compoundShape = createCompoundShape();
- btCompoundShapeChildData* childShapeDataArray = &compoundData->m_childShapePtr[0];
-
btAlignedObjectArray<btCollisionShape*> childShapes;
for (int i=0;i<compoundData->m_numChildShapes;i++)
{
- btCompoundShapeChildData* ptr = &compoundData->m_childShapePtr[i];
-
btCollisionShapeData* cd = compoundData->m_childShapePtr[i].m_childShape;
btCollisionShape* childShape = convertCollisionShape(cd);
diff --git a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
index 57fc119..31faf1d 100644
--- a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
+++ b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
@@ -29,14 +29,11 @@ subject to the following restrictions:
static btVector3
getNormalizedVector(const btVector3& v)
{
- btScalar l = v.length();
- btVector3 n = v;
- if (l < SIMD_EPSILON) {
- n.setValue(0,0,0);
- } else {
- n /= l;
- }
+ btVector3 n(0, 0, 0);
+ if (v.length() > SIMD_EPSILON) {
+ n = v.normalized();
+ }
return n;
}
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h
index 27ccefe..8e4456e 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h
@@ -37,8 +37,13 @@ struct btSimdScalar
{
}
-
+/* workaround for clang 3.4 ( == apple clang 5.1 ) issue, friction would fail with forced inlining */
+#if (defined(__clang__) && defined(__apple_build_version__) && (__clang_major__ == 5) && (__clang_minor__ == 1)) \
+|| (defined(__clang__) && !defined(__apple_build_version__) && (__clang_major__ == 3) && (__clang_minor__ == 4))
+ inline __attribute__ ((noinline)) btSimdScalar(float fl)
+#else
SIMD_FORCE_INLINE btSimdScalar(float fl)
+#endif
:m_vec128 (_mm_set1_ps(fl))
{
}
diff --git a/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBody.cpp b/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBody.cpp
index 5d62da7..fcd312e 100644
--- a/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBody.cpp
+++ b/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBody.cpp
@@ -28,7 +28,6 @@
#include "btMultiBodyJointFeedback.h"
#include "LinearMath/btTransformUtil.h"
#include "LinearMath/btSerializer.h"
-#include "Bullet3Common/b3Logging.h"
// #define INCLUDE_GYRO_TERM
///todo: determine if we need these options. If so, make a proper API, otherwise delete those globals
@@ -1732,7 +1731,6 @@ void btMultiBody::goToSleep()
void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep)
{
- int num_links = getNumLinks();
extern bool gDisableDeactivation;
if (!m_canSleep || gDisableDeactivation)
{
diff --git a/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
index 8a034b3..4f66b20 100644
--- a/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
+++ b/extern/bullet2/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
@@ -809,7 +809,6 @@ static void applyJointFeedback(btMultiBodyJacobianData& data, const btMultiBodyS
}
#endif
-#include "Bullet3Common/b3Logging.h"
void btMultiBodyConstraintSolver::writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint& c, btScalar deltaTime)
{
#if 1
diff --git a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h
index bcf0c79..8992ddb 100644
--- a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h
+++ b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h
@@ -185,7 +185,6 @@ struct btSparseSdf
{
++nprobes;
++ncells;
- int sz = sizeof(Cell);
if (ncells>m_clampCells)
{
static int numResets=0;
diff --git a/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp b/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp
index d58ac95..3fd77df 100644
--- a/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp
+++ b/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp
@@ -2665,6 +2665,7 @@ btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, in
}
vertices.resize(0);
+ original_vertex_index.resize(0);
edges.resize(0);
faces.resize(0);
@@ -2675,6 +2676,7 @@ btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, in
{
btConvexHullInternal::Vertex* v = oldVertices[copied];
vertices.push_back(hull.getCoordinates(v));
+ original_vertex_index.push_back(v->point.index);
btConvexHullInternal::Edge* firstEdge = v->edges;
if (firstEdge)
{
diff --git a/extern/bullet2/src/LinearMath/btConvexHullComputer.h b/extern/bullet2/src/LinearMath/btConvexHullComputer.h
index 7240ac4..6871ce8 100644
--- a/extern/bullet2/src/LinearMath/btConvexHullComputer.h
+++ b/extern/bullet2/src/LinearMath/btConvexHullComputer.h
@@ -67,6 +67,7 @@ class btConvexHullComputer
// Vertices of the output hull
btAlignedObjectArray<btVector3> vertices;
+ btAlignedObjectArray<int> original_vertex_index;
// Edges of the output hull
btAlignedObjectArray<Edge> edges;
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp
index 0623e35..02ea503 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp
@@ -13,9 +13,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined (_WIN32) || defined (__i386__)
-#define BT_USE_SSE_IN_API
-#endif
+//#if defined (_WIN32) || defined (__i386__)
+//#define BT_USE_SSE_IN_API
+//#endif
#include "btConvexHullShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp
index b56d729..88018b4 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp
@@ -13,9 +13,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined (_WIN32) || defined (__i386__)
-#define BT_USE_SSE_IN_API
-#endif
+//#if defined (_WIN32) || defined (__i386__)
+//#define BT_USE_SSE_IN_API
+//#endif
#include "btConvexShape.h"
#include "btTriangleShape.h"
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
index a7362ea..6abfdff 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
@@ -13,9 +13,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined (_WIN32) || defined (__i386__)
-#define BT_USE_SSE_IN_API
-#endif
+//#if defined (_WIN32) || defined (__i386__)
+//#define BT_USE_SSE_IN_API
+//#endif
#include "btMultiSphereShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
index 4854f37..9095c59 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
@@ -12,9 +12,9 @@ subject to the following restrictions:
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.
*/
-#if defined (_WIN32) || defined (__i386__)
-#define BT_USE_SSE_IN_API
-#endif
+//#if defined (_WIN32) || defined (__i386__)
+//#define BT_USE_SSE_IN_API
+//#endif
#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
#include "btConvexPolyhedron.h"
diff --git a/extern/bullet2/src/LinearMath/btVector3.cpp b/extern/bullet2/src/LinearMath/btVector3.cpp
index e05bdcc..dbcf2b6 100644
--- a/extern/bullet2/src/LinearMath/btVector3.cpp
+++ b/extern/bullet2/src/LinearMath/btVector3.cpp
@@ -15,9 +15,9 @@
This source version has been altered.
*/
-#if defined (_WIN32) || defined (__i386__)
-#define BT_USE_SSE_IN_API
-#endif
+//#if defined (_WIN32) || defined (__i386__)
+//#define BT_USE_SSE_IN_API
+//#endif
#include "btVector3.h"
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp
index e0e8bc7..a788268 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp
@@ -425,50 +425,38 @@ void btRigidBody::setCenterOfMassTransform(const btTransform& xform)
}
+bool btRigidBody::checkCollideWithOverride(const btCollisionObject* co) const
+{
+ const btRigidBody* otherRb = btRigidBody::upcast(co);
+ if (!otherRb)
+ return true;
+
+ for (int i = 0; i < m_constraintRefs.size(); ++i)
+ {
+ const btTypedConstraint* c = m_constraintRefs[i];
+ if (c->isEnabled())
+ if (&c->getRigidBodyA() == otherRb || &c->getRigidBodyB() == otherRb)
+ return false;
+ }
+
+ return true;
+}
void btRigidBody::addConstraintRef(btTypedConstraint* c)
{
- ///disable collision with the 'other' body
-
int index = m_constraintRefs.findLinearSearch(c);
- //don't add constraints that are already referenced
- //btAssert(index == m_constraintRefs.size());
if (index == m_constraintRefs.size())
- {
- m_constraintRefs.push_back(c);
- btCollisionObject* colObjA = &c->getRigidBodyA();
- btCollisionObject* colObjB = &c->getRigidBodyB();
- if (colObjA == this)
- {
- colObjA->setIgnoreCollisionCheck(colObjB, true);
- }
- else
- {
- colObjB->setIgnoreCollisionCheck(colObjA, true);
- }
- }
+ m_constraintRefs.push_back(c);
+
+ m_checkCollideWith = true;
}
void btRigidBody::removeConstraintRef(btTypedConstraint* c)
{
- int index = m_constraintRefs.findLinearSearch(c);
- //don't remove constraints that are not referenced
- if(index < m_constraintRefs.size())
- {
- m_constraintRefs.remove(c);
- btCollisionObject* colObjA = &c->getRigidBodyA();
- btCollisionObject* colObjB = &c->getRigidBodyB();
- if (colObjA == this)
- {
- colObjA->setIgnoreCollisionCheck(colObjB, false);
- }
- else
- {
- colObjB->setIgnoreCollisionCheck(colObjA, false);
- }
- }
+ m_constraintRefs.remove(c);
+ m_checkCollideWith = m_constraintRefs.size() > 0;
}
int btRigidBody::calculateSerializeBufferSize() const
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h
index 1d177db..c2f8c5d 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h
@@ -509,6 +509,8 @@ public:
return (getBroadphaseProxy() != 0);
}
+ virtual bool checkCollideWithOverride(const btCollisionObject* co) const;
+
void addConstraintRef(btTypedConstraint* c);
void removeConstraintRef(btTypedConstraint* c);

View File

@@ -0,0 +1,41 @@
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
index 9095c592d87..b831e20c2f9 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
@@ -406,17 +406,17 @@ void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& ine
#ifndef __SPU__
//not yet, return box inertia
- btScalar margin = getMargin();
+ //btScalar margin = getMargin();
btTransform ident;
ident.setIdentity();
btVector3 aabbMin,aabbMax;
- getAabb(ident,aabbMin,aabbMax);
+ getAabb(ident,aabbMin,aabbMax); // This already contains the margin
btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
- btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
- btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
- btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
+ btScalar lx=btScalar(2.)*(halfExtents.x());
+ btScalar ly=btScalar(2.)*(halfExtents.y());
+ btScalar lz=btScalar(2.)*(halfExtents.z());
const btScalar x2 = lx*lx;
const btScalar y2 = ly*ly;
const btScalar z2 = lz*lz;
@@ -476,10 +476,10 @@ void btPolyhedralConvexAabbCachingShape::recalcLocalAabb()
for ( int i = 0; i < 3; ++i )
{
- m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
- m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+ m_localAabbMax[i] = _supporting[i][i];
+ m_localAabbMin[i] = _supporting[i + 3][i];
}
-
+
#else
for (int i=0;i<3;i++)

View File

@@ -1,113 +0,0 @@
From 1b4c1687748bafd3c521f454bfdfc89b3857b65e Mon Sep 17 00:00:00 2001
From: David Vogel <Dadido3@aol.com>
Date: Mon, 30 Mar 2020 19:45:23 +0200
Subject: [PATCH 1/2] Fix inertia and margin calculation for
btPolyhedralConvexShape
---
.../CollisionShapes/btPolyhedralConvexShape.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
index 521ecfc760..e4bd7bb4d5 100644
--- a/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
+++ b/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
@@ -463,17 +463,17 @@ void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass, btVector3& in
#ifndef __SPU__
//not yet, return box inertia
- btScalar margin = getMargin();
+ //btScalar margin = getMargin();
btTransform ident;
ident.setIdentity();
btVector3 aabbMin, aabbMax;
- getAabb(ident, aabbMin, aabbMax);
+ getAabb(ident, aabbMin, aabbMax); // This already contains the margin
btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
- btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
- btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
- btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
+ btScalar lx = btScalar(2.) * (halfExtents.x());
+ btScalar ly = btScalar(2.) * (halfExtents.y());
+ btScalar lz = btScalar(2.) * (halfExtents.z());
const btScalar x2 = lx * lx;
const btScalar y2 = ly * ly;
const btScalar z2 = lz * lz;
@@ -529,8 +529,8 @@ void btPolyhedralConvexAabbCachingShape::recalcLocalAabb()
for (int i = 0; i < 3; ++i)
{
- m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
- m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+ m_localAabbMax[i] = _supporting[i][i];
+ m_localAabbMin[i] = _supporting[i + 3][i];
}
#else
From 4b9a201d4c1b8cacbcdd68f9cdb55745caa6adc4 Mon Sep 17 00:00:00 2001
From: David Vogel <Dadido3@aol.com>
Date: Mon, 30 Mar 2020 20:43:55 +0200
Subject: [PATCH 2/2] Fix margins
- Margin in ineratia calculation of btConeShape is already contained in the AABB
- Remove margin from the cached AABB in btConvexInternalShape, as it is added on getAabb()
---
src/BulletCollision/CollisionShapes/btConeShape.h | 10 ++++------
.../CollisionShapes/btConvexInternalShape.cpp | 8 ++++----
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/src/BulletCollision/CollisionShapes/btConeShape.h b/src/BulletCollision/CollisionShapes/btConeShape.h
index 49f26bc4e5..ee6786c807 100644
--- a/src/BulletCollision/CollisionShapes/btConeShape.h
+++ b/src/BulletCollision/CollisionShapes/btConeShape.h
@@ -56,15 +56,13 @@ btConeShape : public btConvexInternalShape
btTransform identity;
identity.setIdentity();
btVector3 aabbMin, aabbMax;
- getAabb(identity, aabbMin, aabbMax);
+ getAabb(identity, aabbMin, aabbMax); // This already contains the margin
btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
- btScalar margin = getMargin();
-
- btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
- btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
- btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
+ btScalar lx = btScalar(2.) * (halfExtents.x());
+ btScalar ly = btScalar(2.) * (halfExtents.y());
+ btScalar lz = btScalar(2.) * (halfExtents.z());
const btScalar x2 = lx * lx;
const btScalar y2 = ly * ly;
const btScalar z2 = lz * lz;
diff --git a/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
index 4d598b1aa2..b847f8f40f 100644
--- a/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
+++ b/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
@@ -117,8 +117,8 @@ void btConvexInternalAabbCachingShape::recalcLocalAabb()
for (int i = 0; i < 3; ++i)
{
- m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
- m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+ m_localAabbMax[i] = _supporting[i][i];
+ m_localAabbMin[i] = _supporting[i + 3][i];
}
#else
@@ -128,10 +128,10 @@ void btConvexInternalAabbCachingShape::recalcLocalAabb()
btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
vec[i] = btScalar(1.);
btVector3 tmp = localGetSupportingVertex(vec);
- m_localAabbMax[i] = tmp[i] + m_collisionMargin;
+ m_localAabbMax[i] = tmp[i];
vec[i] = btScalar(-1.);
tmp = localGetSupportingVertex(vec);
- m_localAabbMin[i] = tmp[i] - m_collisionMargin;
+ m_localAabbMin[i] = tmp[i];
}
#endif
}

187
extern/bullet2/src/Bullet-C-Api.h vendored Normal file
View File

@@ -0,0 +1,187 @@
/*
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.
*/
/*
Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's.
Work in progress, functionality will be added on demand.
If possible, use the richer Bullet C++ API, by including "btBulletDynamicsCommon.h"
*/
#ifndef BULLET_C_API_H
#define BULLET_C_API_H
#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
#ifdef BT_USE_DOUBLE_PRECISION
typedef double plReal;
#else
typedef float plReal;
#endif
typedef plReal plVector3[3];
typedef plReal plQuaternion[4];
#ifdef __cplusplus
extern "C" {
#endif
/** Particular physics SDK (C-API) */
PL_DECLARE_HANDLE(plPhysicsSdkHandle);
/** Dynamics world, belonging to some physics SDK (C-API)*/
PL_DECLARE_HANDLE(plDynamicsWorldHandle);
/** Rigid Body that can be part of a Dynamics World (C-API)*/
PL_DECLARE_HANDLE(plRigidBodyHandle);
/** Collision Shape/Geometry, property of a Rigid Body (C-API)*/
PL_DECLARE_HANDLE(plCollisionShapeHandle);
/** Constraint for Rigid Bodies (C-API)*/
PL_DECLARE_HANDLE(plConstraintHandle);
/** Triangle Mesh interface (C-API)*/
PL_DECLARE_HANDLE(plMeshInterfaceHandle);
/** Broadphase Scene/Proxy Handles (C-API)*/
PL_DECLARE_HANDLE(plCollisionBroadphaseHandle);
PL_DECLARE_HANDLE(plBroadphaseProxyHandle);
PL_DECLARE_HANDLE(plCollisionWorldHandle);
/**
Create and Delete a Physics SDK
*/
extern plPhysicsSdkHandle plNewBulletSdk(void); //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(void);
extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn);
extern void plDeleteShape(plCollisionShapeHandle shape);
/* Convex Meshes */
extern plCollisionShapeHandle plNewConvexHullShape(void);
extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z);
/* Concave static triangle meshes */
extern plMeshInterfaceHandle plNewMeshInterface(void);
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);
extern void plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
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]);
/* Convex Hull */
PL_DECLARE_HANDLE(plConvexHull);
plConvexHull plConvexHullCompute(float (*coords)[3], int count);
void plConvexHullDelete(plConvexHull hull);
int plConvexHullNumVertices(plConvexHull hull);
int plConvexHullNumFaces(plConvexHull hull);
void plConvexHullGetVertex(plConvexHull hull, int n, float coords[3], int *original_index);
int plConvexHullGetFaceSize(plConvexHull hull, int n);
void plConvexHullGetFaceVertices(plConvexHull hull, int n, int *vertices);
#ifdef __cplusplus
}
#endif
#endif //BULLET_C_API_H

View File

@@ -2,6 +2,7 @@
//Bullet Continuous Collision Detection and Physics Library
//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
//
// btAxisSweep3
//
@@ -18,15 +19,18 @@
// 3. This notice may not be removed or altered from any source distribution.
#include "btAxisSweep3.h"
btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
: btAxisSweep3Internal<unsigned short int>(worldAabbMin, worldAabbMax, 0xfffe, 0xffff, maxHandles, pairCache, disableRaycastAccelerator)
btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
:btAxisSweep3Internal<unsigned short int>(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache,disableRaycastAccelerator)
{
// 1 handle is reserved as sentinel
btAssert(maxHandles > 1 && maxHandles < 32767);
}
bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
: btAxisSweep3Internal<unsigned int>(worldAabbMin, worldAabbMax, 0xfffffffe, 0x7fffffff, maxHandles, pairCache, disableRaycastAccelerator)
bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
:btAxisSweep3Internal<unsigned int>(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache,disableRaycastAccelerator)
{
// 1 handle is reserved as sentinel
btAssert(maxHandles > 1 && maxHandles < 2147483647);

File diff suppressed because it is too large Load Diff

View File

@@ -1,954 +0,0 @@
//Bullet Continuous Collision Detection and Physics Library
//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
//
// btAxisSweep3.h
//
// Copyright (c) 2006 Simon Hobbs
//
// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
#ifndef BT_AXIS_SWEEP_3_INTERNAL_H
#define BT_AXIS_SWEEP_3_INTERNAL_H
#include "LinearMath/btVector3.h"
#include "btOverlappingPairCache.h"
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
#include "btOverlappingPairCallback.h"
#include "btDbvtBroadphase.h"
//#define DEBUG_BROADPHASE 1
#define USE_OVERLAP_TEST_ON_REMOVES 1
/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
/// It uses quantized integers to represent the begin and end points for each of the 3 axis.
/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
template <typename BP_FP_INT_TYPE>
class btAxisSweep3Internal : public btBroadphaseInterface
{
protected:
BP_FP_INT_TYPE m_bpHandleMask;
BP_FP_INT_TYPE m_handleSentinel;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
class Edge
{
public:
BP_FP_INT_TYPE m_pos; // low bit is min/max
BP_FP_INT_TYPE m_handle;
BP_FP_INT_TYPE IsMax() const { return static_cast<BP_FP_INT_TYPE>(m_pos & 1); }
};
public:
class Handle : public btBroadphaseProxy
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
// indexes into the edge arrays
BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12
// BP_FP_INT_TYPE m_uniqueId;
btBroadphaseProxy* m_dbvtProxy; //for faster raycast
//void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) { m_minEdges[0] = next; }
SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const { return m_minEdges[0]; }
}; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
protected:
btVector3 m_worldAabbMin; // overall system bounds
btVector3 m_worldAabbMax; // overall system bounds
btVector3 m_quantize; // scaling factor for quantization
BP_FP_INT_TYPE m_numHandles; // number of active handles
BP_FP_INT_TYPE m_maxHandles; // max number of handles
Handle* m_pHandles; // handles pool
BP_FP_INT_TYPE m_firstFreeHandle; // free handles list
Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
void* m_pEdgesRawPtr[3];
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;
///additional dynamic aabb structure, used to accelerate ray cast queries.
///can be disabled using a optional argument in the constructor
btDbvtBroadphase* m_raycastAccelerator;
btOverlappingPairCache* m_nullPairCache;
// allocation/deallocation
BP_FP_INT_TYPE allocHandle();
void freeHandle(BP_FP_INT_TYPE handle);
bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB, int axis0, int axis1);
#ifdef DEBUG_BROADPHASE
void debugPrintAxis(int axis, bool checkCardinality = true);
#endif //DEBUG_BROADPHASE
//Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
//void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
public:
btAxisSweep3Internal(const btVector3& worldAabbMin, const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
virtual ~btAxisSweep3Internal();
BP_FP_INT_TYPE getNumHandles() const
{
return m_numHandles;
}
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
BP_FP_INT_TYPE addHandle(const btVector3& aabbMin, const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
void removeHandle(BP_FP_INT_TYPE handle, btDispatcher* dispatcher);
void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const { return m_pHandles + index; }
virtual void resetPool(btDispatcher* dispatcher);
void processAllOverlappingPairs(btOverlapCallback* callback);
//Broadphase Interface
virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const;
///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result
void unQuantize(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
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)
btAssert(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, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher)
{
(void)shapeType;
BP_FP_INT_TYPE handleId = addHandle(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher);
Handle* handle = getHandle(handleId);
if (m_raycastAccelerator)
{
btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher);
handle->m_dbvtProxy = rayProxy;
}
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);
if (m_raycastAccelerator)
m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy, dispatcher);
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);
handle->m_aabbMin = aabbMin;
handle->m_aabbMax = aabbMax;
updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax, dispatcher);
if (m_raycastAccelerator)
m_raycastAccelerator->setAabb(handle->m_dbvtProxy, aabbMin, aabbMax, dispatcher);
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
{
if (m_raycastAccelerator)
{
m_raycastAccelerator->rayTest(rayFrom, rayTo, rayCallback, aabbMin, aabbMax);
}
else
{
//choose axis?
BP_FP_INT_TYPE axis = 0;
//for each proxy
for (BP_FP_INT_TYPE i = 1; i < m_numHandles * 2 + 1; i++)
{
if (m_pEdges[axis][i].IsMax())
{
rayCallback.process(getHandle(m_pEdges[axis][i].m_handle));
}
}
}
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
{
if (m_raycastAccelerator)
{
m_raycastAccelerator->aabbTest(aabbMin, aabbMax, callback);
}
else
{
//choose axis?
BP_FP_INT_TYPE axis = 0;
//for each proxy
for (BP_FP_INT_TYPE i = 1; i < m_numHandles * 2 + 1; i++)
{
if (m_pEdges[axis][i].IsMax())
{
Handle* handle = getHandle(m_pEdges[axis][i].m_handle);
if (TestAabbAgainstAabb2(aabbMin, aabbMax, handle->m_aabbMin, handle->m_aabbMax))
{
callback.process(handle);
}
}
}
}
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
{
Handle* pHandle = static_cast<Handle*>(proxy);
aabbMin = pHandle->m_aabbMin;
aabbMax = pHandle->m_aabbMax;
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::unQuantize(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
{
Handle* pHandle = static_cast<Handle*>(proxy);
unsigned short vecInMin[3];
unsigned short vecInMax[3];
vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos;
vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos + 1;
vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos;
vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos + 1;
vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos;
vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos + 1;
aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()), (btScalar)(vecInMin[1]) / (m_quantize.getY()), (btScalar)(vecInMin[2]) / (m_quantize.getZ()));
aabbMin += m_worldAabbMin;
aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()), (btScalar)(vecInMax[1]) / (m_quantize.getY()), (btScalar)(vecInMax[2]) / (m_quantize.getZ()));
aabbMax += m_worldAabbMin;
}
template <typename BP_FP_INT_TYPE>
btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btVector3& worldAabbMin, const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
: m_bpHandleMask(handleMask),
m_handleSentinel(handleSentinel),
m_pairCache(pairCache),
m_userPairCallback(0),
m_ownsPairCache(false),
m_invalidPair(0),
m_raycastAccelerator(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;
}
if (!disableRaycastAccelerator)
{
m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache), 16)) btNullPairCache();
m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase), 16)) btDbvtBroadphase(m_nullPairCache); //m_pairCache);
m_raycastAccelerator->m_deferedcollide = true; //don't add/remove pairs
}
//btAssert(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()
{
if (m_raycastAccelerator)
{
m_nullPairCache->~btOverlappingPairCache();
btAlignedFree(m_nullPairCache);
m_raycastAccelerator->~btDbvtBroadphase();
btAlignedFree(m_raycastAccelerator);
}
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 btVector3& point, int isMax) const
{
#ifdef OLD_CLAMPING_METHOD
///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax]
///see http://code.google.com/p/bullet/issues/detail?id=87
btVector3 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);
#else
btVector3 v = (point - m_worldAabbMin) * m_quantize;
out[0] = (v[0] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[0] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0] & m_bpHandleMask) | isMax);
out[1] = (v[1] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[1] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1] & m_bpHandleMask) | isMax);
out[2] = (v[2] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[2] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2] & m_bpHandleMask) | isMax);
#endif //OLD_CLAMPING_METHOD
}
template <typename BP_FP_INT_TYPE>
BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
{
btAssert(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)
{
btAssert(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 btVector3& aabbMin, const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher)
{
// 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;
// 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);
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* /*dispatcher*/)
{
if (m_numHandles == 0)
{
m_firstFreeHandle = 1;
{
for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++)
m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
m_pHandles[m_maxHandles - 1].SetNextFree(0);
}
}
}
//#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)
{
///important to use an AABB test that is consistent with the broadphase
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++;
}
}
///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 btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher)
{
// btAssert(bounds.IsFinite());
//btAssert(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++;
}
}
#endif

View File

@@ -13,8 +13,10 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_BROADPHASE_INTERFACE_H
#define BT_BROADPHASE_INTERFACE_H
#ifndef BT_BROADPHASE_INTERFACE_H
#define BT_BROADPHASE_INTERFACE_H
struct btDispatcherInfo;
class btDispatcher;
@@ -22,23 +24,23 @@ class btDispatcher;
class btOverlappingPairCache;
struct btBroadphaseAabbCallback
struct btBroadphaseAabbCallback
{
virtual ~btBroadphaseAabbCallback() {}
virtual bool process(const btBroadphaseProxy* proxy) = 0;
virtual bool process(const btBroadphaseProxy* proxy) = 0;
};
struct btBroadphaseRayCallback : public btBroadphaseAabbCallback
struct btBroadphaseRayCallback : public btBroadphaseAabbCallback
{
///added some cached data to accelerate ray-AABB tests
btVector3 m_rayDirectionInverse;
unsigned int m_signs[3];
btScalar m_lambda_max;
btVector3 m_rayDirectionInverse;
unsigned int m_signs[3];
btScalar m_lambda_max;
virtual ~btBroadphaseRayCallback() {}
protected:
btBroadphaseRayCallback() {}
};
#include "LinearMath/btVector3.h"
@@ -51,29 +53,30 @@ class btBroadphaseInterface
public:
virtual ~btBroadphaseInterface() {}
virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher) = 0;
virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher) = 0;
virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const = 0;
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0;
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0;
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0;
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0)) = 0;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) = 0;
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0;
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0;
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
virtual void calculateOverlappingPairs(btDispatcher* dispatcher) = 0;
virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0;
virtual btOverlappingPairCache* getOverlappingPairCache() = 0;
virtual const btOverlappingPairCache* getOverlappingPairCache() const = 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 getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0;
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher) { (void)dispatcher; };
virtual void resetPool(btDispatcher* dispatcher) { (void) dispatcher; };
virtual void printStats() = 0;
virtual void printStats() = 0;
};
#endif //BT_BROADPHASE_INTERFACE_H
#endif //BT_BROADPHASE_INTERFACE_H

View File

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

View File

@@ -16,10 +16,11 @@ subject to the following restrictions:
#ifndef BT_BROADPHASE_PROXY_H
#define BT_BROADPHASE_PROXY_H
#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedAllocator.h"
/// btDispatcher uses these types
/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave
/// to facilitate type checking
@@ -34,8 +35,8 @@ enum BroadphaseNativeTypes
CONVEX_HULL_SHAPE_PROXYTYPE,
CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE,
CUSTOM_POLYHEDRAL_SHAPE_TYPE,
//implicit convex shapes
IMPLICIT_CONVEX_SHAPES_START_HERE,
//implicit convex shapes
IMPLICIT_CONVEX_SHAPES_START_HERE,
SPHERE_SHAPE_PROXYTYPE,
MULTI_SPHERE_SHAPE_PROXYTYPE,
CAPSULE_SHAPE_PROXYTYPE,
@@ -48,8 +49,8 @@ enum BroadphaseNativeTypes
BOX_2D_SHAPE_PROXYTYPE,
CONVEX_2D_SHAPE_PROXYTYPE,
CUSTOM_CONVEX_SHAPE_TYPE,
//concave shapes
CONCAVE_SHAPES_START_HERE,
//concave shapes
CONCAVE_SHAPES_START_HERE,
//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
TRIANGLE_MESH_SHAPE_PROXYTYPE,
SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
@@ -57,16 +58,15 @@ enum BroadphaseNativeTypes
FAST_CONCAVE_MESH_PROXYTYPE,
//terrain
TERRAIN_SHAPE_PROXYTYPE,
///Used for GIMPACT Trimesh integration
///Used for GIMPACT Trimesh integration
GIMPACT_SHAPE_PROXYTYPE,
///Multimaterial mesh
MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
///Multimaterial mesh
MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
EMPTY_SHAPE_PROXYTYPE,
STATIC_PLANE_PROXYTYPE,
CUSTOM_CONCAVE_SHAPE_TYPE,
SDF_SHAPE_PROXYTYPE = CUSTOM_CONCAVE_SHAPE_TYPE,
CONCAVE_SHAPES_END_HERE,
CONCAVE_SHAPES_END_HERE,
COMPOUND_SHAPE_PROXYTYPE,
@@ -76,37 +76,38 @@ enum BroadphaseNativeTypes
INVALID_SHAPE_PROXYTYPE,
MAX_BROADPHASE_COLLISION_TYPES
};
///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
ATTRIBUTE_ALIGNED16(struct)
btBroadphaseProxy
{
BT_DECLARE_ALIGNED_ALLOCATOR();
///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
{
BT_DECLARE_ALIGNED_ALLOCATOR();
///optional filtering to cull potential collisions
enum CollisionFilterGroups
{
DefaultFilter = 1,
StaticFilter = 2,
KinematicFilter = 4,
DebrisFilter = 8,
SensorTrigger = 16,
CharacterFilter = 32,
AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
DefaultFilter = 1,
StaticFilter = 2,
KinematicFilter = 4,
DebrisFilter = 8,
SensorTrigger = 16,
CharacterFilter = 32,
AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
};
//Usually the client btCollisionObject or Rigidbody class
void* m_clientObject;
int m_collisionFilterGroup;
int m_collisionFilterMask;
void* m_clientObject;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
void* m_multiSapParentProxy;
int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
int m_uniqueId; //m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
btVector3 m_aabbMin;
btVector3 m_aabbMax;
btVector3 m_aabbMin;
btVector3 m_aabbMax;
SIMD_FORCE_INLINE int getUid() const
{
@@ -114,45 +115,48 @@ btBroadphaseProxy
}
//used for memory pools
btBroadphaseProxy() : m_clientObject(0)
btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0)
{
}
btBroadphaseProxy(const btVector3& aabbMin, const btVector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
: m_clientObject(userPtr),
m_collisionFilterGroup(collisionFilterGroup),
m_collisionFilterMask(collisionFilterMask),
m_aabbMin(aabbMin),
m_aabbMax(aabbMax)
btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0)
:m_clientObject(userPtr),
m_collisionFilterGroup(collisionFilterGroup),
m_collisionFilterMask(collisionFilterMask),
m_aabbMin(aabbMin),
m_aabbMax(aabbMax)
{
m_multiSapParentProxy = multiSapParentProxy;
}
static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
{
return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
}
static SIMD_FORCE_INLINE bool isConvex(int proxyType)
static SIMD_FORCE_INLINE bool isConvex(int proxyType)
{
return (proxyType < CONCAVE_SHAPES_START_HERE);
}
static SIMD_FORCE_INLINE bool isNonMoving(int proxyType)
static SIMD_FORCE_INLINE bool isNonMoving(int proxyType)
{
return (isConcave(proxyType) && !(proxyType == GIMPACT_SHAPE_PROXYTYPE));
return (isConcave(proxyType) && !(proxyType==GIMPACT_SHAPE_PROXYTYPE));
}
static SIMD_FORCE_INLINE bool isConcave(int proxyType)
static SIMD_FORCE_INLINE bool isConcave(int proxyType)
{
return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
(proxyType < CONCAVE_SHAPES_END_HERE));
(proxyType < CONCAVE_SHAPES_END_HERE));
}
static SIMD_FORCE_INLINE bool isCompound(int proxyType)
static SIMD_FORCE_INLINE bool isCompound(int proxyType)
{
return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
}
static SIMD_FORCE_INLINE bool isSoftBody(int proxyType)
static SIMD_FORCE_INLINE bool isSoftBody(int proxyType)
{
return (proxyType == SOFTBODY_SHAPE_PROXYTYPE);
}
@@ -164,55 +168,67 @@ btBroadphaseProxy
static SIMD_FORCE_INLINE bool isConvex2d(int proxyType)
{
return (proxyType == BOX_2D_SHAPE_PROXYTYPE) || (proxyType == CONVEX_2D_SHAPE_PROXYTYPE);
return (proxyType == BOX_2D_SHAPE_PROXYTYPE) || (proxyType == CONVEX_2D_SHAPE_PROXYTYPE);
}
};
}
;
class btCollisionAlgorithm;
struct btBroadphaseProxy;
///The btBroadphasePair class contains a pair of aabb-overlapping objects.
///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes.
ATTRIBUTE_ALIGNED16(struct)
btBroadphasePair
ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
{
btBroadphasePair()
: m_pProxy0(0),
m_pProxy1(0),
m_algorithm(0),
m_internalInfo1(0)
btBroadphasePair ()
:
m_pProxy0(0),
m_pProxy1(0),
m_algorithm(0),
m_internalInfo1(0)
{
}
BT_DECLARE_ALIGNED_ALLOCATOR();
BT_DECLARE_ALIGNED_ALLOCATOR();
btBroadphasePair(btBroadphaseProxy & proxy0, btBroadphaseProxy & proxy1)
btBroadphasePair(const btBroadphasePair& other)
: m_pProxy0(other.m_pProxy0),
m_pProxy1(other.m_pProxy1),
m_algorithm(other.m_algorithm),
m_internalInfo1(other.m_internalInfo1)
{
}
btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1)
{
//keep them sorted, so the std::set operations work
if (proxy0.m_uniqueId < proxy1.m_uniqueId)
{
m_pProxy0 = &proxy0;
m_pProxy1 = &proxy1;
}
else
{
m_pProxy0 = &proxy1;
m_pProxy1 = &proxy0;
}
{
m_pProxy0 = &proxy0;
m_pProxy1 = &proxy1;
}
else
{
m_pProxy0 = &proxy1;
m_pProxy1 = &proxy0;
}
m_algorithm = 0;
m_internalInfo1 = 0;
}
}
btBroadphaseProxy* m_pProxy0;
btBroadphaseProxy* m_pProxy1;
mutable btCollisionAlgorithm* m_algorithm;
union {
void* m_internalInfo1;
int m_internalTmpValue;
}; //don't use this data, it will be removed in future version.
union { void* m_internalInfo1; int m_internalTmpValue;};//don't use this data, it will be removed in future version.
};
/*
@@ -224,25 +240,31 @@ SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePa
}
*/
class btBroadphasePairSortPredicate
{
public:
bool operator()(const btBroadphasePair& a, const btBroadphasePair& b) const
{
const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1;
const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1;
const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1;
const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1;
public:
return uidA0 > uidB0 ||
(a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) ||
(a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);
}
bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) const
{
const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1;
const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1;
const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1;
const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1;
return uidA0 > uidB0 ||
(a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) ||
(a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);
}
};
SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)
SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)
{
return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
}
#endif //BT_BROADPHASE_PROXY_H
#endif //BT_BROADPHASE_PROXY_H

View File

@@ -20,3 +20,4 @@ btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructio
{
m_dispatcher = ci.m_dispatcher1;
}

View File

@@ -25,51 +25,57 @@ class btManifoldResult;
class btCollisionObject;
struct btCollisionObjectWrapper;
struct btDispatcherInfo;
class btPersistentManifold;
class btPersistentManifold;
typedef btAlignedObjectArray<btPersistentManifold*> btManifoldArray;
typedef btAlignedObjectArray<btPersistentManifold*> btManifoldArray;
struct btCollisionAlgorithmConstructionInfo
{
btCollisionAlgorithmConstructionInfo()
: m_dispatcher1(0),
m_manifold(0)
:m_dispatcher1(0),
m_manifold(0)
{
}
btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher, int temp)
: m_dispatcher1(dispatcher)
btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp)
:m_dispatcher1(dispatcher)
{
(void)temp;
}
btDispatcher* m_dispatcher1;
btPersistentManifold* m_manifold;
btDispatcher* m_dispatcher1;
btPersistentManifold* m_manifold;
// int getDispatcherId();
// int getDispatcherId();
};
///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher.
///It is persistent over frames
class btCollisionAlgorithm
{
protected:
btDispatcher* m_dispatcher;
protected:
// int getDispatcherId();
btDispatcher* m_dispatcher;
protected:
// int getDispatcherId();
public:
btCollisionAlgorithm(){};
btCollisionAlgorithm() {};
btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
virtual ~btCollisionAlgorithm(){};
virtual ~btCollisionAlgorithm() {};
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut) = 0;
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
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;
virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
};
#endif //BT_COLLISION_ALGORITHM_H
#endif //BT_COLLISION_ALGORITHM_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -24,16 +24,15 @@ subject to the following restrictions:
// Compile time config
//
#define DBVT_BP_PROFILE 0
#define DBVT_BP_PROFILE 0
//#define DBVT_BP_SORTPAIRS 1
#define DBVT_BP_PREVENTFALSEUPDATE 0
#define DBVT_BP_ACCURATESLEEPING 0
#define DBVT_BP_ENABLE_BENCHMARK 0
//#define DBVT_BP_MARGIN (btScalar)0.05
extern btScalar gDbvtMargin;
#define DBVT_BP_PREVENTFALSEUPDATE 0
#define DBVT_BP_ACCURATESLEEPING 0
#define DBVT_BP_ENABLE_BENCHMARK 0
#define DBVT_BP_MARGIN (btScalar)0.05
#if DBVT_BP_PROFILE
#define DBVT_BP_PROFILING_RATE 256
#define DBVT_BP_PROFILING_RATE 256
#include "LinearMath/btQuickprof.h"
#endif
@@ -42,90 +41,89 @@ extern btScalar gDbvtMargin;
//
struct btDbvtProxy : btBroadphaseProxy
{
/* Fields */
/* Fields */
//btDbvtAabbMm aabb;
btDbvtNode* leaf;
btDbvtProxy* links[2];
int stage;
/* ctor */
btDbvtProxy(const btVector3& aabbMin, const btVector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask) : btBroadphaseProxy(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask)
btDbvtNode* leaf;
btDbvtProxy* links[2];
int stage;
/* ctor */
btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
{
links[0] = links[1] = 0;
links[0]=links[1]=0;
}
};
typedef btAlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
typedef btAlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
struct btDbvtBroadphase : btBroadphaseInterface
struct btDbvtBroadphase : btBroadphaseInterface
{
/* Config */
enum
{
DYNAMIC_SET = 0, /* Dynamic set index */
FIXED_SET = 1, /* Fixed set index */
STAGECOUNT = 2 /* Number of stages */
/* Config */
enum {
DYNAMIC_SET = 0, /* Dynamic set index */
FIXED_SET = 1, /* Fixed set index */
STAGECOUNT = 2 /* Number of stages */
};
/* Fields */
btDbvt m_sets[2]; // Dbvt sets
btDbvtProxy* m_stageRoots[STAGECOUNT + 1]; // Stages list
btOverlappingPairCache* m_paircache; // Pair cache
btScalar m_prediction; // Velocity prediction
int m_stageCurrent; // Current stage
int m_fupdates; // % of fixed updates per frame
int m_dupdates; // % of dynamic updates per frame
int m_cupdates; // % of cleanup updates per frame
int m_newpairs; // Number of pairs created
int m_fixedleft; // Fixed optimization left
unsigned m_updates_call; // Number of updates call
unsigned m_updates_done; // Number of updates done
btScalar m_updates_ratio; // m_updates_done/m_updates_call
int m_pid; // Parse id
int m_cid; // Cleanup index
int m_gid; // Gen id
bool m_releasepaircache; // Release pair cache on delete
bool m_deferedcollide; // Defere dynamic/static collision to collide call
bool m_needcleanup; // Need to run cleanup?
btAlignedObjectArray<btAlignedObjectArray<const btDbvtNode*> > m_rayTestStacks;
/* Fields */
btDbvt m_sets[2]; // Dbvt sets
btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
btOverlappingPairCache* m_paircache; // Pair cache
btScalar m_prediction; // Velocity prediction
int m_stageCurrent; // Current stage
int m_fupdates; // % of fixed updates per frame
int m_dupdates; // % of dynamic updates per frame
int m_cupdates; // % of cleanup updates per frame
int m_newpairs; // Number of pairs created
int m_fixedleft; // Fixed optimization left
unsigned m_updates_call; // Number of updates call
unsigned m_updates_done; // Number of updates done
btScalar m_updates_ratio; // m_updates_done/m_updates_call
int m_pid; // Parse id
int m_cid; // Cleanup index
int m_gid; // Gen id
bool m_releasepaircache; // Release pair cache on delete
bool m_deferedcollide; // Defere dynamic/static collision to collide call
bool m_needcleanup; // Need to run cleanup?
#if DBVT_BP_PROFILE
btClock m_clock;
struct
{
unsigned long m_total;
unsigned long m_ddcollide;
unsigned long m_fdcollide;
unsigned long m_cleanup;
unsigned long m_jobcount;
} m_profiling;
btClock m_clock;
struct {
unsigned long m_total;
unsigned long m_ddcollide;
unsigned long m_fdcollide;
unsigned long m_cleanup;
unsigned long m_jobcount;
} m_profiling;
#endif
/* Methods */
btDbvtBroadphase(btOverlappingPairCache* paircache = 0);
/* Methods */
btDbvtBroadphase(btOverlappingPairCache* paircache=0);
~btDbvtBroadphase();
void collide(btDispatcher* dispatcher);
void optimize();
void collide(btDispatcher* dispatcher);
void optimize();
/* btBroadphaseInterface Implementation */
btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
virtual btOverlappingPairCache* getOverlappingPairCache();
virtual const btOverlappingPairCache* getOverlappingPairCache() const;
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
virtual void printStats();
virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
virtual btOverlappingPairCache* getOverlappingPairCache();
virtual const btOverlappingPairCache* getOverlappingPairCache() const;
virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const;
virtual void printStats();
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
void performDeferredRemoval(btDispatcher* dispatcher);
void setVelocityPrediction(btScalar prediction)
void performDeferredRemoval(btDispatcher* dispatcher);
void setVelocityPrediction(btScalar prediction)
{
m_prediction = prediction;
}
@@ -134,13 +132,15 @@ struct btDbvtBroadphase : btBroadphaseInterface
return m_prediction;
}
///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
///it is not part of the btBroadphaseInterface but specific to btDbvtBroadphase.
///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
///http://code.google.com/p/bullet/issues/detail?id=223
void setAabbForceUpdate(btBroadphaseProxy* absproxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* /*dispatcher*/);
void setAabbForceUpdate( btBroadphaseProxy* absproxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* /*dispatcher*/);
static void benchmark(btBroadphaseInterface*);
static void benchmark(btBroadphaseInterface*);
};
#endif

View File

@@ -17,4 +17,6 @@ subject to the following restrictions:
btDispatcher::~btDispatcher()
{
}

View File

@@ -20,7 +20,7 @@ subject to the following restrictions:
class btCollisionAlgorithm;
struct btBroadphaseProxy;
class btRigidBody;
class btCollisionObject;
class btCollisionObject;
class btOverlappingPairCache;
struct btCollisionObjectWrapper;
@@ -35,76 +35,73 @@ struct btDispatcherInfo
DISPATCH_CONTINUOUS
};
btDispatcherInfo()
: m_timeStep(btScalar(0.)),
m_stepCount(0),
m_dispatchFunc(DISPATCH_DISCRETE),
m_timeOfImpact(btScalar(1.)),
m_useContinuous(true),
m_debugDraw(0),
m_enableSatConvex(false),
m_enableSPU(true),
m_useEpa(true),
m_allowedCcdPenetration(btScalar(0.04)),
m_useConvexConservativeDistanceUtil(false),
m_convexConservativeDistanceThreshold(0.0f),
m_deterministicOverlappingPairs(false)
:m_timeStep(btScalar(0.)),
m_stepCount(0),
m_dispatchFunc(DISPATCH_DISCRETE),
m_timeOfImpact(btScalar(1.)),
m_useContinuous(true),
m_debugDraw(0),
m_enableSatConvex(false),
m_enableSPU(true),
m_useEpa(true),
m_allowedCcdPenetration(btScalar(0.04)),
m_useConvexConservativeDistanceUtil(false),
m_convexConservativeDistanceThreshold(0.0f)
{
}
btScalar m_timeStep;
int m_stepCount;
int m_dispatchFunc;
mutable btScalar m_timeOfImpact;
bool m_useContinuous;
class btIDebugDraw* m_debugDraw;
bool m_enableSatConvex;
bool m_enableSPU;
bool m_useEpa;
btScalar m_allowedCcdPenetration;
bool m_useConvexConservativeDistanceUtil;
btScalar m_convexConservativeDistanceThreshold;
bool m_deterministicOverlappingPairs;
};
enum ebtDispatcherQueryType
{
BT_CONTACT_POINT_ALGORITHMS = 1,
BT_CLOSEST_POINT_ALGORITHMS = 2
}
btScalar m_timeStep;
int m_stepCount;
int m_dispatchFunc;
mutable btScalar m_timeOfImpact;
bool m_useContinuous;
class btIDebugDraw* m_debugDraw;
bool m_enableSatConvex;
bool m_enableSPU;
bool m_useEpa;
btScalar m_allowedCcdPenetration;
bool m_useConvexConservativeDistanceUtil;
btScalar m_convexConservativeDistanceThreshold;
};
///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs.
///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic).
class btDispatcher
{
public:
virtual ~btDispatcher();
virtual ~btDispatcher() ;
virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType) = 0;
virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold=0) = 0;
virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0, const btCollisionObject* b1) = 0;
virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1)=0;
virtual void releaseManifold(btPersistentManifold* manifold) = 0;
virtual void releaseManifold(btPersistentManifold* manifold)=0;
virtual void clearManifold(btPersistentManifold* manifold) = 0;
virtual void clearManifold(btPersistentManifold* manifold)=0;
virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1) = 0;
virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1) = 0;
virtual bool needsResponse(const btCollisionObject* body0, const btCollisionObject* body1) = 0;
virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)=0;
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher) = 0;
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0;
virtual int getNumManifolds() const = 0;
virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
virtual btPersistentManifold** getInternalManifoldPointer() = 0;
virtual btPersistentManifold** getInternalManifoldPointer() = 0;
virtual btPoolAllocator* getInternalManifoldPool() = 0;
virtual btPoolAllocator* getInternalManifoldPool() = 0;
virtual const btPoolAllocator* getInternalManifoldPool() const = 0;
virtual const btPoolAllocator* getInternalManifoldPool() const = 0;
virtual void* allocateCollisionAlgorithm(int size) = 0;
virtual void* allocateCollisionAlgorithm(int size) = 0;
virtual void freeCollisionAlgorithm(void* ptr) = 0;
virtual void freeCollisionAlgorithm(void* ptr) = 0;
};
#endif //BT_DISPATCHER_H
#endif //BT_DISPATCHER_H

View File

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

View File

@@ -0,0 +1,151 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_MULTI_SAP_BROADPHASE
#define BT_MULTI_SAP_BROADPHASE
#include "btBroadphaseInterface.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "btOverlappingPairCache.h"
class btBroadphaseInterface;
class btSimpleBroadphase;
typedef btAlignedObjectArray<btBroadphaseInterface*> btSapBroadphaseArray;
///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead.
///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases.
///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time.
///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy.
///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328
///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329
class btMultiSapBroadphase :public btBroadphaseInterface
{
btSapBroadphaseArray m_sapBroadphases;
btSimpleBroadphase* m_simpleBroadphase;
btOverlappingPairCache* m_overlappingPairs;
class btQuantizedBvh* m_optimizedAabbTree;
bool m_ownsPairCache;
btOverlapFilterCallback* m_filterCallback;
int m_invalidPair;
struct btBridgeProxy
{
btBroadphaseProxy* m_childProxy;
btBroadphaseInterface* m_childBroadphase;
};
public:
struct btMultiSapProxy : public btBroadphaseProxy
{
///array with all the entries that this proxy belongs to
btAlignedObjectArray<btBridgeProxy*> m_bridgeProxies;
btVector3 m_aabbMin;
btVector3 m_aabbMax;
int m_shapeType;
/* void* m_userPtr;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
*/
btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask)
:btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask),
m_aabbMin(aabbMin),
m_aabbMax(aabbMax),
m_shapeType(shapeType)
{
m_multiSapParentProxy =this;
}
};
protected:
btAlignedObjectArray<btMultiSapProxy*> m_multiSapProxies;
public:
btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0);
btSapBroadphaseArray& getBroadphaseArray()
{
return m_sapBroadphases;
}
const btSapBroadphaseArray& getBroadphaseArray() const
{
return m_sapBroadphases;
}
virtual ~btMultiSapBroadphase();
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase);
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
virtual btOverlappingPairCache* getOverlappingPairCache()
{
return m_overlappingPairs;
}
virtual const btOverlappingPairCache* getOverlappingPairCache() const
{
return m_overlappingPairs;
}
///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
///will add some transform later
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
{
aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
}
void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
virtual void printStats();
void quicksort (btBroadphasePairArray& a, int lo, int hi);
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
};
#endif //BT_MULTI_SAP_BROADPHASE

View File

@@ -13,6 +13,8 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btOverlappingPairCache.h"
#include "btDispatcher.h"
@@ -21,95 +23,127 @@ subject to the following restrictions:
#include <stdio.h>
btHashedOverlappingPairCache::btHashedOverlappingPairCache() : m_overlapFilterCallback(0),
m_ghostPairCallback(0)
int gOverlappingPairs = 0;
int gRemovePairs =0;
int gAddedPairs =0;
int gFindPairs =0;
btHashedOverlappingPairCache::btHashedOverlappingPairCache():
m_overlapFilterCallback(0),
m_ghostPairCallback(0)
{
int initialAllocatedSize = 2;
int initialAllocatedSize= 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
growTables();
}
btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
{
}
void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher)
void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
{
if (pair.m_algorithm && dispatcher)
{
{
pair.m_algorithm->~btCollisionAlgorithm();
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
pair.m_algorithm = 0;
pair.m_algorithm=0;
}
}
}
void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class CleanPairCallback : public btOverlapCallback
class CleanPairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_cleanProxy;
btOverlappingPairCache* m_pairCache;
btOverlappingPairCache* m_pairCache;
btDispatcher* m_dispatcher;
public:
CleanPairCallback(btBroadphaseProxy* cleanProxy, btOverlappingPairCache* pairCache, btDispatcher* dispatcher)
: m_cleanProxy(cleanProxy),
m_pairCache(pairCache),
m_dispatcher(dispatcher)
CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
:m_cleanProxy(cleanProxy),
m_pairCache(pairCache),
m_dispatcher(dispatcher)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
virtual bool processOverlap(btBroadphasePair& pair)
{
if ((pair.m_pProxy0 == m_cleanProxy) ||
(pair.m_pProxy1 == m_cleanProxy))
{
m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
}
return false;
}
};
CleanPairCallback cleanPairs(proxy, this, dispatcher);
CleanPairCallback cleanPairs(proxy,this,dispatcher);
processAllOverlappingPairs(&cleanPairs,dispatcher);
processAllOverlappingPairs(&cleanPairs, dispatcher);
}
void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class RemovePairCallback : public btOverlapCallback
class RemovePairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_obsoleteProxy;
public:
RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
: m_obsoleteProxy(obsoleteProxy)
:m_obsoleteProxy(obsoleteProxy)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
virtual bool processOverlap(btBroadphasePair& pair)
{
return ((pair.m_pProxy0 == m_obsoleteProxy) ||
(pair.m_pProxy1 == m_obsoleteProxy));
(pair.m_pProxy1 == m_obsoleteProxy));
}
};
RemovePairCallback removeCallback(proxy);
processAllOverlappingPairs(&removeCallback, dispatcher);
processAllOverlappingPairs(&removeCallback,dispatcher);
}
btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
if (proxy0->m_uniqueId > proxy1->m_uniqueId)
btSwap(proxy0, proxy1);
gFindPairs++;
if(proxy0->m_uniqueId>proxy1->m_uniqueId)
btSwap(proxy0,proxy1);
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
/*if (proxyId1 > proxyId2)
/*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));
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())
{
@@ -134,8 +168,9 @@ btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* prox
//#include <stdio.h>
void btHashedOverlappingPairCache::growTables()
void btHashedOverlappingPairCache::growTables()
{
int newCapacity = m_overlappingPairArray.capacity();
if (m_hashTable.size() < newCapacity)
@@ -146,9 +181,10 @@ void btHashedOverlappingPairCache::growTables()
m_hashTable.resize(newCapacity);
m_next.resize(newCapacity);
int i;
for (i = 0; i < newCapacity; ++i)
for (i= 0; i < newCapacity; ++i)
{
m_hashTable[i] = BT_NULL_PAIR;
}
@@ -157,31 +193,35 @@ void btHashedOverlappingPairCache::growTables()
m_next[i] = BT_NULL_PAIR;
}
for (i = 0; i < curHashtableSize; i++)
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
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->m_uniqueId > proxy1->m_uniqueId)
btSwap(proxy0, proxy1);
if(proxy0->m_uniqueId>proxy1->m_uniqueId)
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
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)
@@ -203,7 +243,7 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
//this is where we add an actual pair, so also call the 'ghost'
if (m_ghostPairCallback)
m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
int newCapacity = m_overlappingPairArray.capacity();
@@ -211,14 +251,15 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
{
growTables();
//hash with new capacity
hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
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 = new (mem) btBroadphasePair(*proxy0,*proxy1);
// pair->m_pProxy0 = proxy0;
// pair->m_pProxy1 = proxy1;
pair->m_algorithm = 0;
pair->m_internalTmpValue = 0;
m_next[count] = m_hashTable[hash];
m_hashTable[hash] = count;
@@ -226,17 +267,20 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
return pair;
}
void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
{
if (proxy0->m_uniqueId > proxy1->m_uniqueId)
btSwap(proxy0, proxy1);
gRemovePairs++;
if(proxy0->m_uniqueId>proxy1->m_uniqueId)
btSwap(proxy0,proxy1);
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
/*if (proxyId1 > proxyId2)
/*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));
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)
@@ -244,7 +288,7 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
return 0;
}
cleanOverlappingPair(*pair, dispatcher);
cleanOverlappingPair(*pair,dispatcher);
void* userData = pair->m_internalInfo1;
@@ -282,7 +326,7 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
int lastPairIndex = m_overlappingPairArray.size() - 1;
if (m_ghostPairCallback)
m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1, dispatcher);
m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
// If the removed pair is the last pair, we are done.
if (lastPairIndex == pairIndex)
@@ -293,8 +337,8 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
// 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));
/* 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);
@@ -328,106 +372,44 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
return userData;
}
//#include <stdio.h>
#include "LinearMath/btQuickprof.h"
void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher)
void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
{
BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs");
int i;
// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
for (i = 0; i < m_overlappingPairArray.size();)
// 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);
}
else
removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
gOverlappingPairs--;
} else
{
i++;
}
}
}
struct MyPairIndex
{
int m_orgIndex;
int m_uidA0;
int m_uidA1;
};
class MyPairIndeSortPredicate
{
public:
bool operator()(const MyPairIndex& a, const MyPairIndex& b) const
{
const int uidA0 = a.m_uidA0;
const int uidB0 = b.m_uidA0;
const int uidA1 = a.m_uidA1;
const int uidB1 = b.m_uidA1;
return uidA0 > uidB0 || (uidA0 == uidB0 && uidA1 > uidB1);
}
};
void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& dispatchInfo)
{
if (dispatchInfo.m_deterministicOverlappingPairs)
{
btBroadphasePairArray& pa = getOverlappingPairArray();
btAlignedObjectArray<MyPairIndex> indices;
{
BT_PROFILE("sortOverlappingPairs");
indices.resize(pa.size());
for (int i = 0; i < indices.size(); i++)
{
const btBroadphasePair& p = pa[i];
const int uidA0 = p.m_pProxy0 ? p.m_pProxy0->m_uniqueId : -1;
const int uidA1 = p.m_pProxy1 ? p.m_pProxy1->m_uniqueId : -1;
indices[i].m_uidA0 = uidA0;
indices[i].m_uidA1 = uidA1;
indices[i].m_orgIndex = i;
}
indices.quickSort(MyPairIndeSortPredicate());
}
{
BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs");
int i;
for (i = 0; i < indices.size();)
{
btBroadphasePair* pair = &pa[indices[i].m_orgIndex];
if (callback->processOverlap(*pair))
{
removeOverlappingPair(pair->m_pProxy0, pair->m_pProxy1, dispatcher);
}
else
{
i++;
}
}
}
}
else
{
processAllOverlappingPairs(callback, dispatcher);
}
}
void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
{
///need to keep hashmap in sync with pair address, so rebuild all
btBroadphasePairArray tmpPairs;
int i;
for (i = 0; i < m_overlappingPairArray.size(); i++)
for (i=0;i<m_overlappingPairArray.size();i++)
{
tmpPairs.push_back(m_overlappingPairArray[i]);
}
for (i = 0; i < tmpPairs.size(); i++)
for (i=0;i<tmpPairs.size();i++)
{
removeOverlappingPair(tmpPairs[i].m_pProxy0, tmpPairs[i].m_pProxy1, dispatcher);
removeOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1,dispatcher);
}
for (i = 0; i < m_next.size(); i++)
{
m_next[i] = BT_NULL_PAIR;
@@ -435,28 +417,32 @@ void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher
tmpPairs.quickSort(btBroadphasePairSortPredicate());
for (i = 0; i < tmpPairs.size(); i++)
for (i=0;i<tmpPairs.size();i++)
{
addOverlappingPair(tmpPairs[i].m_pProxy0, tmpPairs[i].m_pProxy1);
addOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1);
}
}
void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
{
if (!hasDeferredRemoval())
{
btBroadphasePair findPair(*proxy0, *proxy1);
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_internalInfo1;
cleanOverlappingPair(pair, dispatcher);
cleanOverlappingPair(pair,dispatcher);
if (m_ghostPairCallback)
m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1, dispatcher);
m_overlappingPairArray.swap(findIndex, m_overlappingPairArray.capacity() - 1);
m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
m_overlappingPairArray.pop_back();
return userData;
}
@@ -465,73 +451,99 @@ void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
return 0;
}
btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
//don't add overlap with own
btAssert(proxy0 != proxy1);
if (!needsBroadphaseCollision(proxy0, proxy1))
if (!needsBroadphaseCollision(proxy0,proxy1))
return 0;
void* mem = &m_overlappingPairArray.expandNonInitializing();
btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0, *proxy1);
btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
gOverlappingPairs++;
gAddedPairs++;
if (m_ghostPairCallback)
m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
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)
btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
if (!needsBroadphaseCollision(proxy0, proxy1))
if (!needsBroadphaseCollision(proxy0,proxy1))
return 0;
btBroadphasePair tmpPair(*proxy0, *proxy1);
btBroadphasePair tmpPair(*proxy0,*proxy1);
int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
if (findIndex < m_overlappingPairArray.size())
{
//btAssert(it != m_overlappingPairSet.end());
btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
return pair;
}
return 0;
}
//#include <stdio.h>
void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher)
void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
{
int i;
for (i = 0; i < m_overlappingPairArray.size();)
for (i=0;i<m_overlappingPairArray.size();)
{
btBroadphasePair* pair = &m_overlappingPairArray[i];
if (callback->processOverlap(*pair))
{
cleanOverlappingPair(*pair, dispatcher);
cleanOverlappingPair(*pair,dispatcher);
pair->m_pProxy0 = 0;
pair->m_pProxy1 = 0;
m_overlappingPairArray.swap(i, m_overlappingPairArray.size() - 1);
m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
m_overlappingPairArray.pop_back();
}
else
gOverlappingPairs--;
} else
{
i++;
}
}
}
btSortedOverlappingPairCache::btSortedOverlappingPairCache() : m_blockedForChanges(false),
m_hasDeferredRemoval(true),
m_overlapFilterCallback(0),
m_ghostPairCallback(0)
btSortedOverlappingPairCache::btSortedOverlappingPairCache():
m_blockedForChanges(false),
m_hasDeferredRemoval(true),
m_overlapFilterCallback(0),
m_ghostPairCallback(0)
{
int initialAllocatedSize = 2;
int initialAllocatedSize= 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
}
@@ -539,73 +551,82 @@ btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
{
}
void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher)
void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
{
if (pair.m_algorithm)
{
{
pair.m_algorithm->~btCollisionAlgorithm();
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
pair.m_algorithm = 0;
pair.m_algorithm=0;
gRemovePairs--;
}
}
}
void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class CleanPairCallback : public btOverlapCallback
class CleanPairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_cleanProxy;
btOverlappingPairCache* m_pairCache;
btOverlappingPairCache* m_pairCache;
btDispatcher* m_dispatcher;
public:
CleanPairCallback(btBroadphaseProxy* cleanProxy, btOverlappingPairCache* pairCache, btDispatcher* dispatcher)
: m_cleanProxy(cleanProxy),
m_pairCache(pairCache),
m_dispatcher(dispatcher)
CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
:m_cleanProxy(cleanProxy),
m_pairCache(pairCache),
m_dispatcher(dispatcher)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
virtual bool processOverlap(btBroadphasePair& pair)
{
if ((pair.m_pProxy0 == m_cleanProxy) ||
(pair.m_pProxy1 == m_cleanProxy))
{
m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
}
return false;
}
};
CleanPairCallback cleanPairs(proxy, this, dispatcher);
CleanPairCallback cleanPairs(proxy,this,dispatcher);
processAllOverlappingPairs(&cleanPairs,dispatcher);
processAllOverlappingPairs(&cleanPairs, dispatcher);
}
void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class RemovePairCallback : public btOverlapCallback
class RemovePairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_obsoleteProxy;
public:
RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
: m_obsoleteProxy(obsoleteProxy)
:m_obsoleteProxy(obsoleteProxy)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
virtual bool processOverlap(btBroadphasePair& pair)
{
return ((pair.m_pProxy0 == m_obsoleteProxy) ||
(pair.m_pProxy1 == m_obsoleteProxy));
(pair.m_pProxy1 == m_obsoleteProxy));
}
};
RemovePairCallback removeCallback(proxy);
processAllOverlappingPairs(&removeCallback, dispatcher);
processAllOverlappingPairs(&removeCallback,dispatcher);
}
void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
{
//should already be sorted
}

View File

@@ -16,6 +16,7 @@ subject to the following restrictions:
#ifndef BT_OVERLAPPING_PAIR_CACHE_H
#define BT_OVERLAPPING_PAIR_CACHE_H
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
#include "btOverlappingPairCallback.h"
@@ -23,164 +24,174 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h"
class btDispatcher;
typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
struct btOverlapCallback
struct btOverlapCallback
{
virtual ~btOverlapCallback()
{
}
{}
//return true for deletion of the pair
virtual bool processOverlap(btBroadphasePair& pair) = 0;
virtual bool processOverlap(btBroadphasePair& pair) = 0;
};
struct btOverlapFilterCallback
{
virtual ~btOverlapFilterCallback()
{
}
{}
// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const = 0;
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
};
const int BT_NULL_PAIR = 0xffffffff;
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 ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
virtual void cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher) = 0;
virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
virtual int getNumOverlappingPairs() const = 0;
virtual bool needsBroadphaseCollision(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1) const = 0;
virtual btOverlapFilterCallback* getOverlapFilterCallback() = 0;
virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0;
virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* dispatcher) = 0;
virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
virtual void processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& /*dispatchInfo*/)
{
processAllOverlappingPairs(callback, dispatcher);
}
virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
virtual bool hasDeferredRemoval() = 0;
virtual bool hasDeferredRemoval() = 0;
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0;
virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) = 0;
virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
};
/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
ATTRIBUTE_ALIGNED16(class)
btHashedOverlappingPairCache : public btOverlappingPairCache
class btHashedOverlappingPairCache : public btOverlappingPairCache
{
btBroadphasePairArray m_overlappingPairArray;
btBroadphasePairArray m_overlappingPairArray;
btOverlapFilterCallback* m_overlapFilterCallback;
protected:
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
btOverlappingPairCallback* m_ghostPairCallback;
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
btOverlappingPairCallback* m_ghostPairCallback;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btHashedOverlappingPairCache();
virtual ~btHashedOverlappingPairCache();
void removeOverlappingPairsContainingProxy(btBroadphaseProxy * proxy, btDispatcher * dispatcher);
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
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);
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)
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
if (!needsBroadphaseCollision(proxy0, proxy1))
gAddedPairs++;
if (!needsBroadphaseCollision(proxy0,proxy1))
return 0;
return internalAddPair(proxy0, proxy1);
return internalAddPair(proxy0,proxy1);
}
void cleanProxyFromPairs(btBroadphaseProxy * proxy, btDispatcher * dispatcher);
virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher * dispatcher);
void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void processAllOverlappingPairs(btOverlapCallback * callback, btDispatcher * dispatcher, const struct btDispatcherInfo& dispatchInfo);
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
virtual btBroadphasePair* getOverlappingPairArrayPtr()
virtual btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
btBroadphasePairArray& getOverlappingPairArray()
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
const btBroadphasePairArray& getOverlappingPairArray() const
const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
void cleanOverlappingPair(btBroadphasePair & pair, btDispatcher * dispatcher);
void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
btBroadphasePair* findPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1);
btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
int GetCount() const { return m_overlappingPairArray.size(); }
// btBroadphasePair* GetPairs() { return m_pairs; }
// btBroadphasePair* GetPairs() { return m_pairs; }
btOverlapFilterCallback* getOverlapFilterCallback()
{
return m_overlapFilterCallback;
}
void setOverlapFilterCallback(btOverlapFilterCallback * callback)
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
{
m_overlapFilterCallback = callback;
}
int getNumOverlappingPairs() const
int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
private:
btBroadphasePair* internalAddPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1);
btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
void growTables();
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;
}
@@ -200,37 +211,43 @@ private:
}
*/
SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
{
unsigned int key = proxyId1 | (proxyId2 << 16);
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 >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
key ^= (key >> 16);
return static_cast<unsigned int>(key);
}
SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1, int hash)
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 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);
#endif
#endif
int index = m_hashTable[hash];
while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
{
index = m_next[index];
}
if (index == BT_NULL_PAIR)
if ( index == BT_NULL_PAIR )
{
return NULL;
}
@@ -240,136 +257,155 @@ private:
return &m_overlappingPairArray[index];
}
virtual bool hasDeferredRemoval()
virtual bool hasDeferredRemoval()
{
return false;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback * ghostPairCallback)
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
virtual void sortOverlappingPairs(btDispatcher * dispatcher);
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
};
///btSortedOverlappingPairCache maintains the objects with overlapping AABB
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
class btSortedOverlappingPairCache : public btOverlappingPairCache
class btSortedOverlappingPairCache : public btOverlappingPairCache
{
protected:
//avoid brute-force finding all the time
btBroadphasePairArray m_overlappingPairArray;
protected:
//avoid brute-force finding all the time
btBroadphasePairArray m_overlappingPairArray;
//during the dispatch, check that user doesn't destroy/create proxy
bool m_blockedForChanges;
//during the dispatch, check that user doesn't destroy/create proxy
bool m_blockedForChanges;
///by default, do the removal during the pair traversal
bool m_hasDeferredRemoval;
///by default, do the removal during the pair traversal
bool m_hasDeferredRemoval;
//if set, use the callback instead of the built in filter in needBroadphaseCollision
btOverlapFilterCallback* m_overlapFilterCallback;
//if set, use the callback instead of the built in filter in needBroadphaseCollision
btOverlapFilterCallback* m_overlapFilterCallback;
btOverlappingPairCallback* m_ghostPairCallback;
btOverlappingPairCallback* m_ghostPairCallback;
public:
btSortedOverlappingPairCache();
virtual ~btSortedOverlappingPairCache();
public:
btSortedOverlappingPairCache();
virtual ~btSortedOverlappingPairCache();
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* dispatcher);
void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher);
void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
void cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher);
btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
{
if (m_overlapFilterCallback)
return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
return collides;
}
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const
{
if (m_overlapFilterCallback)
return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
return collides;
}
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btBroadphasePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
btOverlapFilterCallback* getOverlapFilterCallback()
{
return m_overlapFilterCallback;
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
{
m_overlapFilterCallback = callback;
}
int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
virtual bool hasDeferredRemoval()
{
return m_hasDeferredRemoval;
}
btOverlapFilterCallback* getOverlapFilterCallback()
{
return m_overlapFilterCallback;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
{
m_overlapFilterCallback = callback;
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
virtual bool hasDeferredRemoval()
{
return m_hasDeferredRemoval;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
{
m_ghostPairCallback = ghostPairCallback;
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
};
///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
class btNullPairCache : public btOverlappingPairCache
{
btBroadphasePairArray m_overlappingPairArray;
btBroadphasePairArray m_overlappingPairArray;
public:
virtual btBroadphasePair* getOverlappingPairArrayPtr()
virtual btBroadphasePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btBroadphasePair* getOverlappingPairArrayPtr() const
const btBroadphasePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
btBroadphasePairArray& getOverlappingPairArray()
btBroadphasePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/, btDispatcher* /*dispatcher*/)
virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
{
}
virtual int getNumOverlappingPairs() const
@@ -377,23 +413,16 @@ public:
return 0;
}
virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/, btDispatcher* /*dispatcher*/)
virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
{
}
virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
{
}
bool needsBroadphaseCollision(btBroadphaseProxy*, btBroadphaseProxy*) const
{
return true;
}
btOverlapFilterCallback* getOverlapFilterCallback()
{
return 0;
}
virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
{
}
virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* /*dispatcher*/)
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
{
}
@@ -402,33 +431,39 @@ public:
return 0;
}
virtual bool hasDeferredRemoval()
virtual bool hasDeferredRemoval()
{
return true;
}
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
{
}
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
{
return 0;
}
virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/, btDispatcher* /*dispatcher*/)
virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/)
{
return 0;
}
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/, btDispatcher* /*dispatcher*/)
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
{
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher)
{
(void) dispatcher;
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher)
{
(void)dispatcher;
}
};
#endif //BT_OVERLAPPING_PAIR_CACHE_H
#endif //BT_OVERLAPPING_PAIR_CACHE_H

View File

@@ -18,24 +18,23 @@ subject to the following restrictions:
#define OVERLAPPING_PAIR_CALLBACK_H
class btDispatcher;
struct btBroadphasePair;
struct btBroadphasePair;
///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
class btOverlappingPairCallback
{
protected:
btOverlappingPairCallback() {}
public:
virtual ~btOverlappingPairCallback()
{
}
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0;
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher) = 0;
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0;
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0, btDispatcher* dispatcher) = 0;
};
#endif //OVERLAPPING_PAIR_CALLBACK_H
#endif //OVERLAPPING_PAIR_CALLBACK_H

File diff suppressed because it is too large Load Diff

View File

@@ -22,11 +22,11 @@ class btSerializer;
#ifdef DEBUG_CHECK_DEQUANTIZATION
#ifdef __SPU__
#define printf spu_printf
#endif //__SPU__
#endif //__SPU__
#include <stdio.h>
#include <stdlib.h>
#endif //DEBUG_CHECK_DEQUANTIZATION
#endif //DEBUG_CHECK_DEQUANTIZATION
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedAllocator.h"
@@ -41,10 +41,13 @@ class btSerializer;
#define btQuantizedBvhDataName "btQuantizedBvhFloatData"
#endif
//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
//Note: currently we have 16 bytes per quantized node
#define MAX_SUBTREE_SIZE_IN_BYTES 2048
#define MAX_SUBTREE_SIZE_IN_BYTES 2048
// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
// actually) triangles each (since the sign bit is reserved
@@ -52,16 +55,15 @@ class btSerializer;
///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
ATTRIBUTE_ALIGNED16(struct)
btQuantizedBvhNode
ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode
{
BT_DECLARE_ALIGNED_ALLOCATOR();
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes
int m_escapeIndexOrTriangleIndex;
int m_escapeIndexOrTriangleIndex;
bool isLeafNode() const
{
@@ -73,67 +75,68 @@ btQuantizedBvhNode
btAssert(!isLeafNode());
return -m_escapeIndexOrTriangleIndex;
}
int getTriangleIndex() const
int getTriangleIndex() const
{
btAssert(isLeafNode());
unsigned int x = 0;
unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
unsigned int x=0;
unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
// Get only the lower bits where the triangle index is stored
return (m_escapeIndexOrTriangleIndex & ~(y));
return (m_escapeIndexOrTriangleIndex&~(y));
}
int getPartId() const
int getPartId() const
{
btAssert(isLeafNode());
// Get only the highest bits where the part index is stored
return (m_escapeIndexOrTriangleIndex >> (31 - MAX_NUM_PARTS_IN_BITS));
return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
}
};
}
;
/// btOptimizedBvhNode contains both internal and leaf node information.
/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
ATTRIBUTE_ALIGNED16(struct)
btOptimizedBvhNode
ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode
{
BT_DECLARE_ALIGNED_ALLOCATOR();
//32 bytes
btVector3 m_aabbMinOrg;
btVector3 m_aabbMaxOrg;
btVector3 m_aabbMinOrg;
btVector3 m_aabbMaxOrg;
//4
int m_escapeIndex;
int m_escapeIndex;
//8
//for child nodes
int m_subPart;
int m_triangleIndex;
int m_subPart;
int m_triangleIndex;
//pad the size to 64 bytes
char m_padding[20];
//pad the size to 64 bytes
char m_padding[20];
};
///btBvhSubtreeInfo provides info to gather a subtree of limited size
ATTRIBUTE_ALIGNED16(class)
btBvhSubtreeInfo
ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
{
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
//12 bytes
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
unsigned short int m_quantizedAabbMin[3];
unsigned short int m_quantizedAabbMax[3];
//4 bytes, points to the root of the subtree
int m_rootNodeIndex;
int m_rootNodeIndex;
//4 bytes
int m_subtreeSize;
int m_padding[3];
int m_subtreeSize;
int m_padding[3];
btBvhSubtreeInfo()
{
//memset(&m_padding[0], 0, sizeof(m_padding));
}
void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
{
m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
@@ -142,12 +145,14 @@ public:
m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
}
};
}
;
class btNodeOverlapCallback
{
public:
virtual ~btNodeOverlapCallback(){};
virtual ~btNodeOverlapCallback() {};
virtual void processNode(int subPart, int triangleIndex) = 0;
};
@@ -155,16 +160,18 @@ public:
#include "LinearMath/btAlignedAllocator.h"
#include "LinearMath/btAlignedObjectArray.h"
///for code readability:
typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
///It is used by the btBvhTriangleMeshShape as midphase.
///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase.
///It is recommended to use quantization for better performance and lower memory requirements.
ATTRIBUTE_ALIGNED16(class)
btQuantizedBvh
ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
{
public:
enum btTraversalMode
@@ -175,47 +182,54 @@ public:
};
protected:
btVector3 m_bvhAabbMin;
btVector3 m_bvhAabbMax;
btVector3 m_bvhQuantization;
int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
int m_curNodeIndex;
btVector3 m_bvhAabbMin;
btVector3 m_bvhAabbMax;
btVector3 m_bvhQuantization;
int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
int m_curNodeIndex;
//quantization data
bool m_useQuantization;
bool m_useQuantization;
NodeArray m_leafNodes;
NodeArray m_contiguousNodes;
QuantizedNodeArray m_quantizedLeafNodes;
QuantizedNodeArray m_quantizedContiguousNodes;
btTraversalMode m_traversalMode;
BvhSubtreeInfoArray m_SubtreeHeaders;
NodeArray m_leafNodes;
NodeArray m_contiguousNodes;
QuantizedNodeArray m_quantizedLeafNodes;
QuantizedNodeArray m_quantizedContiguousNodes;
btTraversalMode m_traversalMode;
BvhSubtreeInfoArray m_SubtreeHeaders;
//This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
mutable int m_subtreeHeaderCount;
///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
///this might be refactored into a virtual, it is usually not calculated at run-time
void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
{
if (m_useQuantization)
{
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0], aabbMin, 0);
}
else
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
} else
{
m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
}
}
void setInternalNodeAabbMax(int nodeIndex, const btVector3& aabbMax)
void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
{
if (m_useQuantization)
{
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0], aabbMax, 1);
}
else
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
} else
{
m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
}
@@ -229,102 +243,115 @@ protected:
}
//non-quantized
return m_leafNodes[nodeIndex].m_aabbMinOrg;
}
btVector3 getAabbMax(int nodeIndex) const
{
if (m_useQuantization)
{
return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
}
}
//non-quantized
return m_leafNodes[nodeIndex].m_aabbMaxOrg;
}
void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
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)
void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax)
{
if (m_useQuantization)
{
unsigned short int quantizedAabbMin[3];
unsigned short int quantizedAabbMax[3];
quantize(quantizedAabbMin, newAabbMin, 0);
quantize(quantizedAabbMax, newAabbMax, 1);
for (int i = 0; i < 3; i++)
quantize(quantizedAabbMin,newAabbMin,0);
quantize(quantizedAabbMax,newAabbMax,1);
for (int i=0;i<3;i++)
{
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
}
}
else
} else
{
//non-quantized
m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
}
}
void swapLeafNodes(int firstIndex, int secondIndex);
void swapLeafNodes(int firstIndex,int secondIndex);
void assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex);
void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
protected:
void buildTree(int startIndex, int endIndex);
int calcSplittingAxis(int startIndex, int endIndex);
int sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis);
void buildTree (int startIndex,int endIndex);
void walkStacklessTree(btNodeOverlapCallback * nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const;
int calcSplittingAxis(int startIndex,int endIndex);
void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
void walkStacklessQuantizedTree(btNodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const;
void walkStacklessTreeAgainstRay(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
void walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, 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;
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;
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;
void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
void updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex);
void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btQuantizedBvh();
virtual ~btQuantizedBvh();
///***************************************** expert/internal use only *************************
void setQuantizationValues(const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, btScalar quantizationMargin = btScalar(1.0));
QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
void buildInternal();
void buildInternal();
///***************************************** expert/internal use only *************************
void reportAabbOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const;
void reportRayOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
void reportBoxCastOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) const;
void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point, int isMax) const
SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
{
btAssert(m_useQuantization);
btAssert(point.getX() <= m_bvhAabbMax.getX());
@@ -341,114 +368,122 @@ public:
///@todo: double-check this
if (isMax)
{
out[0] = (unsigned short)(((unsigned short)(v.getX() + btScalar(1.)) | 1));
out[1] = (unsigned short)(((unsigned short)(v.getY() + btScalar(1.)) | 1));
out[2] = (unsigned short)(((unsigned short)(v.getZ() + btScalar(1.)) | 1));
}
else
out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
} else
{
out[0] = (unsigned short)(((unsigned short)(v.getX()) & 0xfffe));
out[1] = (unsigned short)(((unsigned short)(v.getY()) & 0xfffe));
out[2] = (unsigned short)(((unsigned short)(v.getZ()) & 0xfffe));
out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
}
#ifdef DEBUG_CHECK_DEQUANTIZATION
btVector3 newPoint = unQuantize(out);
if (isMax)
{
if (newPoint.getX() < point.getX())
{
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
}
if (newPoint.getY() < point.getY())
{
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
}
if (newPoint.getZ() < point.getZ())
{
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
}
}
else
} else
{
if (newPoint.getX() > point.getX())
{
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
}
if (newPoint.getY() > point.getY())
{
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
}
if (newPoint.getZ() > point.getZ())
{
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
}
}
#endif //DEBUG_CHECK_DEQUANTIZATION
#endif //DEBUG_CHECK_DEQUANTIZATION
}
SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2, int isMax) const
SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
{
btAssert(m_useQuantization);
btVector3 clampedPoint(point2);
clampedPoint.setMax(m_bvhAabbMin);
clampedPoint.setMin(m_bvhAabbMax);
quantize(out, clampedPoint, isMax);
}
quantize(out,clampedPoint,isMax);
SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
}
SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
{
btVector3 vecOut;
vecOut.setValue(
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;
vecOut += m_bvhAabbMin;
return vecOut;
}
///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
void setTraversalMode(btTraversalMode traversalMode)
void setTraversalMode(btTraversalMode traversalMode)
{
m_traversalMode = traversalMode;
}
SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
{
return m_quantizedContiguousNodes;
SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
{
return m_quantizedContiguousNodes;
}
SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
{
return m_SubtreeHeaders;
}
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
/////Calculate space needed to store BVH for serialization
unsigned calculateSerializeBufferSize() const;
/// Data buffer MUST be 16 byte aligned
virtual bool serialize(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
static btQuantizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
static unsigned int getAlignmentSerializationPadding();
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
virtual int calculateSerializeBufferSizeNew() const;
virtual int calculateSerializeBufferSizeNew() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
virtual void deSerializeFloat(struct btQuantizedBvhFloatData & quantizedBvhFloatData);
virtual void deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData);
virtual void deSerializeDouble(struct btQuantizedBvhDoubleData & quantizedBvhDoubleData);
virtual void deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData);
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
SIMD_FORCE_INLINE bool isQuantized()
{
@@ -459,37 +494,38 @@ private:
// Special "copy" constructor that allows for in-place deserialization
// Prevents btVector3's default constructor from being called, but doesn't inialize much else
// ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
btQuantizedBvh(btQuantizedBvh & other, bool ownsMemory);
};
btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
// clang-format off
// parser needs * with the name
struct btBvhSubtreeInfoData
}
;
struct btBvhSubtreeInfoData
{
int m_rootNodeIndex;
int m_subtreeSize;
int m_rootNodeIndex;
int m_subtreeSize;
unsigned short m_quantizedAabbMin[3];
unsigned short m_quantizedAabbMax[3];
};
struct btOptimizedBvhNodeFloatData
{
btVector3FloatData m_aabbMinOrg;
btVector3FloatData m_aabbMaxOrg;
int m_escapeIndex;
int m_subPart;
int m_triangleIndex;
btVector3FloatData m_aabbMinOrg;
btVector3FloatData m_aabbMaxOrg;
int m_escapeIndex;
int m_subPart;
int m_triangleIndex;
char m_pad[4];
};
struct btOptimizedBvhNodeDoubleData
{
btVector3DoubleData m_aabbMinOrg;
btVector3DoubleData m_aabbMaxOrg;
int m_escapeIndex;
int m_subPart;
int m_triangleIndex;
char m_pad[4];
btVector3DoubleData m_aabbMinOrg;
btVector3DoubleData m_aabbMaxOrg;
int m_escapeIndex;
int m_subPart;
int m_triangleIndex;
char m_pad[4];
};
@@ -533,11 +569,13 @@ struct btQuantizedBvhDoubleData
int m_numSubtreeHeaders;
btBvhSubtreeInfoData *m_subTreeInfoPtr;
};
// clang-format on
SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const
SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const
{
return sizeof(btQuantizedBvhData);
}
#endif //BT_QUANTIZED_BVH_H
#endif //BT_QUANTIZED_BVH_H

View File

@@ -24,45 +24,52 @@ subject to the following restrictions:
#include <new>
void btSimpleBroadphase::validate()
extern int gOverlappingPairs;
void btSimpleBroadphase::validate()
{
for (int i = 0; i < m_numHandles; i++)
for (int i=0;i<m_numHandles;i++)
{
for (int j = i + 1; j < m_numHandles; j++)
for (int j=i+1;j<m_numHandles;j++)
{
btAssert(&m_pHandles[i] != &m_pHandles[j]);
}
}
}
btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
: m_pairCache(overlappingPairCache),
m_ownsPairCache(false),
m_invalidPair(0)
:m_pairCache(overlappingPairCache),
m_ownsPairCache(false),
m_invalidPair(0)
{
if (!overlappingPairCache)
{
void* mem = btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16);
m_pairCache = new (mem) btHashedOverlappingPairCache();
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_pHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy)*maxProxies,16);
m_pHandles = new(m_pHandlesRawPtr) btSimpleBroadphaseProxy[maxProxies];
m_maxHandles = maxProxies;
m_numHandles = 0;
m_firstFreeHandle = 0;
m_LastHandleIndex = -1;
{
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[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()
@@ -76,25 +83,26 @@ btSimpleBroadphase::~btSimpleBroadphase()
}
}
btBroadphaseProxy* btSimpleBroadphase::createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* /*dispatcher*/)
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_numHandles >= m_maxHandles)
{
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 ;-)
}
btAssert(aabbMin[0] <= aabbMax[0] && aabbMin[1] <= aabbMax[1] && aabbMin[2] <= aabbMax[2]);
btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]);
int newHandleIndex = allocHandle();
btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex]) btSimpleBroadphaseProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask);
btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy);
return proxy;
}
class RemovingOverlapCallback : public btOverlapCallback
class RemovingOverlapCallback : public btOverlapCallback
{
protected:
virtual bool processOverlap(btBroadphasePair& pair)
virtual bool processOverlap(btBroadphasePair& pair)
{
(void)pair;
btAssert(0);
@@ -104,13 +112,12 @@ protected:
class RemovePairContainingProxy
{
btBroadphaseProxy* m_targetProxy;
public:
btBroadphaseProxy* m_targetProxy;
public:
virtual ~RemovePairContainingProxy()
{
}
protected:
virtual bool processOverlap(btBroadphasePair& pair)
{
@@ -121,36 +128,38 @@ protected:
};
};
void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg, btDispatcher* dispatcher)
void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher)
{
m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg, dispatcher);
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
freeHandle(proxy0);
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
freeHandle(proxy0);
m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher);
//validate();
//validate();
}
void btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
void btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
{
const btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
aabbMin = sbp->m_aabbMin;
aabbMax = sbp->m_aabbMax;
}
void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
{
btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
sbp->m_aabbMin = aabbMin;
sbp->m_aabbMax = aabbMax;
}
void btSimpleBroadphase::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
void btSimpleBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
{
for (int i = 0; i <= m_LastHandleIndex; i++)
for (int i=0; i <= m_LastHandleIndex; i++)
{
btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
if (!proxy->m_clientObject)
if(!proxy->m_clientObject)
{
continue;
}
@@ -158,59 +167,69 @@ void btSimpleBroadphase::rayTest(const btVector3& rayFrom, const btVector3& rayT
}
}
void btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
void btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
{
for (int i = 0; i <= m_LastHandleIndex; i++)
for (int i=0; i <= m_LastHandleIndex; i++)
{
btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
if (!proxy->m_clientObject)
if(!proxy->m_clientObject)
{
continue;
}
if (TestAabbAgainstAabb2(aabbMin, aabbMax, proxy->m_aabbMin, proxy->m_aabbMax))
if (TestAabbAgainstAabb2(aabbMin,aabbMax,proxy->m_aabbMin,proxy->m_aabbMax))
{
callback.process(proxy);
}
}
}
bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0, btSimpleBroadphaseProxy* proxy1)
bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1)
{
return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] &&
return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] &&
proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] &&
proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2];
}
//then remove non-overlapping ones
class CheckOverlapCallback : public btOverlapCallback
{
public:
virtual bool processOverlap(btBroadphasePair& pair)
{
return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0), static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1)));
return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0),static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1)));
}
};
void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{
//first check for new overlapping pairs
int i, j;
int i,j;
if (m_numHandles >= 0)
{
int new_largest_index = -1;
for (i = 0; i <= m_LastHandleIndex; i++)
for (i=0; i <= m_LastHandleIndex; i++)
{
btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i];
if (!proxy0->m_clientObject)
if(!proxy0->m_clientObject)
{
continue;
}
new_largest_index = i;
for (j = i + 1; j <= m_LastHandleIndex; j++)
for (j=i+1; j <= m_LastHandleIndex; j++)
{
btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j];
btAssert(proxy0 != proxy1);
if (!proxy1->m_clientObject)
if(!proxy1->m_clientObject)
{
continue;
}
@@ -218,20 +237,19 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
if (aabbOverlap(p0, p1))
if (aabbOverlap(p0,p1))
{
if (!m_pairCache->findPair(proxy0, proxy1))
if ( !m_pairCache->findPair(proxy0,proxy1))
{
m_pairCache->addOverlappingPair(proxy0, proxy1);
m_pairCache->addOverlappingPair(proxy0,proxy1);
}
}
else
} else
{
if (!m_pairCache->hasDeferredRemoval())
{
if (m_pairCache->findPair(proxy0, proxy1))
if ( m_pairCache->findPair(proxy0,proxy1))
{
m_pairCache->removeOverlappingPair(proxy0, proxy1, dispatcher);
m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
}
}
}
@@ -242,7 +260,8 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
if (m_ownsPairCache && m_pairCache->hasDeferredRemoval())
{
btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
@@ -250,13 +269,16 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
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++)
for (i=0;i<overlappingPairArray.size();i++)
{
btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
@@ -267,18 +289,16 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
if (!isDuplicate)
{
bool hasOverlap = testAabbOverlap(pair.m_pProxy0, pair.m_pProxy1);
bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
if (hasOverlap)
{
needsRemoval = false; //callback->processOverlap(pair);
}
else
needsRemoval = false;//callback->processOverlap(pair);
} else
{
needsRemoval = true;
}
}
else
} else
{
//remove duplicate
needsRemoval = true;
@@ -288,14 +308,16 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
if (needsRemoval)
{
m_pairCache->cleanOverlappingPair(pair, dispatcher);
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:
@@ -307,19 +329,21 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
#endif //CLEAN_INVALID_PAIRS
#endif//CLEAN_INVALID_PAIRS
}
}
}
bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
return aabbOverlap(p0, p1);
return aabbOverlap(p0,p1);
}
void btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
void btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
{
//not yet
}

View File

@@ -16,47 +16,57 @@ subject to the following restrictions:
#ifndef BT_SIMPLE_BROADPHASE_H
#define BT_SIMPLE_BROADPHASE_H
#include "btOverlappingPairCache.h"
struct btSimpleBroadphaseProxy : public btBroadphaseProxy
{
int m_nextFree;
int m_nextFree;
// int m_handleId;
// int m_handleId;
btSimpleBroadphaseProxy() {};
btSimpleBroadphaseProxy(){};
btSimpleBroadphaseProxy(const btVector3& minpt, const btVector3& maxpt, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
: btBroadphaseProxy(minpt, maxpt, userPtr, collisionFilterGroup, collisionFilterMask)
btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy)
:btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy)
{
(void)shapeType;
}
SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;}
SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;}
SIMD_FORCE_INLINE void SetNextFree(int next) { m_nextFree = next; }
SIMD_FORCE_INLINE int GetNextFree() const { return m_nextFree; }
};
///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead.
///It is a brute force aabb culling broadphase based on O(n^2) aabb checks
class btSimpleBroadphase : public btBroadphaseInterface
{
protected:
int m_numHandles; // number of active handles
int m_maxHandles; // max number of handles
int m_LastHandleIndex;
btSimpleBroadphaseProxy* m_pHandles; // handles pool
protected:
int m_numHandles; // number of active handles
int m_maxHandles; // max number of handles
int m_LastHandleIndex;
btSimpleBroadphaseProxy* m_pHandles; // handles pool
void* m_pHandlesRawPtr;
int m_firstFreeHandle; // free handles list
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++;
if (freeHandle > m_LastHandleIndex)
if(freeHandle > m_LastHandleIndex)
{
m_LastHandleIndex = freeHandle;
}
@@ -65,9 +75,9 @@ protected:
void freeHandle(btSimpleBroadphaseProxy* proxy)
{
int handle = int(proxy - m_pHandles);
int handle = int(proxy-m_pHandles);
btAssert(handle >= 0 && handle < m_maxHandles);
if (handle == m_LastHandleIndex)
if(handle == m_LastHandleIndex)
{
m_LastHandleIndex--;
}
@@ -79,18 +89,20 @@ protected:
m_numHandles--;
}
btOverlappingPairCache* m_pairCache;
bool m_ownsPairCache;
btOverlappingPairCache* m_pairCache;
bool m_ownsPairCache;
int m_invalidPair;
int m_invalidPair;
inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
{
btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxy);
return proxy0;
}
inline const btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const
inline const btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const
{
const btSimpleBroadphaseProxy* proxy0 = static_cast<const btSimpleBroadphaseProxy*>(proxy);
return proxy0;
@@ -99,50 +111,61 @@ protected:
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
void validate();
void validate();
protected:
public:
btSimpleBroadphase(int maxProxies = 16384, btOverlappingPairCache* overlappingPairCache = 0);
btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0);
virtual ~btSimpleBroadphase();
static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0, btSimpleBroadphaseProxy* proxy1);
virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1);
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
btOverlappingPairCache* getOverlappingPairCache()
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
btOverlappingPairCache* getOverlappingPairCache()
{
return m_pairCache;
}
const btOverlappingPairCache* getOverlappingPairCache() const
const btOverlappingPairCache* getOverlappingPairCache() const
{
return m_pairCache;
}
bool testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
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
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
{
aabbMin.setValue(-BT_LARGE_FLOAT, -BT_LARGE_FLOAT, -BT_LARGE_FLOAT);
aabbMax.setValue(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
}
virtual void printStats()
virtual void printStats()
{
// printf("btSimpleBroadphase.h\n");
// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
// printf("btSimpleBroadphase.h\n");
// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
}
};
#endif //BT_SIMPLE_BROADPHASE_H
#endif //BT_SIMPLE_BROADPHASE_H

View File

@@ -18,162 +18,145 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btTriangleShape.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere, btTriangleShape* triangle, btScalar contactBreakingThreshold)
: m_sphere(sphere),
m_triangle(triangle),
m_contactBreakingThreshold(contactBreakingThreshold)
SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold)
:m_sphere(sphere),
m_triangle(triangle),
m_contactBreakingThreshold(contactBreakingThreshold)
{
}
void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults)
void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
{
(void)debugDraw;
const btTransform& transformA = input.m_transformA;
const btTransform& transformB = input.m_transformB;
btVector3 point, normal;
btVector3 point,normal;
btScalar timeOfImpact = btScalar(1.);
btScalar depth = btScalar(0.);
// output.m_distance = btScalar(BT_LARGE_FLOAT);
// output.m_distance = btScalar(BT_LARGE_FLOAT);
//move sphere into triangle space
btTransform sphereInTr = transformB.inverseTimes(transformA);
btTransform sphereInTr = transformB.inverseTimes(transformA);
if (collide(sphereInTr.getOrigin(), point, normal, depth, timeOfImpact, m_contactBreakingThreshold))
if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold))
{
if (swapResults)
{
btVector3 normalOnB = transformB.getBasis() * normal;
btVector3 normalOnB = transformB.getBasis()*normal;
btVector3 normalOnA = -normalOnB;
btVector3 pointOnA = transformB * point + normalOnB * depth;
output.addContactPoint(normalOnA, pointOnA, depth);
}
else
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);
}
}
}
// See also geometrictools.com
// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to, const btVector3& p, btVector3& nearest);
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest);
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to, const btVector3& p, btVector3& nearest)
{
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) {
btVector3 diff = p - from;
btVector3 v = to - from;
btScalar t = v.dot(diff);
if (t > 0)
{
if (t > 0) {
btScalar dotVV = v.dot(v);
if (t < dotVV)
{
if (t < dotVV) {
t /= dotVV;
diff -= t * v;
}
else
{
diff -= t*v;
} else {
t = 1;
diff -= v;
}
}
else
} else
t = 0;
nearest = from + t * v;
return diff.dot(diff);
nearest = from + t*v;
return diff.dot(diff);
}
bool SphereTriangleDetector::facecontains(const btVector3& p, const btVector3* vertices, btVector3& normal)
{
bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal) {
btVector3 lp(p);
btVector3 lnormal(normal);
return pointInTriangle(vertices, lnormal, &lp);
}
bool SphereTriangleDetector::collide(const btVector3& sphereCenter, btVector3& point, btVector3& resultNormal, btScalar& depth, btScalar& timeOfImpact, btScalar contactBreakingThreshold)
bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold)
{
const btVector3* vertices = &m_triangle->getVertexPtr(0);
const btVector3* vertices = &m_triangle->getVertexPtr(0);
btScalar radius = m_sphere->getRadius();
btScalar radiusWithThreshold = radius + contactBreakingThreshold;
btVector3 normal = (vertices[1] - vertices[0]).cross(vertices[2] - vertices[0]);
btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
normal.normalize();
btVector3 p1ToCentre = sphereCenter - vertices[0];
btScalar distanceFromPlane = p1ToCentre.dot(normal);
btScalar l2 = normal.length2();
if (distanceFromPlane < btScalar(0.))
{
//triangle facing the other way
distanceFromPlane *= btScalar(-1.);
normal *= btScalar(-1.);
}
bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
// Check for contact / intersection
bool hasContact = false;
btVector3 contactPoint;
if (isInsideContactPlane) {
if (facecontains(sphereCenter,vertices,normal)) {
// Inside the contact wedge - touches a point on the shell plane
hasContact = true;
contactPoint = sphereCenter - normal*distanceFromPlane;
} else {
// Could be inside one of the contact capsules
btScalar contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;
btVector3 nearestOnEdge;
for (int i = 0; i < m_triangle->getNumEdges(); i++) {
btVector3 pa;
btVector3 pb;
m_triangle->getEdge(i,pa,pb);
if (l2 >= SIMD_EPSILON * SIMD_EPSILON)
{
normal /= btSqrt(l2);
btVector3 p1ToCentre = sphereCenter - vertices[0];
btScalar distanceFromPlane = p1ToCentre.dot(normal);
if (distanceFromPlane < btScalar(0.))
{
//triangle facing the other way
distanceFromPlane *= btScalar(-1.);
normal *= btScalar(-1.);
}
bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
// Check for contact / intersection
if (isInsideContactPlane)
{
if (facecontains(sphereCenter, vertices, normal))
{
// Inside the contact wedge - touches a point on the shell plane
hasContact = true;
contactPoint = sphereCenter - normal * distanceFromPlane;
}
else
{
// Could be inside one of the contact capsules
btScalar contactCapsuleRadiusSqr = radiusWithThreshold * radiusWithThreshold;
btScalar minDistSqr = contactCapsuleRadiusSqr;
btVector3 nearestOnEdge;
for (int i = 0; i < m_triangle->getNumEdges(); i++)
{
btVector3 pa;
btVector3 pb;
m_triangle->getEdge(i, pa, pb);
btScalar distanceSqr = SegmentSqrDistance(pa, pb, sphereCenter, nearestOnEdge);
if (distanceSqr < minDistSqr)
{
// Yep, we're inside a capsule, and record the capsule with smallest distance
minDistSqr = distanceSqr;
hasContact = true;
contactPoint = nearestOnEdge;
}
btScalar distanceSqr = SegmentSqrDistance(pa,pb,sphereCenter, nearestOnEdge);
if (distanceSqr < contactCapsuleRadiusSqr) {
// Yep, we're inside a capsule
hasContact = true;
contactPoint = nearestOnEdge;
}
}
}
}
if (hasContact)
{
if (hasContact) {
btVector3 contactToCentre = sphereCenter - contactPoint;
btScalar distanceSqr = contactToCentre.length2();
if (distanceSqr < radiusWithThreshold * radiusWithThreshold)
if (distanceSqr < radiusWithThreshold*radiusWithThreshold)
{
if (distanceSqr > SIMD_EPSILON)
if (distanceSqr>SIMD_EPSILON)
{
btScalar distance = btSqrt(distanceSqr);
resultNormal = contactToCentre;
resultNormal.normalize();
point = contactPoint;
depth = -(radius - distance);
}
else
depth = -(radius-distance);
} else
{
resultNormal = normal;
point = contactPoint;
@@ -182,34 +165,36 @@ bool SphereTriangleDetector::collide(const btVector3& sphereCenter, btVector3& p
return true;
}
}
return false;
}
bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3& normal, btVector3* p)
bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p )
{
const btVector3* p1 = &vertices[0];
const btVector3* p2 = &vertices[1];
const btVector3* p3 = &vertices[2];
btVector3 edge1(*p2 - *p1);
btVector3 edge2(*p3 - *p2);
btVector3 edge3(*p1 - *p3);
btVector3 edge1( *p2 - *p1 );
btVector3 edge2( *p3 - *p2 );
btVector3 edge3( *p1 - *p3 );
btVector3 p1_to_p(*p - *p1);
btVector3 p2_to_p(*p - *p2);
btVector3 p3_to_p(*p - *p3);
btVector3 edge1_normal(edge1.cross(normal));
btVector3 edge2_normal(edge2.cross(normal));
btVector3 edge3_normal(edge3.cross(normal));
btVector3 p1_to_p( *p - *p1 );
btVector3 p2_to_p( *p - *p2 );
btVector3 p3_to_p( *p - *p3 );
btVector3 edge1_normal( edge1.cross(normal));
btVector3 edge2_normal( edge2.cross(normal));
btVector3 edge3_normal( edge3.cross(normal));
btScalar r1, r2, r3;
r1 = edge1_normal.dot(p1_to_p);
r2 = edge2_normal.dot(p2_to_p);
r3 = edge3_normal.dot(p3_to_p);
if ((r1 > 0 && r2 > 0 && r3 > 0) ||
(r1 <= 0 && r2 <= 0 && r3 <= 0))
r1 = edge1_normal.dot( p1_to_p );
r2 = edge2_normal.dot( p2_to_p );
r3 = edge3_normal.dot( p3_to_p );
if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) ||
( r1 <= 0 && r2 <= 0 && r3 <= 0 ) )
return true;
return false;
}

View File

@@ -18,26 +18,34 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
class btSphereShape;
class btTriangleShape;
/// sphere-triangle to match the btDiscreteCollisionDetectorInterface
struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface
{
virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
SphereTriangleDetector(btSphereShape* sphere, btTriangleShape* triangle, btScalar contactBreakingThreshold);
SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle, btScalar contactBreakingThreshold);
virtual ~SphereTriangleDetector(){};
virtual ~SphereTriangleDetector() {};
bool collide(const btVector3& sphereCenter, btVector3& point, btVector3& resultNormal, btScalar& depth, btScalar& timeOfImpact, btScalar contactBreakingThreshold);
bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold);
private:
bool pointInTriangle(const btVector3 vertices[], const btVector3& normal, btVector3* p);
bool facecontains(const btVector3& p, const btVector3* vertices, btVector3& normal);
bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p );
bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal);
btSphereShape* m_sphere;
btTriangleShape* m_triangle;
btScalar m_contactBreakingThreshold;
btScalar m_contactBreakingThreshold;
};
#endif //BT_SPHERE_TRIANGLE_DETECTOR_H
#endif //BT_SPHERE_TRIANGLE_DETECTOR_H

View File

@@ -17,31 +17,31 @@ subject to the following restrictions:
#include "btCollisionDispatcher.h"
#include "btCollisionObject.h"
btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btCollisionAlgorithm(ci)
btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci)
:btCollisionAlgorithm(ci)
//,
//m_colObj0(0),
//m_colObj1(0)
{
}
btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper*, const btCollisionObjectWrapper*)
: btCollisionAlgorithm(ci)
btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* )
:btCollisionAlgorithm(ci)
//,
//m_colObj0(0),
//m_colObj1(0)
{
// if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
// {
// m_colObj0 = colObj0;
// m_colObj1 = colObj1;
//
// m_colObj0->activate();
// m_colObj1->activate();
// }
// if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
// {
// m_colObj0 = colObj0;
// m_colObj1 = colObj1;
//
// m_colObj0->activate();
// m_colObj1->activate();
// }
}
btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm()
{
// m_colObj0->activate();
// m_colObj1->activate();
// m_colObj0->activate();
// m_colObj1->activate();
}

View File

@@ -21,15 +21,16 @@ subject to the following restrictions:
///This class is not enabled yet (work-in-progress) to more aggressively activate objects.
class btActivatingCollisionAlgorithm : public btCollisionAlgorithm
{
// btCollisionObject* m_colObj0;
// btCollisionObject* m_colObj1;
protected:
btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
// btCollisionObject* m_colObj0;
// btCollisionObject* m_colObj1;
public:
btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci);
btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btActivatingCollisionAlgorithm();
};
#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H
#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H

View File

@@ -26,55 +26,61 @@ subject to the following restrictions:
#define USE_PERSISTENT_CONTACTS 1
btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* obj0Wrap, const btCollisionObjectWrapper* obj1Wrap)
: btActivatingCollisionAlgorithm(ci, obj0Wrap, obj1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* obj0Wrap,const btCollisionObjectWrapper* obj1Wrap)
: btActivatingCollisionAlgorithm(ci,obj0Wrap,obj1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
{
if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0Wrap->getCollisionObject(), obj1Wrap->getCollisionObject()))
if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0Wrap->getCollisionObject(),obj1Wrap->getCollisionObject()))
{
m_manifoldPtr = m_dispatcher->getNewManifold(obj0Wrap->getCollisionObject(), obj1Wrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(obj0Wrap->getCollisionObject(),obj1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
btBox2dBox2dCollisionAlgorithm::~btBox2dBox2dCollisionAlgorithm()
{
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
}
void b2CollidePolygons(btManifoldResult* manifold, const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB);
void b2CollidePolygons(btManifoldResult* manifold, const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB);
//#include <stdio.h>
void btBox2dBox2dCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btBox2dBox2dCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
const btBox2dShape* box0 = (const btBox2dShape*)body0Wrap->getCollisionShape();
const btBox2dShape* box1 = (const btBox2dShape*)body1Wrap->getCollisionShape();
resultOut->setPersistentManifold(m_manifoldPtr);
b2CollidePolygons(resultOut, box0, body0Wrap->getWorldTransform(), box1, body1Wrap->getWorldTransform());
b2CollidePolygons(resultOut,box0,body0Wrap->getWorldTransform(),box1,body1Wrap->getWorldTransform());
// refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
}
btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/, btCollisionObject* /*body1*/, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
{
//not yet
return 1.f;
}
struct ClipVertex
{
btVector3 v;
@@ -83,16 +89,16 @@ struct ClipVertex
//b2ContactID id;
};
#define b2Dot(a, b) (a).dot(b)
#define b2Mul(a, b) (a) * (b)
#define b2MulT(a, b) (a).transpose() * (b)
#define b2Cross(a, b) (a).cross(b)
#define btCrossS(a, s) btVector3(s* a.getY(), -s* a.getX(), 0.f)
#define b2Dot(a,b) (a).dot(b)
#define b2Mul(a,b) (a)*(b)
#define b2MulT(a,b) (a).transpose()*(b)
#define b2Cross(a,b) (a).cross(b)
#define btCrossS(a,s) btVector3(s * a.getY(), -s * a.getX(),0.f)
int b2_maxManifoldPoints = 2;
int b2_maxManifoldPoints =2;
static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
const btVector3& normal, btScalar offset)
const btVector3& normal, btScalar offset)
{
// Start with no output points
int numOut = 0;
@@ -127,7 +133,7 @@ static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
// Find the separation between poly1 and poly2 for a give edge normal on poly1.
static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1, int edge1,
const btBox2dShape* poly2, const btTransform& xf2)
const btBox2dShape* poly2, const btTransform& xf2)
{
const btVector3* vertices1 = poly1->getVertices();
const btVector3* normals1 = poly1->getNormals();
@@ -145,8 +151,8 @@ static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1
int index = 0;
btScalar minDot = BT_LARGE_FLOAT;
if (count2 > 0)
index = (int)normal1.minDot(vertices2, count2, minDot);
if( count2 > 0 )
index = (int) normal1.minDot( vertices2, count2, minDot);
btVector3 v1 = b2Mul(xf1, vertices1[edge1]);
btVector3 v2 = b2Mul(xf2, vertices2[index]);
@@ -156,8 +162,8 @@ static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1
// Find the max separation between poly1 and poly2 using edge normals from poly1.
static btScalar FindMaxSeparation(int* edgeIndex,
const btBox2dShape* poly1, const btTransform& xf1,
const btBox2dShape* poly2, const btTransform& xf2)
const btBox2dShape* poly1, const btTransform& xf1,
const btBox2dShape* poly2, const btTransform& xf2)
{
int count1 = poly1->getVertexCount();
const btVector3* normals1 = poly1->getNormals();
@@ -169,8 +175,8 @@ static btScalar FindMaxSeparation(int* edgeIndex,
// Find edge normal on poly1 that has the largest projection onto d.
int edge = 0;
btScalar maxDot;
if (count1 > 0)
edge = (int)dLocal1.maxDot(normals1, count1, maxDot);
if( count1 > 0 )
edge = (int) dLocal1.maxDot( normals1, count1, maxDot);
// Get the separation for the edge normal.
btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
@@ -218,7 +224,7 @@ static btScalar FindMaxSeparation(int* edgeIndex,
}
// Perform a local search for the best edge normal.
for (;;)
for ( ; ; )
{
if (increment == -1)
edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;
@@ -279,14 +285,14 @@ static void FindIncidentEdge(ClipVertex c[2],
int i2 = i1 + 1 < count2 ? i1 + 1 : 0;
c[0].v = b2Mul(xf2, vertices2[i1]);
// c[0].id.features.referenceEdge = (unsigned char)edge1;
// c[0].id.features.incidentEdge = (unsigned char)i1;
// c[0].id.features.incidentVertex = 0;
// c[0].id.features.referenceEdge = (unsigned char)edge1;
// c[0].id.features.incidentEdge = (unsigned char)i1;
// c[0].id.features.incidentVertex = 0;
c[1].v = b2Mul(xf2, vertices2[i2]);
// c[1].id.features.referenceEdge = (unsigned char)edge1;
// c[1].id.features.incidentEdge = (unsigned char)i2;
// c[1].id.features.incidentVertex = 1;
// c[1].id.features.referenceEdge = (unsigned char)edge1;
// c[1].id.features.incidentEdge = (unsigned char)i2;
// c[1].id.features.incidentVertex = 1;
}
// Find edge normal of max separation on A - return if separating axis is found
@@ -297,9 +303,10 @@ static void FindIncidentEdge(ClipVertex c[2],
// The normal points from 1 to 2
void b2CollidePolygons(btManifoldResult* manifold,
const btBox2dShape* polyA, const btTransform& xfA,
const btBox2dShape* polyB, const btTransform& xfB)
const btBox2dShape* polyA, const btTransform& xfA,
const btBox2dShape* polyB, const btTransform& xfB)
{
int edgeA = 0;
btScalar separationA = FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB);
if (separationA > 0.0f)
@@ -310,10 +317,10 @@ void b2CollidePolygons(btManifoldResult* manifold,
if (separationB > 0.0f)
return;
const btBox2dShape* poly1; // reference poly
const btBox2dShape* poly2; // incident poly
const btBox2dShape* poly1; // reference poly
const btBox2dShape* poly2; // incident poly
btTransform xf1, xf2;
int edge1; // reference edge
int edge1; // reference edge
unsigned char flip;
const btScalar k_relativeTol = 0.98f;
const btScalar k_absoluteTol = 0.001f;
@@ -345,13 +352,14 @@ void b2CollidePolygons(btManifoldResult* manifold,
const btVector3* vertices1 = poly1->getVertices();
btVector3 v11 = vertices1[edge1];
btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1 + 1] : vertices1[0];
btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1+1] : vertices1[0];
//btVector3 dv = v12 - v11;
btVector3 sideNormal = b2Mul(xf1.getBasis(), v12 - v11);
sideNormal.normalize();
btVector3 frontNormal = btCrossS(sideNormal, 1.0f);
v11 = b2Mul(xf1, v11);
v12 = b2Mul(xf1, v12);
@@ -361,12 +369,13 @@ void b2CollidePolygons(btManifoldResult* manifold,
// Clip incident edge against extruded edge1 side edges.
ClipVertex clipPoints1[2];
clipPoints1[0].v.setValue(0, 0, 0);
clipPoints1[1].v.setValue(0, 0, 0);
clipPoints1[0].v.setValue(0,0,0);
clipPoints1[1].v.setValue(0,0,0);
ClipVertex clipPoints2[2];
clipPoints2[0].v.setValue(0, 0, 0);
clipPoints2[1].v.setValue(0, 0, 0);
clipPoints2[0].v.setValue(0,0,0);
clipPoints2[1].v.setValue(0,0,0);
int np;
@@ -377,7 +386,7 @@ void b2CollidePolygons(btManifoldResult* manifold,
return;
// Clip to negative box side 1
np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, sideOffset2);
np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, sideOffset2);
if (np < 2)
{
@@ -394,18 +403,19 @@ void b2CollidePolygons(btManifoldResult* manifold,
if (separation <= 0.0f)
{
//b2ManifoldPoint* cp = manifold->points + pointCount;
//btScalar separation = separation;
//cp->localPoint1 = b2MulT(xfA, clipPoints2[i].v);
//cp->localPoint2 = b2MulT(xfB, clipPoints2[i].v);
manifold->addContactPoint(-manifoldNormal, clipPoints2[i].v, separation);
manifold->addContactPoint(-manifoldNormal,clipPoints2[i].v,separation);
// cp->id = clipPoints2[i].id;
// cp->id.features.flip = flip;
// cp->id = clipPoints2[i].id;
// cp->id.features.flip = flip;
++pointCount;
}
}
// manifold->pointCount = pointCount;}
// manifold->pointCount = pointCount;}
}

View File

@@ -26,22 +26,22 @@ class btPersistentManifold;
///box-box collision detection
class btBox2dBox2dCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
public:
btBox2dBox2dCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btBox2dBox2dCollisionAlgorithm();
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
@@ -49,15 +49,18 @@ public:
}
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
int bbsize = sizeof(btBox2dBox2dCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
return new (ptr) btBox2dBox2dCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
return new(ptr) btBox2dBox2dCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
}
};
};
#endif //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
#endif //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H

View File

@@ -21,14 +21,14 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#define USE_PERSISTENT_CONTACTS 1
btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
: btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
{
if (!m_manifoldPtr && m_dispatcher->needsCollision(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject()))
if (!m_manifoldPtr && m_dispatcher->needsCollision(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()))
{
m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -42,27 +42,30 @@ btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
}
}
void btBoxBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btBoxBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
const btBoxShape* box0 = (btBoxShape*)body0Wrap->getCollisionShape();
const btBoxShape* box1 = (btBoxShape*)body1Wrap->getCollisionShape();
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
#ifndef USE_PERSISTENT_CONTACTS
#ifndef USE_PERSISTENT_CONTACTS
m_manifoldPtr->clearManifold();
#endif //USE_PERSISTENT_CONTACTS
#endif //USE_PERSISTENT_CONTACTS
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
input.m_transformA = body0Wrap->getWorldTransform();
input.m_transformB = body1Wrap->getWorldTransform();
btBoxBoxDetector detector(box0, box1);
detector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
btBoxBoxDetector detector(box0,box1);
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
#ifdef USE_PERSISTENT_CONTACTS
// refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
@@ -70,10 +73,11 @@ void btBoxBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrapper
{
resultOut->refreshContactPoints();
}
#endif //USE_PERSISTENT_CONTACTS
#endif //USE_PERSISTENT_CONTACTS
}
btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/, btCollisionObject* /*body1*/, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
{
//not yet
return 1.f;

View File

@@ -26,22 +26,22 @@ class btPersistentManifold;
///box-box collision detection
class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
public:
btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btBoxBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btBoxBoxCollisionAlgorithm();
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
@@ -49,15 +49,18 @@ public:
}
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
return new (ptr) btBoxBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
}
};
};
#endif //BT_BOX_BOX__COLLISION_ALGORITHM_H
#endif //BT_BOX_BOX__COLLISION_ALGORITHM_H

File diff suppressed because it is too large Load Diff

View File

@@ -19,9 +19,11 @@ subject to the following restrictions:
#ifndef BT_BOX_BOX_DETECTOR_H
#define BT_BOX_BOX_DETECTOR_H
class btBoxShape;
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
/// btBoxBoxDetector wraps the ODE box-box collision detector
/// re-distributed under the Zlib license with permission from Russell L. Smith
struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
@@ -30,11 +32,13 @@ struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
const btBoxShape* m_box2;
public:
btBoxBoxDetector(const btBoxShape* box1, const btBoxShape* box2);
virtual ~btBoxBoxDetector(){};
btBoxBoxDetector(const btBoxShape* box1,const btBoxShape* box2);
virtual ~btBoxBoxDetector() {};
virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
};
#endif //BT_BOX_BOX_DETECTOR_H
#endif //BT_BOX_BOX_DETECTOR_H

View File

@@ -23,9 +23,11 @@ class btPoolAllocator;
///btCollisionConfiguration allows to configure Bullet collision detection
///stack allocator size, default collision algorithms and persistent manifold pool size
///@todo: describe the meaning
class btCollisionConfiguration
class btCollisionConfiguration
{
public:
virtual ~btCollisionConfiguration()
{
}
@@ -35,9 +37,10 @@ public:
virtual btPoolAllocator* getCollisionAlgorithmPool() = 0;
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1) = 0;
virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1) = 0;
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0;
};
#endif //BT_COLLISION_CONFIGURATION
#endif //BT_COLLISION_CONFIGURATION

View File

@@ -26,18 +26,20 @@ struct btCollisionAlgorithmConstructionInfo;
struct btCollisionAlgorithmCreateFunc
{
bool m_swapped;
btCollisionAlgorithmCreateFunc()
: m_swapped(false)
:m_swapped(false)
{
}
virtual ~btCollisionAlgorithmCreateFunc(){};
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo&, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
(void)body0Wrap;
(void)body1Wrap;
return 0;
}
};
#endif //BT_COLLISION_CREATE_FUNC
#endif //BT_COLLISION_CREATE_FUNC

View File

@@ -13,8 +13,10 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btCollisionDispatcher.h"
#include "LinearMath/btQuickprof.h"
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
@@ -25,73 +27,82 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
int gNumManifold = 0;
#ifdef BT_DEBUG
#include <stdio.h>
#endif
btCollisionDispatcher::btCollisionDispatcher(btCollisionConfiguration* collisionConfiguration) : m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
m_collisionConfiguration(collisionConfiguration)
btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
m_collisionConfiguration(collisionConfiguration)
{
int i;
setNearCallback(defaultNearCallback);
m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
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_doubleDispatchContactPoints[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i, j);
btAssert(m_doubleDispatchContactPoints[i][j]);
m_doubleDispatchClosestPoints[i][j] = m_collisionConfiguration->getClosestPointsAlgorithmCreateFunc(i, j);
m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
btAssert(m_doubleDispatch[i][j]);
}
}
}
void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc)
{
m_doubleDispatchContactPoints[proxyType0][proxyType1] = createFunc;
}
void btCollisionDispatcher::registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc)
void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
{
m_doubleDispatchClosestPoints[proxyType0][proxyType1] = createFunc;
m_doubleDispatch[proxyType0][proxyType1] = createFunc;
}
btCollisionDispatcher::~btCollisionDispatcher()
{
}
btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1)
{
btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObject* body0,const btCollisionObject* body1)
{
gNumManifold++;
//btAssert(gNumManifold < 65535);
//optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ?
btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold) , body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
: gContactBreakingThreshold ;
btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold), body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
: gContactBreakingThreshold;
btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold());
void* mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
if (NULL == mem)
btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold());
void* mem = 0;
if (m_persistentManifoldPoolAllocator->getFreeCount())
{
mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
} else
{
//we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
if ((m_dispatcherFlags & CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION) == 0)
if ((m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION)==0)
{
mem = btAlignedAlloc(sizeof(btPersistentManifold), 16);
}
else
mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
} else
{
btAssert(0);
//make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
return 0;
}
}
btPersistentManifold* manifold = new (mem) btPersistentManifold(body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold);
btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold);
manifold->m_index1a = m_manifoldsPtr.size();
m_manifoldsPtr.push_back(manifold);
@@ -103,14 +114,18 @@ void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
manifold->clearManifold();
}
void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
{
gNumManifold--;
//printf("releaseManifold: gNumManifold %d\n",gNumManifold);
clearManifold(manifold);
int findIndex = manifold->m_index1a;
btAssert(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();
@@ -118,44 +133,42 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
if (m_persistentManifoldPoolAllocator->validPtr(manifold))
{
m_persistentManifoldPoolAllocator->freeMemory(manifold);
}
else
} else
{
btAlignedFree(manifold);
}
}
btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType algoType)
btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold)
{
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = this;
ci.m_manifold = sharedManifold;
btCollisionAlgorithm* algo = 0;
if (algoType == BT_CONTACT_POINT_ALGORITHMS)
{
algo = m_doubleDispatchContactPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap);
}
else
{
algo = m_doubleDispatchClosestPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap);
}
btCollisionAlgorithm* algo = m_doubleDispatch[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0Wrap,body1Wrap);
return algo;
}
bool btCollisionDispatcher::needsResponse(const btCollisionObject* body0, const btCollisionObject* body1)
bool btCollisionDispatcher::needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)
{
//here you can do filtering
bool hasResponse =
bool hasResponse =
(body0->hasContactResponse() && body1->hasContactResponse());
//no response between two static/kinematic bodies:
hasResponse = hasResponse &&
((!body0->isStaticOrKinematicObject()) || (!body1->isStaticOrKinematicObject()));
((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
return hasResponse;
}
bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0, const btCollisionObject* body1)
bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0,const btCollisionObject* body1)
{
btAssert(body0);
btAssert(body1);
@@ -172,27 +185,31 @@ bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0, const
printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
}
}
#endif //BT_DEBUG
#endif //BT_DEBUG
if ((!body0->isActive()) && (!body1->isActive()))
needsCollision = false;
else if ((!body0->checkCollideWith(body1)) || (!body1->checkCollideWith(body0)))
needsCollision = false;
return needsCollision ;
return needsCollision;
}
///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
///this is useful for the collision dispatcher.
class btCollisionPairCallback : public btOverlapCallback
{
const btDispatcherInfo& m_dispatchInfo;
btCollisionDispatcher* m_dispatcher;
btCollisionDispatcher* m_dispatcher;
public:
btCollisionPairCallback(const btDispatcherInfo& dispatchInfo, btCollisionDispatcher* dispatcher)
: m_dispatchInfo(dispatchInfo),
m_dispatcher(dispatcher)
btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
:m_dispatchInfo(dispatchInfo),
m_dispatcher(dispatcher)
{
}
@@ -204,76 +221,85 @@ public:
}
*/
virtual ~btCollisionPairCallback() {}
virtual bool processOverlap(btBroadphasePair& pair)
virtual bool processOverlap(btBroadphasePair& pair)
{
(*m_dispatcher->getNearCallback())(pair, *m_dispatcher, m_dispatchInfo);
(*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
return false;
}
};
void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher)
void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
{
//m_blockedForChanges = true;
btCollisionPairCallback collisionCallback(dispatchInfo, this);
btCollisionPairCallback collisionCallback(dispatchInfo,this);
{
BT_PROFILE("processAllOverlappingPairs");
pairCache->processAllOverlappingPairs(&collisionCallback, dispatcher, dispatchInfo);
}
pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
//m_blockedForChanges = false;
}
//by default, Bullet will use this near callback
void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
{
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
if (dispatcher.needsCollision(colObj0, colObj1))
{
btCollisionObjectWrapper obj0Wrap(0, colObj0->getCollisionShape(), colObj0, colObj0->getWorldTransform(), -1, -1);
btCollisionObjectWrapper obj1Wrap(0, colObj1->getCollisionShape(), colObj1, colObj1->getWorldTransform(), -1, -1);
//dispatcher will keep algorithms persistent in the collision pair
if (!collisionPair.m_algorithm)
if (dispatcher.needsCollision(colObj0,colObj1))
{
collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap, &obj1Wrap, 0, BT_CONTACT_POINT_ALGORITHMS);
}
btCollisionObjectWrapper obj0Wrap(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
btCollisionObjectWrapper obj1Wrap(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
if (collisionPair.m_algorithm)
{
btManifoldResult contactPointResult(&obj0Wrap, &obj1Wrap);
if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
//dispatcher will keep algorithms persistent in the collision pair
if (!collisionPair.m_algorithm)
{
//discrete collision detection query
collisionPair.m_algorithm->processCollision(&obj0Wrap, &obj1Wrap, dispatchInfo, &contactPointResult);
collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap,&obj1Wrap);
}
else
if (collisionPair.m_algorithm)
{
//continuous collision detection query, time of impact (toi)
btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0, colObj1, dispatchInfo, &contactPointResult);
if (dispatchInfo.m_timeOfImpact > toi)
dispatchInfo.m_timeOfImpact = toi;
btManifoldResult contactPointResult(&obj0Wrap,&obj1Wrap);
if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
{
//discrete collision detection query
collisionPair.m_algorithm->processCollision(&obj0Wrap,&obj1Wrap,dispatchInfo,&contactPointResult);
} else
{
//continuous collision detection query, time of impact (toi)
btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
if (dispatchInfo.m_timeOfImpact > toi)
dispatchInfo.m_timeOfImpact = toi;
}
}
}
}
}
void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
{
void* mem = m_collisionAlgorithmPoolAllocator->allocate(size);
if (NULL == mem)
if (m_collisionAlgorithmPoolAllocator->getFreeCount())
{
//warn user for overflow?
return btAlignedAlloc(static_cast<size_t>(size), 16);
return m_collisionAlgorithmPoolAllocator->allocate(size);
}
return mem;
//warn user for overflow?
return btAlignedAlloc(static_cast<size_t>(size), 16);
}
void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
@@ -281,8 +307,7 @@ void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
{
m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
}
else
} else
{
btAlignedFree(ptr);
}

View File

@@ -37,28 +37,33 @@ class btCollisionDispatcher;
///user can override this nearcallback for collision filtering and more finegrained control over collision detection
typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
///Time of Impact, Closest Points and Penetration Depth.
class btCollisionDispatcher : public btDispatcher
{
protected:
int m_dispatcherFlags;
btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
int m_dispatcherFlags;
btNearCallback m_nearCallback;
btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
btPoolAllocator* m_collisionAlgorithmPoolAllocator;
btManifoldResult m_defaultManifoldResult;
btPoolAllocator* m_persistentManifoldPoolAllocator;
btNearCallback m_nearCallback;
btPoolAllocator* m_collisionAlgorithmPoolAllocator;
btCollisionAlgorithmCreateFunc* m_doubleDispatchContactPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
btPoolAllocator* m_persistentManifoldPoolAllocator;
btCollisionAlgorithmCreateFunc* m_doubleDispatchClosestPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
btCollisionConfiguration* m_collisionConfiguration;
btCollisionConfiguration* m_collisionConfiguration;
public:
enum DispatcherFlags
{
CD_STATIC_STATIC_REPORTED = 1,
@@ -66,104 +71,101 @@ public:
CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION = 4
};
int getDispatcherFlags() const
int getDispatcherFlags() const
{
return m_dispatcherFlags;
}
void setDispatcherFlags(int flags)
void setDispatcherFlags(int flags)
{
m_dispatcherFlags = flags;
}
///registerCollisionCreateFunc allows registration of custom/alternative collision create functions
void registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
void registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
void registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
int getNumManifolds() const
{
return int(m_manifoldsPtr.size());
int getNumManifolds() const
{
return int( m_manifoldsPtr.size());
}
btPersistentManifold** getInternalManifoldPointer()
btPersistentManifold** getInternalManifoldPointer()
{
return m_manifoldsPtr.size() ? &m_manifoldsPtr[0] : 0;
return m_manifoldsPtr.size()? &m_manifoldsPtr[0] : 0;
}
btPersistentManifold* getManifoldByIndexInternal(int index)
btPersistentManifold* getManifoldByIndexInternal(int index)
{
btAssert(index>=0);
btAssert(index<m_manifoldsPtr.size());
return m_manifoldsPtr[index];
}
const btPersistentManifold* getManifoldByIndexInternal(int index) const
const btPersistentManifold* getManifoldByIndexInternal(int index) const
{
btAssert(index>=0);
btAssert(index<m_manifoldsPtr.size());
return m_manifoldsPtr[index];
}
btCollisionDispatcher(btCollisionConfiguration* collisionConfiguration);
btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration);
virtual ~btCollisionDispatcher();
virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0, const btCollisionObject* b1);
virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1);
virtual void releaseManifold(btPersistentManifold* manifold);
virtual void clearManifold(btPersistentManifold* manifold);
btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType);
btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold = 0);
virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1);
virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1);
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1);
virtual bool needsResponse(const btCollisionObject* body0, const btCollisionObject* body1);
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher);
void setNearCallback(btNearCallback nearCallback)
void setNearCallback(btNearCallback nearCallback)
{
m_nearCallback = nearCallback;
m_nearCallback = nearCallback;
}
btNearCallback getNearCallback() const
btNearCallback getNearCallback() const
{
return m_nearCallback;
}
//by default, Bullet will use this near callback
static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
virtual void* allocateCollisionAlgorithm(int size);
virtual void* allocateCollisionAlgorithm(int size);
virtual void freeCollisionAlgorithm(void* ptr);
virtual void freeCollisionAlgorithm(void* ptr);
btCollisionConfiguration* getCollisionConfiguration()
btCollisionConfiguration* getCollisionConfiguration()
{
return m_collisionConfiguration;
}
const btCollisionConfiguration* getCollisionConfiguration() const
const btCollisionConfiguration* getCollisionConfiguration() const
{
return m_collisionConfiguration;
}
void setCollisionConfiguration(btCollisionConfiguration* config)
void setCollisionConfiguration(btCollisionConfiguration* config)
{
m_collisionConfiguration = config;
}
virtual btPoolAllocator* getInternalManifoldPool()
virtual btPoolAllocator* getInternalManifoldPool()
{
return m_persistentManifoldPoolAllocator;
}
virtual const btPoolAllocator* getInternalManifoldPool() const
virtual const btPoolAllocator* getInternalManifoldPool() const
{
return m_persistentManifoldPoolAllocator;
}
};
#endif //BT_COLLISION__DISPATCHER_H
#endif //BT_COLLISION__DISPATCHER_H

View File

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

View File

@@ -1,38 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_COLLISION_DISPATCHER_MT_H
#define BT_COLLISION_DISPATCHER_MT_H
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "LinearMath/btThreads.h"
class btCollisionDispatcherMt : public btCollisionDispatcher
{
public:
btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize = 40);
virtual btPersistentManifold* getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1) BT_OVERRIDE;
virtual void releaseManifold(btPersistentManifold* manifold) BT_OVERRIDE;
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher) BT_OVERRIDE;
protected:
btAlignedObjectArray<btAlignedObjectArray<btPersistentManifold*> > m_batchManifoldsPtr;
bool m_batchUpdating;
int m_grainSize;
};
#endif //BT_COLLISION_DISPATCHER_MT_H

View File

@@ -13,45 +13,36 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btCollisionObject.h"
#include "LinearMath/btSerializer.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
btCollisionObject::btCollisionObject()
: m_interpolationLinearVelocity(0.f, 0.f, 0.f),
m_interpolationAngularVelocity(0.f, 0.f, 0.f),
m_anisotropicFriction(1.f, 1.f, 1.f),
m_hasAnisotropicFriction(false),
m_contactProcessingThreshold(BT_LARGE_FLOAT),
m_broadphaseHandle(0),
m_collisionShape(0),
m_extensionPointer(0),
m_rootCollisionShape(0),
m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
m_islandTag1(-1),
m_companionId(-1),
m_worldArrayIndex(-1),
m_activationState1(1),
m_deactivationTime(btScalar(0.)),
m_friction(btScalar(0.5)),
m_restitution(btScalar(0.)),
m_rollingFriction(0.0f),
m_spinningFriction(0.f),
m_contactDamping(.1),
m_contactStiffness(BT_LARGE_FLOAT),
m_internalType(CO_COLLISION_OBJECT),
m_userObjectPointer(0),
m_userIndex2(-1),
m_userIndex(-1),
m_userIndex3(-1),
m_hitFraction(btScalar(1.)),
m_ccdSweptSphereRadius(btScalar(0.)),
m_ccdMotionThreshold(btScalar(0.)),
m_checkCollideWith(false),
m_updateRevision(0)
: m_anisotropicFriction(1.f,1.f,1.f),
m_hasAnisotropicFriction(false),
m_contactProcessingThreshold(BT_LARGE_FLOAT),
m_broadphaseHandle(0),
m_collisionShape(0),
m_extensionPointer(0),
m_rootCollisionShape(0),
m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
m_islandTag1(-1),
m_companionId(-1),
m_activationState1(1),
m_deactivationTime(btScalar(0.)),
m_friction(btScalar(0.5)),
m_restitution(btScalar(0.)),
m_rollingFriction(0.0f),
m_internalType(CO_COLLISION_OBJECT),
m_userObjectPointer(0),
m_userIndex(-1),
m_hitFraction(btScalar(1.)),
m_ccdSweptSphereRadius(btScalar(0.)),
m_ccdMotionThreshold(btScalar(0.)),
m_checkCollideWith(false),
m_updateRevision(0)
{
m_worldTransform.setIdentity();
m_interpolationWorldTransform.setIdentity();
}
btCollisionObject::~btCollisionObject()
@@ -59,8 +50,8 @@ btCollisionObject::~btCollisionObject()
}
void btCollisionObject::setActivationState(int newState) const
{
if ((m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
{
if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
m_activationState1 = newState;
}
@@ -71,7 +62,7 @@ void btCollisionObject::forceActivationState(int newState) const
void btCollisionObject::activate(bool forceActivation) const
{
if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT)))
if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT)))
{
setActivationState(ACTIVE_TAG);
m_deactivationTime = btScalar(0.);
@@ -80,6 +71,7 @@ void btCollisionObject::activate(bool forceActivation) const
const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* serializer) const
{
btCollisionObjectData* dataOut = (btCollisionObjectData*)dataBuffer;
m_worldTransform.serialize(dataOut->m_worldTransform);
@@ -91,7 +83,7 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
dataOut->m_contactProcessingThreshold = m_contactProcessingThreshold;
dataOut->m_broadphaseHandle = 0;
dataOut->m_collisionShape = serializer->getUniquePointer(m_collisionShape);
dataOut->m_rootCollisionShape = 0; //@todo
dataOut->m_rootCollisionShape = 0;//@todo
dataOut->m_collisionFlags = m_collisionFlags;
dataOut->m_islandTag1 = m_islandTag1;
dataOut->m_companionId = m_companionId;
@@ -99,12 +91,10 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
dataOut->m_deactivationTime = m_deactivationTime;
dataOut->m_friction = m_friction;
dataOut->m_rollingFriction = m_rollingFriction;
dataOut->m_contactDamping = m_contactDamping;
dataOut->m_contactStiffness = m_contactStiffness;
dataOut->m_restitution = m_restitution;
dataOut->m_internalType = m_internalType;
char* name = (char*)serializer->findNameForPointer(this);
char* name = (char*) serializer->findNameForPointer(this);
dataOut->m_name = (char*)serializer->getUniquePointer(name);
if (dataOut->m_name)
{
@@ -114,25 +104,15 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
dataOut->m_ccdSweptSphereRadius = m_ccdSweptSphereRadius;
dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
dataOut->m_checkCollideWith = m_checkCollideWith;
if (m_broadphaseHandle)
{
dataOut->m_collisionFilterGroup = m_broadphaseHandle->m_collisionFilterGroup;
dataOut->m_collisionFilterMask = m_broadphaseHandle->m_collisionFilterMask;
dataOut->m_uniqueId = m_broadphaseHandle->m_uniqueId;
}
else
{
dataOut->m_collisionFilterGroup = 0;
dataOut->m_collisionFilterMask = 0;
dataOut->m_uniqueId = -1;
}
return btCollisionObjectDataName;
}
void btCollisionObject::serializeSingleObject(class btSerializer* serializer) const
{
int len = calculateSerializeBufferSize();
btChunk* chunk = serializer->allocate(len, 1);
btChunk* chunk = serializer->allocate(len,1);
const char* structType = serialize(chunk->m_oldPtr, serializer);
serializer->finalizeChunk(chunk, structType, BT_COLLISIONOBJECT_CODE, (void*)this);
serializer->finalizeChunk(chunk,structType,BT_COLLISIONOBJECT_CODE,(void*)this);
}

View File

@@ -25,8 +25,8 @@ subject to the following restrictions:
#define DISABLE_DEACTIVATION 4
#define DISABLE_SIMULATION 5
struct btBroadphaseProxy;
class btCollisionShape;
struct btBroadphaseProxy;
class btCollisionShape;
struct btCollisionShapeData;
#include "LinearMath/btMotionState.h"
#include "LinearMath/btAlignedAllocator.h"
@@ -42,120 +42,110 @@ typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
#define btCollisionObjectDataName "btCollisionObjectFloatData"
#endif
/// btCollisionObject can be used to manage collision detection objects.
/// btCollisionObject can be used to manage collision detection objects.
/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy.
/// They can be added to the btCollisionWorld.
ATTRIBUTE_ALIGNED16(class)
btCollisionObject
ATTRIBUTE_ALIGNED16(class) btCollisionObject
{
protected:
btTransform m_worldTransform;
btTransform m_worldTransform;
///m_interpolationWorldTransform is used for CCD and interpolation
///it can be either previous or future (predicted) transform
btTransform m_interpolationWorldTransform;
//those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities)
btTransform m_interpolationWorldTransform;
//those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities)
//without destroying the continuous interpolated motion (which uses this interpolation velocities)
btVector3 m_interpolationLinearVelocity;
btVector3 m_interpolationAngularVelocity;
btVector3 m_interpolationLinearVelocity;
btVector3 m_interpolationAngularVelocity;
btVector3 m_anisotropicFriction;
int m_hasAnisotropicFriction;
btScalar m_contactProcessingThreshold;
btVector3 m_anisotropicFriction;
int m_hasAnisotropicFriction;
btScalar m_contactProcessingThreshold;
btBroadphaseProxy* m_broadphaseHandle;
btCollisionShape* m_collisionShape;
btBroadphaseProxy* m_broadphaseHandle;
btCollisionShape* m_collisionShape;
///m_extensionPointer is used by some internal low-level Bullet extensions.
void* m_extensionPointer;
void* m_extensionPointer;
///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;
btCollisionShape* m_rootCollisionShape;
int m_collisionFlags;
int m_collisionFlags;
int m_islandTag1;
int m_companionId;
int m_worldArrayIndex; // index of object in world's collisionObjects array
int m_islandTag1;
int m_companionId;
mutable int m_activationState1;
mutable btScalar m_deactivationTime;
mutable int m_activationState1;
mutable btScalar m_deactivationTime;
btScalar m_friction;
btScalar m_restitution;
btScalar m_rollingFriction; //torsional friction orthogonal to contact normal (useful to stop spheres rolling forever)
btScalar m_spinningFriction; // torsional friction around the contact normal (useful for grasping)
btScalar m_contactDamping;
btScalar m_contactStiffness;
btScalar m_friction;
btScalar m_restitution;
btScalar m_rollingFriction;
///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc.
///do not assign your own m_internalType unless you write a new dynamics object class.
int m_internalType;
int m_internalType;
///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
void* m_userObjectPointer;
int m_userIndex2;
int m_userIndex;
int m_userIndex3;
void* m_userObjectPointer;
int m_userIndex;
///time of impact calculation
btScalar m_hitFraction;
btScalar m_hitFraction;
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
btScalar m_ccdSweptSphereRadius;
btScalar m_ccdSweptSphereRadius;
/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
btScalar m_ccdMotionThreshold;
btScalar m_ccdMotionThreshold;
/// If some object should have elaborate collision filtering by sub-classes
int m_checkCollideWith;
int m_checkCollideWith;
btAlignedObjectArray<const btCollisionObject*> m_objectsWithoutCollisionCheck;
///internal update revision number. It will be increased when the object changes. This allows some subsystems to perform lazy evaluation.
int m_updateRevision;
int m_updateRevision;
btVector3 m_customDebugColorRGB;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
enum CollisionFlags
{
CF_STATIC_OBJECT = 1,
CF_KINEMATIC_OBJECT = 2,
CF_STATIC_OBJECT= 1,
CF_KINEMATIC_OBJECT= 2,
CF_NO_CONTACT_RESPONSE = 4,
CF_CUSTOM_MATERIAL_CALLBACK = 8, //this allows per-triangle material (friction/restitution)
CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution)
CF_CHARACTER_OBJECT = 16,
CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing
CF_DISABLE_SPU_COLLISION_PROCESSING = 64, //disable parallel/SPU processing
CF_HAS_CONTACT_STIFFNESS_DAMPING = 128,
CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR = 256,
CF_HAS_FRICTION_ANCHOR = 512,
CF_HAS_COLLISION_SOUND_TRIGGER = 1024
CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing
CF_DISABLE_SPU_COLLISION_PROCESSING = 64//disable parallel/SPU processing
};
enum CollisionObjectTypes
enum CollisionObjectTypes
{
CO_COLLISION_OBJECT = 1,
CO_RIGID_BODY = 2,
CO_COLLISION_OBJECT =1,
CO_RIGID_BODY=2,
///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter
///It is useful for collision sensors, explosion objects, character controller etc.
CO_GHOST_OBJECT = 4,
CO_SOFT_BODY = 8,
CO_HF_FLUID = 16,
CO_USER_TYPE = 32,
CO_FEATHERSTONE_LINK = 64
CO_GHOST_OBJECT=4,
CO_SOFT_BODY=8,
CO_HF_FLUID=16,
CO_USER_TYPE=32,
CO_FEATHERSTONE_LINK=64
};
enum AnisotropicFrictionFlags
{
CF_ANISOTROPIC_FRICTION_DISABLED = 0,
CF_ANISOTROPIC_FRICTION_DISABLED=0,
CF_ANISOTROPIC_FRICTION = 1,
CF_ANISOTROPIC_ROLLING_FRICTION = 2
};
@@ -163,77 +153,76 @@ public:
SIMD_FORCE_INLINE bool mergesSimulationIslands() const
{
///static objects, kinematic and object without contact response don't merge islands
return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE)) == 0);
return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0);
}
const btVector3& getAnisotropicFriction() const
{
return m_anisotropicFriction;
}
void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION)
void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION)
{
m_anisotropicFriction = anisotropicFriction;
bool isUnity = (anisotropicFriction[0] != 1.f) || (anisotropicFriction[1] != 1.f) || (anisotropicFriction[2] != 1.f);
m_hasAnisotropicFriction = isUnity ? frictionMode : 0;
bool isUnity = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f);
m_hasAnisotropicFriction = isUnity?frictionMode : 0;
}
bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const
bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const
{
return (m_hasAnisotropicFriction & frictionMode) != 0;
return (m_hasAnisotropicFriction&frictionMode)!=0;
}
///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default.
///Note that using contacts with positive distance can improve stability. It increases, however, the chance of colliding with degerate contacts, such as 'interior' triangle edges
void setContactProcessingThreshold(btScalar contactProcessingThreshold)
void setContactProcessingThreshold( btScalar contactProcessingThreshold)
{
m_contactProcessingThreshold = contactProcessingThreshold;
}
btScalar getContactProcessingThreshold() const
btScalar getContactProcessingThreshold() const
{
return m_contactProcessingThreshold;
}
SIMD_FORCE_INLINE bool isStaticObject() const
{
SIMD_FORCE_INLINE bool isStaticObject() const {
return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
}
SIMD_FORCE_INLINE bool isKinematicObject() const
SIMD_FORCE_INLINE bool isKinematicObject() const
{
return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
}
SIMD_FORCE_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 ;
}
SIMD_FORCE_INLINE bool hasContactResponse() const
{
return (m_collisionFlags & CF_NO_CONTACT_RESPONSE) == 0;
SIMD_FORCE_INLINE bool hasContactResponse() const {
return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0;
}
btCollisionObject();
virtual ~btCollisionObject();
virtual void setCollisionShape(btCollisionShape * collisionShape)
virtual void setCollisionShape(btCollisionShape* collisionShape)
{
m_updateRevision++;
m_collisionShape = collisionShape;
m_rootCollisionShape = collisionShape;
}
SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
{
return m_collisionShape;
}
SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
{
return m_collisionShape;
}
void setIgnoreCollisionCheck(const btCollisionObject* co, bool ignoreCollisionCheck)
void setIgnoreCollisionCheck(const btCollisionObject* co, bool ignoreCollisionCheck)
{
if (ignoreCollisionCheck)
{
@@ -251,17 +240,7 @@ public:
m_checkCollideWith = m_objectsWithoutCollisionCheck.size() > 0;
}
int getNumObjectsWithoutCollision() const
{
return m_objectsWithoutCollisionCheck.size();
}
const btCollisionObject* getObjectWithoutCollision(int index)
{
return m_objectsWithoutCollisionCheck[index];
}
virtual bool checkCollideWithOverride(const btCollisionObject* co) const
virtual bool checkCollideWithOverride(const btCollisionObject* co) const
{
int index = m_objectsWithoutCollisionCheck.findLinearSearch(co);
if (index < m_objectsWithoutCollisionCheck.size())
@@ -271,325 +250,249 @@ public:
return true;
}
///Avoid using this internal API call, the extension pointer is used by some Bullet extensions.
///Avoid using this internal API call, the extension pointer is used by some Bullet extensions.
///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
void* internalGetExtensionPointer() const
void* internalGetExtensionPointer() const
{
return m_extensionPointer;
}
///Avoid using this internal API call, the extension pointer is used by some Bullet extensions
///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
void internalSetExtensionPointer(void* pointer)
void internalSetExtensionPointer(void* pointer)
{
m_extensionPointer = pointer;
}
SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1; }
SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1;}
void setActivationState(int newState) const;
void setDeactivationTime(btScalar time)
void setDeactivationTime(btScalar time)
{
m_deactivationTime = time;
}
btScalar getDeactivationTime() const
btScalar getDeactivationTime() const
{
return m_deactivationTime;
}
void forceActivationState(int newState) const;
void activate(bool forceActivation = false) const;
void activate(bool forceActivation = false) const;
SIMD_FORCE_INLINE bool isActive() const
{
return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION));
}
void setRestitution(btScalar rest)
void setRestitution(btScalar rest)
{
m_updateRevision++;
m_restitution = rest;
}
btScalar getRestitution() const
btScalar getRestitution() const
{
return m_restitution;
}
void setFriction(btScalar frict)
void setFriction(btScalar frict)
{
m_updateRevision++;
m_friction = frict;
}
btScalar getFriction() const
btScalar getFriction() const
{
return m_friction;
}
void setRollingFriction(btScalar frict)
void setRollingFriction(btScalar frict)
{
m_updateRevision++;
m_rollingFriction = frict;
}
btScalar getRollingFriction() const
btScalar getRollingFriction() const
{
return m_rollingFriction;
}
void setSpinningFriction(btScalar frict)
{
m_updateRevision++;
m_spinningFriction = frict;
}
btScalar getSpinningFriction() const
{
return m_spinningFriction;
}
void setContactStiffnessAndDamping(btScalar stiffness, btScalar damping)
{
m_updateRevision++;
m_contactStiffness = stiffness;
m_contactDamping = damping;
m_collisionFlags |= CF_HAS_CONTACT_STIFFNESS_DAMPING;
//avoid divisions by zero...
if (m_contactStiffness < SIMD_EPSILON)
{
m_contactStiffness = SIMD_EPSILON;
}
}
btScalar getContactStiffness() const
{
return m_contactStiffness;
}
btScalar getContactDamping() const
{
return m_contactDamping;
}
///reserved for Bullet internal usage
int getInternalType() const
int getInternalType() const
{
return m_internalType;
}
btTransform& getWorldTransform()
btTransform& getWorldTransform()
{
return m_worldTransform;
}
const btTransform& getWorldTransform() const
const btTransform& getWorldTransform() const
{
return m_worldTransform;
}
void setWorldTransform(const btTransform& worldTrans)
void setWorldTransform(const btTransform& worldTrans)
{
m_updateRevision++;
m_worldTransform = worldTrans;
}
SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle()
SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle()
{
return m_broadphaseHandle;
}
SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const
SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const
{
return m_broadphaseHandle;
}
void setBroadphaseHandle(btBroadphaseProxy * handle)
void setBroadphaseHandle(btBroadphaseProxy* handle)
{
m_broadphaseHandle = handle;
}
const btTransform& getInterpolationWorldTransform() const
const btTransform& getInterpolationWorldTransform() const
{
return m_interpolationWorldTransform;
}
btTransform& getInterpolationWorldTransform()
btTransform& getInterpolationWorldTransform()
{
return m_interpolationWorldTransform;
}
void setInterpolationWorldTransform(const btTransform& trans)
void setInterpolationWorldTransform(const btTransform& trans)
{
m_updateRevision++;
m_interpolationWorldTransform = trans;
}
void setInterpolationLinearVelocity(const btVector3& linvel)
void setInterpolationLinearVelocity(const btVector3& linvel)
{
m_updateRevision++;
m_interpolationLinearVelocity = linvel;
}
void setInterpolationAngularVelocity(const btVector3& angvel)
void setInterpolationAngularVelocity(const btVector3& angvel)
{
m_updateRevision++;
m_interpolationAngularVelocity = angvel;
}
const btVector3& getInterpolationLinearVelocity() const
const btVector3& getInterpolationLinearVelocity() const
{
return m_interpolationLinearVelocity;
}
const btVector3& getInterpolationAngularVelocity() const
const btVector3& getInterpolationAngularVelocity() const
{
return m_interpolationAngularVelocity;
}
SIMD_FORCE_INLINE int getIslandTag() const
{
return m_islandTag1;
return m_islandTag1;
}
void setIslandTag(int tag)
void setIslandTag(int tag)
{
m_islandTag1 = tag;
}
SIMD_FORCE_INLINE int getCompanionId() const
{
return m_companionId;
return m_companionId;
}
void setCompanionId(int id)
void setCompanionId(int id)
{
m_companionId = id;
}
SIMD_FORCE_INLINE int getWorldArrayIndex() const
SIMD_FORCE_INLINE btScalar getHitFraction() const
{
return m_worldArrayIndex;
return m_hitFraction;
}
// only should be called by CollisionWorld
void setWorldArrayIndex(int ix)
{
m_worldArrayIndex = ix;
}
SIMD_FORCE_INLINE btScalar getHitFraction() const
{
return m_hitFraction;
}
void setHitFraction(btScalar hitFraction)
void setHitFraction(btScalar hitFraction)
{
m_hitFraction = hitFraction;
}
SIMD_FORCE_INLINE int getCollisionFlags() const
SIMD_FORCE_INLINE int getCollisionFlags() const
{
return m_collisionFlags;
}
void setCollisionFlags(int flags)
void setCollisionFlags(int flags)
{
m_collisionFlags = flags;
}
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
btScalar getCcdSweptSphereRadius() const
btScalar getCcdSweptSphereRadius() const
{
return m_ccdSweptSphereRadius;
}
///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
void setCcdSweptSphereRadius(btScalar radius)
void setCcdSweptSphereRadius(btScalar radius)
{
m_ccdSweptSphereRadius = radius;
}
btScalar getCcdMotionThreshold() const
btScalar getCcdMotionThreshold() const
{
return m_ccdMotionThreshold;
}
btScalar getCcdSquareMotionThreshold() const
btScalar getCcdSquareMotionThreshold() const
{
return m_ccdMotionThreshold * m_ccdMotionThreshold;
return m_ccdMotionThreshold*m_ccdMotionThreshold;
}
/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
void setCcdMotionThreshold(btScalar ccdMotionThreshold)
void setCcdMotionThreshold(btScalar ccdMotionThreshold)
{
m_ccdMotionThreshold = ccdMotionThreshold;
}
///users can point to their objects, userPointer is not used by Bullet
void* getUserPointer() const
void* getUserPointer() const
{
return m_userObjectPointer;
}
int getUserIndex() const
int getUserIndex() const
{
return m_userIndex;
}
int getUserIndex2() const
{
return m_userIndex2;
}
int getUserIndex3() const
{
return m_userIndex3;
}
///users can point to their objects, userPointer is not used by Bullet
void setUserPointer(void* userPointer)
void setUserPointer(void* userPointer)
{
m_userObjectPointer = userPointer;
}
///users can point to their objects, userPointer is not used by Bullet
void setUserIndex(int index)
void setUserIndex(int index)
{
m_userIndex = index;
}
void setUserIndex2(int index)
{
m_userIndex2 = index;
}
void setUserIndex3(int index)
{
m_userIndex3 = index;
}
int getUpdateRevisionInternal() const
int getUpdateRevisionInternal() const
{
return m_updateRevision;
}
void setCustomDebugColor(const btVector3& colorRGB)
{
m_customDebugColorRGB = colorRGB;
m_collisionFlags |= CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
}
void removeCustomDebugColor()
{
m_collisionFlags &= ~CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
}
bool getCustomDebugColor(btVector3 & colorRGB) const
{
bool hasCustomColor = (0 != (m_collisionFlags & CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR));
if (hasCustomColor)
{
colorRGB = m_customDebugColorRGB;
}
return hasCustomColor;
}
inline bool checkCollideWith(const btCollisionObject* co) const
{
@@ -599,16 +502,15 @@ public:
return true;
}
virtual int calculateSerializeBufferSize() const;
virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
virtual void serializeSingleObject(class btSerializer* serializer) const;
virtual void serializeSingleObject(class btSerializer * serializer) const;
};
// clang-format off
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
struct btCollisionObjectDoubleData
{
@@ -626,12 +528,11 @@ struct btCollisionObjectDoubleData
double m_deactivationTime;
double m_friction;
double m_rollingFriction;
double m_contactDamping;
double m_contactStiffness;
double m_restitution;
double m_hitFraction;
double m_ccdSweptSphereRadius;
double m_ccdMotionThreshold;
int m_hasAnisotropicFriction;
int m_collisionFlags;
int m_islandTag1;
@@ -639,9 +540,8 @@ struct btCollisionObjectDoubleData
int m_activationState1;
int m_internalType;
int m_checkCollideWith;
int m_collisionFilterGroup;
int m_collisionFilterMask;
int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
char m_padding[4];
};
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
@@ -661,12 +561,12 @@ struct btCollisionObjectFloatData
float m_deactivationTime;
float m_friction;
float m_rollingFriction;
float m_contactDamping;
float m_contactStiffness;
float m_restitution;
float m_hitFraction;
float m_ccdSweptSphereRadius;
float m_ccdMotionThreshold;
int m_hasAnisotropicFriction;
int m_collisionFlags;
int m_islandTag1;
@@ -674,15 +574,16 @@ struct btCollisionObjectFloatData
int m_activationState1;
int m_internalType;
int m_checkCollideWith;
int m_collisionFilterGroup;
int m_collisionFilterMask;
int m_uniqueId;
char m_padding[4];
};
// clang-format on
SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const
SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const
{
return sizeof(btCollisionObjectData);
}
#endif //BT_COLLISION_OBJECT_H
#endif //BT_COLLISION_OBJECT_H

View File

@@ -1,25 +1,25 @@
#ifndef BT_COLLISION_OBJECT_WRAPPER_H
#define BT_COLLISION_OBJECT_WRAPPER_H
///btCollisionObjectWrapperis an internal data structure.
///btCollisionObjectWrapperis an internal data structure.
///Most users can ignore this and use btCollisionObject and btCollisionShape instead
class btCollisionShape;
class btCollisionObject;
class btTransform;
#include "LinearMath/btScalar.h" // for SIMD_FORCE_INLINE definition
#include "LinearMath/btScalar.h" // for SIMD_FORCE_INLINE definition
#define BT_DECLARE_STACK_ONLY_OBJECT \
private: \
void* operator new(size_t size); \
void operator delete(void*);
private: \
void* operator new(size_t size); \
void operator delete(void*);
struct btCollisionObjectWrapper;
struct btCollisionObjectWrapper
{
BT_DECLARE_STACK_ONLY_OBJECT
BT_DECLARE_STACK_ONLY_OBJECT
private:
btCollisionObjectWrapper(const btCollisionObjectWrapper&); // not implemented. Not allowed.
btCollisionObjectWrapper(const btCollisionObjectWrapper&); // not implemented. Not allowed.
btCollisionObjectWrapper* operator=(const btCollisionObjectWrapper&);
public:
@@ -27,23 +27,17 @@ public:
const btCollisionShape* m_shape;
const btCollisionObject* m_collisionObject;
const btTransform& m_worldTransform;
const btTransform* m_preTransform;
int m_partId;
int m_index;
int m_partId;
int m_index;
btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, int partId, int index)
: m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_preTransform(NULL), m_partId(partId), m_index(index)
{
}
btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, const btTransform& preTransform, int partId, int index)
: m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_preTransform(&preTransform), m_partId(partId), m_index(index)
{
}
: m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform),
m_partId(partId), m_index(index)
{}
SIMD_FORCE_INLINE const btTransform& getWorldTransform() const { return m_worldTransform; }
SIMD_FORCE_INLINE const btCollisionObject* getCollisionObject() const { return m_collisionObject; }
SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_shape; }
};
#endif //BT_COLLISION_OBJECT_WRAPPER_H
#endif //BT_COLLISION_OBJECT_WRAPPER_H

File diff suppressed because it is too large Load Diff

View File

@@ -13,8 +13,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
/**
* @mainpage Bullet Documentation
* @page Bullet Documentation
*
* @section intro_sec Introduction
* Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ).
@@ -65,6 +66,8 @@ subject to the following restrictions:
* For up-to-data information and copyright and contributors list check out the Bullet_User_Manual.pdf
*
*/
#ifndef BT_COLLISION_WORLD_H
#define BT_COLLISION_WORLD_H
@@ -84,138 +87,144 @@ class btSerializer;
///CollisionWorld is interface and container for the collision detection
class btCollisionWorld
{
protected:
btAlignedObjectArray<btCollisionObject*> m_collisionObjects;
btDispatcher* m_dispatcher1;
btAlignedObjectArray<btCollisionObject*> m_collisionObjects;
btDispatcher* m_dispatcher1;
btDispatcherInfo m_dispatchInfo;
btDispatcherInfo m_dispatchInfo;
btBroadphaseInterface* m_broadphasePairCache;
btBroadphaseInterface* m_broadphasePairCache;
btIDebugDraw* m_debugDrawer;
btIDebugDraw* m_debugDrawer;
///m_forceUpdateAllAabbs can be set to false as an optimization to only update active object AABBs
///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB)
bool m_forceUpdateAllAabbs;
void serializeCollisionObjects(btSerializer* serializer);
void serializeContactManifolds(btSerializer* serializer);
void serializeCollisionObjects(btSerializer* serializer);
public:
//this constructor doesn't own the dispatcher and paircache/broadphase
btCollisionWorld(btDispatcher* dispatcher, btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
virtual ~btCollisionWorld();
void setBroadphase(btBroadphaseInterface* pairCache)
void setBroadphase(btBroadphaseInterface* pairCache)
{
m_broadphasePairCache = pairCache;
}
const btBroadphaseInterface* getBroadphase() const
const btBroadphaseInterface* getBroadphase() const
{
return m_broadphasePairCache;
}
btBroadphaseInterface* getBroadphase()
btBroadphaseInterface* getBroadphase()
{
return m_broadphasePairCache;
}
btOverlappingPairCache* getPairCache()
btOverlappingPairCache* getPairCache()
{
return m_broadphasePairCache->getOverlappingPairCache();
}
btDispatcher* getDispatcher()
btDispatcher* getDispatcher()
{
return m_dispatcher1;
}
const btDispatcher* getDispatcher() const
const btDispatcher* getDispatcher() const
{
return m_dispatcher1;
}
void updateSingleAabb(btCollisionObject* colObj);
void updateSingleAabb(btCollisionObject* colObj);
virtual void updateAabbs();
virtual void updateAabbs();
///the computeOverlappingPairs is usually already called by performDiscreteCollisionDetection (or stepSimulation)
///it can be useful to use if you perform ray tests without collision detection/simulation
virtual void computeOverlappingPairs();
virtual void computeOverlappingPairs();
virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
{
m_debugDrawer = debugDrawer;
m_debugDrawer = debugDrawer;
}
virtual btIDebugDraw* getDebugDrawer()
virtual btIDebugDraw* getDebugDrawer()
{
return m_debugDrawer;
}
virtual void debugDrawWorld();
virtual void debugDrawWorld();
virtual void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
///LocalShapeInfo gives extra information for complex shapes
///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
struct LocalShapeInfo
struct LocalShapeInfo
{
int m_shapePart;
int m_triangleIndex;
int m_shapePart;
int m_triangleIndex;
//const btCollisionShape* m_shapeTemp;
//const btTransform* m_shapeLocalTransform;
};
struct LocalRayResult
struct LocalRayResult
{
LocalRayResult(const btCollisionObject* collisionObject,
LocalShapeInfo* localShapeInfo,
const btVector3& hitNormalLocal,
btScalar hitFraction)
: m_collisionObject(collisionObject),
m_localShapeInfo(localShapeInfo),
m_hitNormalLocal(hitNormalLocal),
m_hitFraction(hitFraction)
LocalRayResult(const btCollisionObject* collisionObject,
LocalShapeInfo* localShapeInfo,
const btVector3& hitNormalLocal,
btScalar hitFraction)
:m_collisionObject(collisionObject),
m_localShapeInfo(localShapeInfo),
m_hitNormalLocal(hitNormalLocal),
m_hitFraction(hitFraction)
{
}
const btCollisionObject* m_collisionObject;
LocalShapeInfo* m_localShapeInfo;
btVector3 m_hitNormalLocal;
btScalar m_hitFraction;
const btCollisionObject* m_collisionObject;
LocalShapeInfo* m_localShapeInfo;
btVector3 m_hitNormalLocal;
btScalar m_hitFraction;
};
///RayResultCallback is used to report new raycast results
struct RayResultCallback
struct RayResultCallback
{
btScalar m_closestHitFraction;
const btCollisionObject* m_collisionObject;
int m_collisionFilterGroup;
int m_collisionFilterMask;
btScalar m_closestHitFraction;
const btCollisionObject* m_collisionObject;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
//@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback.h. Apply any of the EFlags defined there on m_flags here to invoke.
unsigned int m_flags;
virtual ~RayResultCallback()
{
}
bool hasHit() const
bool hasHit() const
{
return (m_collisionObject != 0);
}
RayResultCallback()
: m_closestHitFraction(btScalar(1.)),
m_collisionObject(0),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter),
//@BP Mod
m_flags(0)
:m_closestHitFraction(btScalar(1.)),
m_collisionObject(0),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter),
//@BP Mod
m_flags(0)
{
}
@@ -226,62 +235,62 @@ public:
return collides;
}
virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace) = 0;
virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0;
};
struct ClosestRayResultCallback : public RayResultCallback
struct ClosestRayResultCallback : public RayResultCallback
{
ClosestRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
: m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld)
ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
:m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld)
{
}
btVector3 m_rayFromWorld; //used to calculate hitPointWorld from hitFraction
btVector3 m_rayToWorld;
btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
btVector3 m_rayToWorld;
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace)
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
{
//caller already does the filter on the m_closestHitFraction
btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
m_closestHitFraction = rayResult.m_hitFraction;
m_collisionObject = rayResult.m_collisionObject;
if (normalInWorldSpace)
{
m_hitNormalWorld = rayResult.m_hitNormalLocal;
}
else
} 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;
}
};
struct AllHitsRayResultCallback : public RayResultCallback
struct AllHitsRayResultCallback : public RayResultCallback
{
AllHitsRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
: m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld)
AllHitsRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld)
:m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld)
{
}
btAlignedObjectArray<const btCollisionObject*> m_collisionObjects;
btAlignedObjectArray<const btCollisionObject*> m_collisionObjects;
btVector3 m_rayFromWorld; //used to calculate hitPointWorld from hitFraction
btVector3 m_rayToWorld;
btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
btVector3 m_rayToWorld;
btAlignedObjectArray<btVector3> m_hitNormalWorld;
btAlignedObjectArray<btVector3> m_hitPointWorld;
btAlignedObjectArray<btVector3> m_hitNormalWorld;
btAlignedObjectArray<btVector3> m_hitPointWorld;
btAlignedObjectArray<btScalar> m_hitFractions;
virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace)
virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
{
m_collisionObject = rayResult.m_collisionObject;
m_collisionObjects.push_back(rayResult.m_collisionObject);
@@ -289,66 +298,69 @@ public:
if (normalInWorldSpace)
{
hitNormalWorld = rayResult.m_hitNormalLocal;
}
else
} else
{
///need to transform normal into worldspace
hitNormalWorld = m_collisionObject->getWorldTransform().getBasis() * rayResult.m_hitNormalLocal;
hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
}
m_hitNormalWorld.push_back(hitNormalWorld);
btVector3 hitPointWorld;
hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, rayResult.m_hitFraction);
hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
m_hitPointWorld.push_back(hitPointWorld);
m_hitFractions.push_back(rayResult.m_hitFraction);
return m_closestHitFraction;
}
};
struct LocalConvexResult
{
LocalConvexResult(const 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)
LocalConvexResult(const 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)
{
}
const btCollisionObject* m_hitCollisionObject;
LocalShapeInfo* m_localShapeInfo;
btVector3 m_hitNormalLocal;
btVector3 m_hitPointLocal;
btScalar m_hitFraction;
const 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
struct ConvexResultCallback
{
btScalar m_closestHitFraction;
int m_collisionFilterGroup;
int m_collisionFilterMask;
btScalar m_closestHitFraction;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
ConvexResultCallback()
: m_closestHitFraction(btScalar(1.)),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter)
:m_closestHitFraction(btScalar(1.)),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter)
{
}
virtual ~ConvexResultCallback()
{
}
bool hasHit() const
bool hasHit() const
{
return (m_closestHitFraction < btScalar(1.));
}
virtual bool needsCollision(btBroadphaseProxy* proxy0) const
{
bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
@@ -356,40 +368,39 @@ public:
return collides;
}
virtual btScalar addSingleResult(LocalConvexResult& convexResult, bool normalInWorldSpace) = 0;
virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0;
};
struct ClosestConvexResultCallback : public ConvexResultCallback
struct ClosestConvexResultCallback : public ConvexResultCallback
{
ClosestConvexResultCallback(const btVector3& convexFromWorld, const btVector3& convexToWorld)
: m_convexFromWorld(convexFromWorld),
m_convexToWorld(convexToWorld),
m_hitCollisionObject(0)
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_convexFromWorld;//used to calculate hitPointWorld from hitFraction
btVector3 m_convexToWorld;
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
const btCollisionObject* m_hitCollisionObject;
virtual btScalar addSingleResult(LocalConvexResult& convexResult, bool normalInWorldSpace)
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
const btCollisionObject* m_hitCollisionObject;
virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace)
{
//caller already does the filter on the m_closestHitFraction
//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
} else
{
///need to transform normal into worldspace
m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal;
m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
}
m_hitPointWorld = convexResult.m_hitPointLocal;
return convexResult.m_hitFraction;
@@ -397,23 +408,21 @@ public:
};
///ContactResultCallback is used to report contact points
struct ContactResultCallback
struct ContactResultCallback
{
int m_collisionFilterGroup;
int m_collisionFilterMask;
btScalar m_closestDistanceThreshold;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
ContactResultCallback()
: m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter),
m_closestDistanceThreshold(0)
:m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter)
{
}
virtual ~ContactResultCallback()
{
}
virtual bool needsCollision(btBroadphaseProxy* proxy0) const
{
bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
@@ -421,57 +430,58 @@ public:
return collides;
}
virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1) = 0;
virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) = 0;
};
int getNumCollisionObjects() const
int getNumCollisionObjects() const
{
return int(m_collisionObjects.size());
}
/// 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.
virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
virtual 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, btScalar allowedCcdPenetration = btScalar(0.)) const;
void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = btScalar(0.)) const;
///contactTest performs a discrete collision test between colObj against all objects in the btCollisionWorld, and calls the resultCallback.
///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
void contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback);
void contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback);
///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
///it reports one or more contact points (including the one with deepest penetration)
void contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback);
void contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback);
/// 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.
/// This allows more customization.
static void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback);
static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback);
static void rayTestSingleInternal(const btTransform& rayFromTrans, const btTransform& rayToTrans,
const btCollisionObjectWrapper* collisionObjectWrap,
RayResultCallback& resultCallback);
static void rayTestSingleInternal(const btTransform& rayFromTrans,const btTransform& rayToTrans,
const btCollisionObjectWrapper* collisionObjectWrap,
RayResultCallback& resultCallback);
/// 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,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
ConvexResultCallback& resultCallback, btScalar allowedPenetration);
static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
ConvexResultCallback& resultCallback, btScalar allowedPenetration);
static void objectQuerySingleInternal(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
const btCollisionObjectWrapper* colObjWrap,
ConvexResultCallback& resultCallback, btScalar allowedPenetration);
static void objectQuerySingleInternal(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
const btCollisionObjectWrapper* colObjWrap,
ConvexResultCallback& resultCallback, btScalar allowedPenetration);
virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
virtual void refreshBroadphaseProxy(btCollisionObject* collisionObject);
virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter);
btCollisionObjectArray& getCollisionObjectArray()
{
@@ -483,9 +493,10 @@ public:
return m_collisionObjects;
}
virtual void removeCollisionObject(btCollisionObject* collisionObject);
virtual void performDiscreteCollisionDetection();
virtual void removeCollisionObject(btCollisionObject* collisionObject);
virtual void performDiscreteCollisionDetection();
btDispatcherInfo& getDispatchInfo()
{
@@ -496,18 +507,20 @@ public:
{
return m_dispatchInfo;
}
bool getForceUpdateAllAabbs() const
bool getForceUpdateAllAabbs() const
{
return m_forceUpdateAllAabbs;
}
void setForceUpdateAllAabbs(bool forceUpdateAllAabbs)
void setForceUpdateAllAabbs( bool forceUpdateAllAabbs)
{
m_forceUpdateAllAabbs = forceUpdateAllAabbs;
}
///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (Bullet/Demos/SerializeDemo)
virtual void serialize(btSerializer* serializer);
virtual void serialize(btSerializer* serializer);
};
#endif //BT_COLLISION_WORLD_H
#endif //BT_COLLISION_WORLD_H

View File

@@ -13,6 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_COLLISION_WORLD_IMPORTER_H
#define BT_COLLISION_WORLD_IMPORTER_H
@@ -25,6 +26,7 @@ class btCollisionShape;
class btCollisionObject;
struct btBulletSerializedArrays;
struct ConstraintInput;
class btCollisionWorld;
struct btCollisionShapeData;
@@ -44,6 +46,9 @@ class btSliderConstraint;
class btGearConstraint;
struct btContactSolverInfo;
class btCollisionWorldImporter
{
protected:
@@ -51,53 +56,60 @@ protected:
int m_verboseMode;
btAlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes;
btAlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes;
btAlignedObjectArray<btCollisionObject*> m_allocatedRigidBodies;
btAlignedObjectArray<btOptimizedBvh*> m_allocatedBvhs;
btAlignedObjectArray<btOptimizedBvh*> m_allocatedBvhs;
btAlignedObjectArray<btTriangleInfoMap*> m_allocatedTriangleInfoMaps;
btAlignedObjectArray<btTriangleIndexVertexArray*> m_allocatedTriangleIndexArrays;
btAlignedObjectArray<btStridingMeshInterfaceData*> m_allocatedbtStridingMeshInterfaceDatas;
btAlignedObjectArray<btCollisionObject*> m_allocatedCollisionObjects;
btAlignedObjectArray<char*> m_allocatedNames;
btAlignedObjectArray<int*> m_indexArrays;
btAlignedObjectArray<short int*> m_shortIndexArrays;
btAlignedObjectArray<unsigned char*> m_charIndexArrays;
btAlignedObjectArray<char*> m_allocatedNames;
btAlignedObjectArray<btVector3FloatData*> m_floatVertexArrays;
btAlignedObjectArray<btVector3DoubleData*> m_doubleVertexArrays;
btAlignedObjectArray<int*> m_indexArrays;
btAlignedObjectArray<short int*> m_shortIndexArrays;
btAlignedObjectArray<unsigned char*> m_charIndexArrays;
btHashMap<btHashPtr, btOptimizedBvh*> m_bvhMap;
btHashMap<btHashPtr, btTriangleInfoMap*> m_timMap;
btAlignedObjectArray<btVector3FloatData*> m_floatVertexArrays;
btAlignedObjectArray<btVector3DoubleData*> m_doubleVertexArrays;
btHashMap<btHashString, btCollisionShape*> m_nameShapeMap;
btHashMap<btHashString, btCollisionObject*> m_nameColObjMap;
btHashMap<btHashPtr, const char*> m_objectNameMap;
btHashMap<btHashPtr,btOptimizedBvh*> m_bvhMap;
btHashMap<btHashPtr,btTriangleInfoMap*> m_timMap;
btHashMap<btHashString,btCollisionShape*> m_nameShapeMap;
btHashMap<btHashString,btCollisionObject*> m_nameColObjMap;
btHashMap<btHashPtr,const char*> m_objectNameMap;
btHashMap<btHashPtr,btCollisionShape*> m_shapeMap;
btHashMap<btHashPtr,btCollisionObject*> m_bodyMap;
btHashMap<btHashPtr, btCollisionShape*> m_shapeMap;
btHashMap<btHashPtr, btCollisionObject*> m_bodyMap;
//methods
char* duplicateName(const char* name);
btCollisionShape* convertCollisionShape(btCollisionShapeData* shapeData);
char* duplicateName(const char* name);
btCollisionShape* convertCollisionShape( btCollisionShapeData* shapeData );
public:
btCollisionWorldImporter(btCollisionWorld* world);
virtual ~btCollisionWorldImporter();
bool convertAllObjects(btBulletSerializedArrays* arrays);
bool convertAllObjects( btBulletSerializedArrays* arrays);
///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load.
///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load.
///make sure you don't use the dynamics world containing objects after you call this method
virtual void deleteAllData();
void setVerboseMode(int verboseMode)
void setVerboseMode(int verboseMode)
{
m_verboseMode = verboseMode;
}
@@ -107,14 +119,15 @@ public:
return m_verboseMode;
}
// query for data
int getNumCollisionShapes() const;
// query for data
int getNumCollisionShapes() const;
btCollisionShape* getCollisionShapeByIndex(int index);
int getNumRigidBodies() const;
btCollisionObject* getRigidBodyByIndex(int index) const;
int getNumConstraints() const;
int getNumBvhs() const;
btOptimizedBvh* getBvhByIndex(int index) const;
btOptimizedBvh* getBvhByIndex(int index) const;
int getNumTriangleInfoMaps() const;
btTriangleInfoMap* getTriangleInfoMapByIndex(int index) const;
@@ -122,48 +135,56 @@ public:
btCollisionShape* getCollisionShapeByName(const char* name);
btCollisionObject* getCollisionObjectByName(const char* name);
const char* getNameForPointer(const void* ptr) const;
const char* getNameForPointer(const void* ptr) const;
///those virtuals are called by load and can be overridden by the user
//bodies
virtual btCollisionObject* createCollisionObject(const btTransform& startTransform, btCollisionShape* shape, const char* bodyName);
virtual btCollisionObject* createCollisionObject( const btTransform& startTransform, btCollisionShape* shape,const char* bodyName);
///shapes
virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal, btScalar planeConstant);
virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal,btScalar planeConstant);
virtual btCollisionShape* createBoxShape(const btVector3& halfExtents);
virtual btCollisionShape* createSphereShape(btScalar radius);
virtual btCollisionShape* createCapsuleShapeX(btScalar radius, btScalar height);
virtual btCollisionShape* createCapsuleShapeY(btScalar radius, btScalar height);
virtual btCollisionShape* createCapsuleShapeZ(btScalar radius, btScalar height);
virtual btCollisionShape* createCylinderShapeX(btScalar radius, btScalar height);
virtual btCollisionShape* createCylinderShapeY(btScalar radius, btScalar height);
virtual btCollisionShape* createCylinderShapeZ(btScalar radius, btScalar height);
virtual btCollisionShape* createConeShapeX(btScalar radius, btScalar height);
virtual btCollisionShape* createConeShapeY(btScalar radius, btScalar height);
virtual btCollisionShape* createConeShapeZ(btScalar radius, btScalar height);
virtual class btTriangleIndexVertexArray* createTriangleMeshContainer();
virtual btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh);
virtual btCollisionShape* createCylinderShapeX(btScalar radius,btScalar height);
virtual btCollisionShape* createCylinderShapeY(btScalar radius,btScalar height);
virtual btCollisionShape* createCylinderShapeZ(btScalar radius,btScalar height);
virtual btCollisionShape* createConeShapeX(btScalar radius,btScalar height);
virtual btCollisionShape* createConeShapeY(btScalar radius,btScalar height);
virtual btCollisionShape* createConeShapeZ(btScalar radius,btScalar height);
virtual class btTriangleIndexVertexArray* createTriangleMeshContainer();
virtual btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh);
virtual btCollisionShape* createConvexTriangleMeshShape(btStridingMeshInterface* trimesh);
#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
virtual btGImpactMeshShape* createGimpactShape(btStridingMeshInterface* trimesh);
#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
virtual btStridingMeshInterfaceData* createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData);
virtual class btConvexHullShape* createConvexHullShape();
virtual class btCompoundShape* createCompoundShape();
virtual class btScaledBvhTriangleMeshShape* createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape, const btVector3& localScalingbtBvhTriangleMeshShape);
virtual class btScaledBvhTriangleMeshShape* createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape,const btVector3& localScalingbtBvhTriangleMeshShape);
virtual class btMultiSphereShape* createMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres);
virtual class btMultiSphereShape* createMultiSphereShape(const btVector3* positions,const btScalar* radi,int numSpheres);
virtual btTriangleIndexVertexArray* createMeshInterface(btStridingMeshInterfaceData& meshData);
///acceleration and connectivity structures
virtual btOptimizedBvh* createOptimizedBvh();
virtual btOptimizedBvh* createOptimizedBvh();
virtual btTriangleInfoMap* createTriangleInfoMap();
};
#endif //BT_WORLD_IMPORTER_H
#endif //BT_WORLD_IMPORTER_H

View File

@@ -25,58 +25,56 @@ subject to the following restrictions:
btShapePairCallback gCompoundChildShapePairCallback = 0;
btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
: btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
m_isSwapped(isSwapped),
m_sharedManifold(ci.m_manifold)
btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
:btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_isSwapped(isSwapped),
m_sharedManifold(ci.m_manifold)
{
m_ownsManifold = false;
const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
btAssert(colObjWrap->getCollisionShape()->isCompound());
const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
btAssert (colObjWrap->getCollisionShape()->isCompound());
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
m_compoundShapeRevision = compoundShape->getUpdateRevision();
preallocateChildAlgorithms(body0Wrap, body1Wrap);
preallocateChildAlgorithms(body0Wrap,body1Wrap);
}
void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* otherObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
btAssert(colObjWrap->getCollisionShape()->isCompound());
const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
btAssert (colObjWrap->getCollisionShape()->isCompound());
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
int numChildren = compoundShape->getNumChildShapes();
int i;
m_childCollisionAlgorithms.resize(numChildren);
for (i = 0; i < numChildren; i++)
for (i=0;i<numChildren;i++)
{
if (compoundShape->getDynamicAabbTree())
{
m_childCollisionAlgorithms[i] = 0;
}
else
} else
{
const btCollisionShape* childShape = compoundShape->getChildShape(i);
btCollisionObjectWrapper childWrap(colObjWrap, childShape, colObjWrap->getCollisionObject(), colObjWrap->getWorldTransform(), -1, i); //wrong child trans, but unused (hopefully)
m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap, otherObjWrap, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsContact;
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsClosestPoints;
btCollisionObjectWrapper childWrap(colObjWrap,childShape,colObjWrap->getCollisionObject(),colObjWrap->getWorldTransform(),-1,i);//wrong child trans, but unused (hopefully)
m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap,otherObjWrap,m_sharedManifold);
}
}
}
void btCompoundCollisionAlgorithm::removeChildAlgorithms()
void btCompoundCollisionAlgorithm::removeChildAlgorithms()
{
int numChildren = m_childCollisionAlgorithms.size();
int i;
for (i = 0; i < numChildren; i++)
for (i=0;i<numChildren;i++)
{
if (m_childCollisionAlgorithms[i])
{
@@ -91,27 +89,48 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
removeChildAlgorithms();
}
struct btCompoundLeafCallback : btDbvt::ICollide
struct btCompoundLeafCallback : btDbvt::ICollide
{
public:
const btCollisionObjectWrapper* m_compoundColObjWrap;
const btCollisionObjectWrapper* m_otherObjWrap;
btDispatcher* m_dispatcher;
const btDispatcherInfo& m_dispatchInfo;
btManifoldResult* m_resultOut;
btCollisionAlgorithm** m_childCollisionAlgorithms;
btPersistentManifold* m_sharedManifold;
btCompoundLeafCallback(const btCollisionObjectWrapper* compoundObjWrap, const btCollisionObjectWrapper* otherObjWrap, btDispatcher* dispatcher, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut, btCollisionAlgorithm** childCollisionAlgorithms, btPersistentManifold* sharedManifold)
: m_compoundColObjWrap(compoundObjWrap), m_otherObjWrap(otherObjWrap), m_dispatcher(dispatcher), m_dispatchInfo(dispatchInfo), m_resultOut(resultOut), m_childCollisionAlgorithms(childCollisionAlgorithms), m_sharedManifold(sharedManifold)
btManifoldResult* m_resultOut;
btCollisionAlgorithm** m_childCollisionAlgorithms;
btPersistentManifold* m_sharedManifold;
btCompoundLeafCallback (const btCollisionObjectWrapper* compoundObjWrap,const btCollisionObjectWrapper* otherObjWrap,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold)
:m_compoundColObjWrap(compoundObjWrap),m_otherObjWrap(otherObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
m_childCollisionAlgorithms(childCollisionAlgorithms),
m_sharedManifold(sharedManifold)
{
}
void ProcessChildShape(const btCollisionShape* childShape, int index)
void ProcessChildShape(const btCollisionShape* childShape,int index)
{
btAssert(index >= 0);
btAssert(index>=0);
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
btAssert(index < compoundShape->getNumChildShapes());
btAssert(index<compoundShape->getNumChildShapes());
//backup
btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
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_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
if (gCompoundChildShapePairCallback)
{
@@ -119,51 +138,17 @@ public:
return;
}
//backup
btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(index);
btTransform newChildWorldTrans = orgTrans * childTrans;
//perform an AABB check first
btVector3 aabbMin0, aabbMax0;
childShape->getAabb(newChildWorldTrans, aabbMin0, aabbMax0);
btVector3 extendAabb(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold);
aabbMin0 -= extendAabb;
aabbMax0 += extendAabb;
btVector3 aabbMin1, aabbMax1;
m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(), aabbMin1, aabbMax1);
if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
btTransform preTransform = childTrans;
if (this->m_compoundColObjWrap->m_preTransform)
{
preTransform = preTransform *(*(this->m_compoundColObjWrap->m_preTransform));
}
btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap, childShape, m_compoundColObjWrap->getCollisionObject(), newChildWorldTrans, preTransform, -1, index);
btCollisionAlgorithm* algo = 0;
bool allocatedAlgorithm = false;
btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap,childShape,m_compoundColObjWrap->getCollisionObject(),newChildWorldTrans,-1,index);
if (m_resultOut->m_closestPointDistanceThreshold > 0)
{
algo = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
allocatedAlgorithm = true;
}
else
{
//the contactpoint is still projected back using the original inverted worldtrans
if (!m_childCollisionAlgorithms[index])
{
m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
}
algo = m_childCollisionAlgorithms[index];
}
//the contactpoint is still projected back using the original inverted worldtrans
if (!m_childCollisionAlgorithms[index])
m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap,m_otherObjWrap,m_sharedManifold);
const btCollisionObjectWrapper* tmpWrap = 0;
///detect swapping case
@@ -171,16 +156,16 @@ public:
{
tmpWrap = m_resultOut->getBody0Wrap();
m_resultOut->setBody0Wrap(&compoundWrap);
m_resultOut->setShapeIdentifiersA(-1, index);
}
else
m_resultOut->setShapeIdentifiersA(-1,index);
} else
{
tmpWrap = m_resultOut->getBody1Wrap();
m_resultOut->setBody1Wrap(&compoundWrap);
m_resultOut->setShapeIdentifiersB(-1, index);
m_resultOut->setShapeIdentifiersB(-1,index);
}
algo->processCollision(&compoundWrap, m_otherObjWrap, m_dispatchInfo, m_resultOut);
m_childCollisionAlgorithms[index]->processCollision(&compoundWrap,m_otherObjWrap,m_dispatchInfo,m_resultOut);
#if 0
if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
@@ -194,19 +179,14 @@ public:
if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
{
m_resultOut->setBody0Wrap(tmpWrap);
}
else
} else
{
m_resultOut->setBody1Wrap(tmpWrap);
}
if (allocatedAlgorithm)
{
algo->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algo);
}
}
}
void Process(const btDbvtNode* leaf)
void Process(const btDbvtNode* leaf)
{
int index = leaf->dataAsInt;
@@ -223,16 +203,22 @@ public:
}
#endif
ProcessChildShape(childShape, index);
ProcessChildShape(childShape,index);
}
};
void btCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* otherObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
btAssert(colObjWrap->getCollisionShape()->isCompound());
void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
btAssert (colObjWrap->getCollisionShape()->isCompound());
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
///btCompoundShape might have changed:
@@ -241,36 +227,36 @@ void btCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapp
{
///clear and update all
removeChildAlgorithms();
preallocateChildAlgorithms(body0Wrap, body1Wrap);
preallocateChildAlgorithms(body0Wrap,body1Wrap);
m_compoundShapeRevision = compoundShape->getUpdateRevision();
}
if (m_childCollisionAlgorithms.size() == 0)
if (m_childCollisionAlgorithms.size()==0)
return;
const btDbvt* tree = compoundShape->getDynamicAabbTree();
//use a dynamic aabb tree to cull potential child-overlaps
btCompoundLeafCallback callback(colObjWrap, otherObjWrap, m_dispatcher, dispatchInfo, resultOut, &m_childCollisionAlgorithms[0], m_sharedManifold);
btCompoundLeafCallback callback(colObjWrap,otherObjWrap,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
///we need to refresh all contact manifolds
///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
{
int i;
manifoldArray.resize(0);
for (i = 0; i < m_childCollisionAlgorithms.size(); i++)
btManifoldArray manifoldArray;
for (i=0;i<m_childCollisionAlgorithms.size();i++)
{
if (m_childCollisionAlgorithms[i])
{
m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
for (int m = 0; m < manifoldArray.size(); m++)
for (int m=0;m<manifoldArray.size();m++)
{
if (manifoldArray[m]->getNumContacts())
{
resultOut->setPersistentManifold(manifoldArray[m]);
resultOut->refreshContactPoints();
resultOut->setPersistentManifold(0); //??necessary?
resultOut->setPersistentManifold(0);//??necessary?
}
}
manifoldArray.resize(0);
@@ -280,56 +266,54 @@ void btCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapp
if (tree)
{
btVector3 localAabbMin, localAabbMax;
btVector3 localAabbMin,localAabbMax;
btTransform otherInCompoundSpace;
otherInCompoundSpace = colObjWrap->getWorldTransform().inverse() * otherObjWrap->getWorldTransform();
otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace, localAabbMin, localAabbMax);
btVector3 extraExtends(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold);
localAabbMin -= extraExtends;
localAabbMax += extraExtends;
otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
//process all children, that overlap with the given AABB bounds
tree->collideTVNoStackAlloc(tree->m_root, bounds, stack2, callback);
}
else
tree->collideTV(tree->m_root,bounds,callback);
} else
{
//iterate over all children, perform an AABB check inside ProcessChildShape
int numChildren = m_childCollisionAlgorithms.size();
int i;
for (i = 0; i < numChildren; i++)
for (i=0;i<numChildren;i++)
{
callback.ProcessChildShape(compoundShape->getChildShape(i), i);
callback.ProcessChildShape(compoundShape->getChildShape(i),i);
}
}
{
//iterate over all children, perform an AABB check inside ProcessChildShape
//iterate over all children, perform an AABB check inside ProcessChildShape
int numChildren = m_childCollisionAlgorithms.size();
int i;
manifoldArray.resize(0);
const btCollisionShape* childShape = 0;
btTransform orgTrans;
btTransform newChildWorldTrans;
btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
for (i = 0; i < numChildren; i++)
btManifoldArray manifoldArray;
const btCollisionShape* childShape = 0;
btTransform orgTrans;
btTransform newChildWorldTrans;
btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
for (i=0;i<numChildren;i++)
{
if (m_childCollisionAlgorithms[i])
{
childShape = compoundShape->getChildShape(i);
//if not longer overlapping, remove the algorithm
//if not longer overlapping, remove the algorithm
orgTrans = colObjWrap->getWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(i);
newChildWorldTrans = orgTrans * childTrans;
newChildWorldTrans = orgTrans*childTrans ;
//perform an AABB check first
childShape->getAabb(newChildWorldTrans, aabbMin0, aabbMax0);
otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(), aabbMin1, aabbMax1);
childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
if (!TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
@@ -340,15 +324,15 @@ void btCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapp
}
}
btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btAssert(0);
//needs to be fixed, using btCollisionObjectWrapper and NOT modifying internal data structures
btCollisionObject* colObj = m_isSwapped ? body1 : body0;
btCollisionObject* otherObj = m_isSwapped ? body0 : body1;
btAssert(colObj->getCollisionShape()->isCompound());
btCollisionObject* colObj = m_isSwapped? body1 : body0;
btCollisionObject* otherObj = m_isSwapped? body0 : body1;
btAssert (colObj->getCollisionShape()->isCompound());
btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
//We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
@@ -362,29 +346,33 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
int numChildren = m_childCollisionAlgorithms.size();
int i;
btTransform orgTrans;
btScalar frac;
for (i = 0; i < numChildren; i++)
btTransform orgTrans;
btScalar frac;
for (i=0;i<numChildren;i++)
{
//btCollisionShape* childShape = compoundShape->getChildShape(i);
//backup
orgTrans = colObj->getWorldTransform();
orgTrans = colObj->getWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(i);
//btTransform newChildWorldTrans = orgTrans*childTrans ;
colObj->setWorldTransform(orgTrans * childTrans);
colObj->setWorldTransform( orgTrans*childTrans );
//btCollisionShape* tmpShape = colObj->getCollisionShape();
//colObj->internalSetTemporaryCollisionShape( childShape );
frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj, otherObj, dispatchInfo, resultOut);
if (frac < hitFraction)
frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
if (frac<hitFraction)
{
hitFraction = frac;
}
//revert back
//colObj->internalSetTemporaryCollisionShape( tmpShape);
colObj->setWorldTransform(orgTrans);
colObj->setWorldTransform( orgTrans);
}
return hitFraction;
}

View File

@@ -26,7 +26,6 @@ class btDispatcher;
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "btCollisionCreateFunc.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
class btDispatcher;
class btCollisionObject;
@@ -35,65 +34,67 @@ typedef bool (*btShapePairCallback)(const btCollisionShape* pShape0, const btCol
extern btShapePairCallback gCompoundChildShapePairCallback;
/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
btNodeStack stack2;
btManifoldArray manifoldArray;
protected:
btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms;
bool m_isSwapped;
class btPersistentManifold* m_sharedManifold;
bool m_ownsManifold;
class btPersistentManifold* m_sharedManifold;
bool m_ownsManifold;
int m_compoundShapeRevision; //to keep track of changes, so that childAlgorithm array can be updated
void removeChildAlgorithms();
void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
int m_compoundShapeRevision;//to keep track of changes, so that childAlgorithm array can be updated
void removeChildAlgorithms();
void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
public:
btCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
virtual ~btCompoundCollisionAlgorithm();
btCollisionAlgorithm* getChildAlgorithm(int n) const
btCollisionAlgorithm* getChildAlgorithm (int n) const
{
return m_childCollisionAlgorithms[n];
}
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
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++)
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, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
return new (mem) btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
return new(mem) btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
}
};
struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
return new (mem) btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
return new(mem) btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
}
};
};
#endif //BT_COMPOUND_COLLISION_ALGORITHM_H
#endif //BT_COMPOUND_COLLISION_ALGORITHM_H

View File

@@ -15,7 +15,6 @@ subject to the following restrictions:
*/
#include "btCompoundCompoundCollisionAlgorithm.h"
#include "LinearMath/btQuickprof.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
@@ -24,30 +23,32 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
//USE_LOCAL_STACK will avoid most (often all) dynamic memory allocations due to resizing in processCollision and MycollideTT
#define USE_LOCAL_STACK 1
btShapePairCallback gCompoundCompoundChildShapePairCallback = 0;
btCompoundCompoundCollisionAlgorithm::btCompoundCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
: btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, isSwapped)
btCompoundCompoundCollisionAlgorithm::btCompoundCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
:btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,isSwapped)
{
void* ptr = btAlignedAlloc(sizeof(btHashedSimplePairCache), 16);
m_childCollisionAlgorithmCache = new (ptr) btHashedSimplePairCache();
void* ptr = btAlignedAlloc(sizeof(btHashedSimplePairCache),16);
m_childCollisionAlgorithmCache= new(ptr) btHashedSimplePairCache();
const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
btAssert(col0ObjWrap->getCollisionShape()->isCompound());
btAssert (col0ObjWrap->getCollisionShape()->isCompound());
const btCollisionObjectWrapper* col1ObjWrap = body1Wrap;
btAssert(col1ObjWrap->getCollisionShape()->isCompound());
btAssert (col1ObjWrap->getCollisionShape()->isCompound());
const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
}
btCompoundCompoundCollisionAlgorithm::~btCompoundCompoundCollisionAlgorithm()
{
removeChildAlgorithms();
@@ -55,30 +56,32 @@ btCompoundCompoundCollisionAlgorithm::~btCompoundCompoundCollisionAlgorithm()
btAlignedFree(m_childCollisionAlgorithmCache);
}
void btCompoundCompoundCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
void btCompoundCompoundCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
{
int i;
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
for (i = 0; i < pairs.size(); i++)
for (i=0;i<pairs.size();i++)
{
if (pairs[i].m_userPointer)
{
((btCollisionAlgorithm*)pairs[i].m_userPointer)->getAllContactManifolds(manifoldArray);
}
}
}
void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms()
void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms()
{
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
int numChildren = pairs.size();
int i;
for (i = 0; i < numChildren; i++)
for (i=0;i<numChildren;i++)
{
if (pairs[i].m_userPointer)
{
btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
btCollisionAlgorithm* algo = (btCollisionAlgorithm*) pairs[i].m_userPointer;
algo->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algo);
}
@@ -86,106 +89,106 @@ void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms()
m_childCollisionAlgorithmCache->removeAllPairs();
}
struct btCompoundCompoundLeafCallback : btDbvt::ICollide
struct btCompoundCompoundLeafCallback : btDbvt::ICollide
{
int m_numOverlapPairs;
const btCollisionObjectWrapper* m_compound0ColObjWrap;
const btCollisionObjectWrapper* m_compound1ColObjWrap;
btDispatcher* m_dispatcher;
const btDispatcherInfo& m_dispatchInfo;
btManifoldResult* m_resultOut;
class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
btPersistentManifold* m_sharedManifold;
btCompoundCompoundLeafCallback(const btCollisionObjectWrapper* compound1ObjWrap,
const btCollisionObjectWrapper* compound0ObjWrap,
btDispatcher* dispatcher,
const btDispatcherInfo& dispatchInfo,
btManifoldResult* resultOut,
btHashedSimplePairCache* childAlgorithmsCache,
btPersistentManifold* sharedManifold)
: m_numOverlapPairs(0), m_compound0ColObjWrap(compound1ObjWrap), m_compound1ColObjWrap(compound0ObjWrap), m_dispatcher(dispatcher), m_dispatchInfo(dispatchInfo), m_resultOut(resultOut), m_childCollisionAlgorithmCache(childAlgorithmsCache), m_sharedManifold(sharedManifold)
btManifoldResult* m_resultOut;
class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
btPersistentManifold* m_sharedManifold;
btCompoundCompoundLeafCallback (const btCollisionObjectWrapper* compound1ObjWrap,
const btCollisionObjectWrapper* compound0ObjWrap,
btDispatcher* dispatcher,
const btDispatcherInfo& dispatchInfo,
btManifoldResult* resultOut,
btHashedSimplePairCache* childAlgorithmsCache,
btPersistentManifold* sharedManifold)
:m_numOverlapPairs(0),m_compound0ColObjWrap(compound1ObjWrap),m_compound1ColObjWrap(compound0ObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
m_childCollisionAlgorithmCache(childAlgorithmsCache),
m_sharedManifold(sharedManifold)
{
}
void Process(const btDbvtNode* leaf0, const btDbvtNode* leaf1)
void Process(const btDbvtNode* leaf0,const btDbvtNode* leaf1)
{
BT_PROFILE("btCompoundCompoundLeafCallback::Process");
m_numOverlapPairs++;
int childIndex0 = leaf0->dataAsInt;
int childIndex1 = leaf1->dataAsInt;
btAssert(childIndex0>=0);
btAssert(childIndex1>=0);
btAssert(childIndex0 >= 0);
btAssert(childIndex1 >= 0);
const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(m_compound0ColObjWrap->getCollisionShape());
btAssert(childIndex0 < compoundShape0->getNumChildShapes());
btAssert(childIndex0<compoundShape0->getNumChildShapes());
const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(m_compound1ColObjWrap->getCollisionShape());
btAssert(childIndex1 < compoundShape1->getNumChildShapes());
btAssert(childIndex1<compoundShape1->getNumChildShapes());
const btCollisionShape* childShape0 = compoundShape0->getChildShape(childIndex0);
const btCollisionShape* childShape1 = compoundShape1->getChildShape(childIndex1);
//backup
btTransform orgTrans0 = m_compound0ColObjWrap->getWorldTransform();
btTransform orgTrans0 = m_compound0ColObjWrap->getWorldTransform();
const btTransform& childTrans0 = compoundShape0->getChildTransform(childIndex0);
btTransform newChildWorldTrans0 = orgTrans0 * childTrans0;
btTransform orgTrans1 = m_compound1ColObjWrap->getWorldTransform();
btTransform newChildWorldTrans0 = orgTrans0*childTrans0 ;
btTransform orgTrans1 = m_compound1ColObjWrap->getWorldTransform();
const btTransform& childTrans1 = compoundShape1->getChildTransform(childIndex1);
btTransform newChildWorldTrans1 = orgTrans1 * childTrans1;
btTransform newChildWorldTrans1 = orgTrans1*childTrans1 ;
//perform an AABB check first
btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
childShape0->getAabb(newChildWorldTrans0, aabbMin0, aabbMax0);
childShape1->getAabb(newChildWorldTrans1, aabbMin1, aabbMax1);
btVector3 thresholdVec(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold);
aabbMin0 -= thresholdVec;
aabbMax0 += thresholdVec;
btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0);
childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1);
if (gCompoundCompoundChildShapePairCallback)
{
if (!gCompoundCompoundChildShapePairCallback(childShape0, childShape1))
if (!gCompoundCompoundChildShapePairCallback(childShape0,childShape1))
return;
}
if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
btCollisionObjectWrapper compoundWrap0(this->m_compound0ColObjWrap, childShape0, m_compound0ColObjWrap->getCollisionObject(), newChildWorldTrans0, -1, childIndex0);
btCollisionObjectWrapper compoundWrap1(this->m_compound1ColObjWrap, childShape1, m_compound1ColObjWrap->getCollisionObject(), newChildWorldTrans1, -1, childIndex1);
btCollisionObjectWrapper compoundWrap0(this->m_compound0ColObjWrap,childShape0, m_compound0ColObjWrap->getCollisionObject(),newChildWorldTrans0,-1,childIndex0);
btCollisionObjectWrapper compoundWrap1(this->m_compound1ColObjWrap,childShape1,m_compound1ColObjWrap->getCollisionObject(),newChildWorldTrans1,-1,childIndex1);
btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0,childIndex1);
btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0, childIndex1);
bool removePair = false;
btCollisionAlgorithm* colAlgo = 0;
if (m_resultOut->m_closestPointDistanceThreshold > 0)
if (pair)
{
colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, 0, BT_CLOSEST_POINT_ALGORITHMS);
removePair = true;
}
else
colAlgo = (btCollisionAlgorithm*)pair->m_userPointer;
} else
{
if (pair)
{
colAlgo = (btCollisionAlgorithm*)pair->m_userPointer;
}
else
{
colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
pair = m_childCollisionAlgorithmCache->addOverlappingPair(childIndex0, childIndex1);
btAssert(pair);
pair->m_userPointer = colAlgo;
}
colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0,&compoundWrap1,m_sharedManifold);
pair = m_childCollisionAlgorithmCache->addOverlappingPair(childIndex0,childIndex1);
btAssert(pair);
pair->m_userPointer = colAlgo;
}
btAssert(colAlgo);
const btCollisionObjectWrapper* tmpWrap0 = 0;
const btCollisionObjectWrapper* tmpWrap1 = 0;
@@ -195,100 +198,94 @@ struct btCompoundCompoundLeafCallback : btDbvt::ICollide
m_resultOut->setBody0Wrap(&compoundWrap0);
m_resultOut->setBody1Wrap(&compoundWrap1);
m_resultOut->setShapeIdentifiersA(-1, childIndex0);
m_resultOut->setShapeIdentifiersB(-1, childIndex1);
m_resultOut->setShapeIdentifiersA(-1,childIndex0);
m_resultOut->setShapeIdentifiersB(-1,childIndex1);
colAlgo->processCollision(&compoundWrap0, &compoundWrap1, m_dispatchInfo, m_resultOut);
colAlgo->processCollision(&compoundWrap0,&compoundWrap1,m_dispatchInfo,m_resultOut);
m_resultOut->setBody0Wrap(tmpWrap0);
m_resultOut->setBody1Wrap(tmpWrap1);
if (removePair)
{
colAlgo->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(colAlgo);
}
}
}
};
static DBVT_INLINE bool MyIntersect(const btDbvtAabbMm& a,
const btDbvtAabbMm& b, const btTransform& xform, btScalar distanceThreshold)
static DBVT_INLINE bool MyIntersect( const btDbvtAabbMm& a,
const btDbvtAabbMm& b, const btTransform& xform)
{
btVector3 newmin, newmax;
btTransformAabb(b.Mins(), b.Maxs(), 0.f, xform, newmin, newmax);
newmin -= btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
newmax += btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin, newmax);
return Intersect(a, newb);
btVector3 newmin,newmax;
btTransformAabb(b.Mins(),b.Maxs(),0.f,xform,newmin,newmax);
btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin,newmax);
return Intersect(a,newb);
}
static inline void MycollideTT(const btDbvtNode* root0,
const btDbvtNode* root1,
const btTransform& xform,
btCompoundCompoundLeafCallback* callback, btScalar distanceThreshold)
static inline void MycollideTT( const btDbvtNode* root0,
const btDbvtNode* root1,
const btTransform& xform,
btCompoundCompoundLeafCallback* callback)
{
if (root0 && root1)
{
int depth = 1;
int treshold = btDbvt::DOUBLE_STACKSIZE - 4;
btAlignedObjectArray<btDbvt::sStkNN> stkStack;
#ifdef USE_LOCAL_STACK
ATTRIBUTE_ALIGNED16(btDbvt::sStkNN localStack[btDbvt::DOUBLE_STACKSIZE]);
stkStack.initializeFromBuffer(&localStack, btDbvt::DOUBLE_STACKSIZE, btDbvt::DOUBLE_STACKSIZE);
#else
stkStack.resize(btDbvt::DOUBLE_STACKSIZE);
#endif
stkStack[0] = btDbvt::sStkNN(root0, root1);
do
if(root0&&root1)
{
btDbvt::sStkNN p = stkStack[--depth];
if (MyIntersect(p.a->volume, p.b->volume, xform, distanceThreshold))
{
if (depth > treshold)
int depth=1;
int treshold=btDbvt::DOUBLE_STACKSIZE-4;
btAlignedObjectArray<btDbvt::sStkNN> stkStack;
stkStack.resize(btDbvt::DOUBLE_STACKSIZE);
stkStack[0]=btDbvt::sStkNN(root0,root1);
do {
btDbvt::sStkNN p=stkStack[--depth];
if(MyIntersect(p.a->volume,p.b->volume,xform))
{
stkStack.resize(stkStack.size() * 2);
treshold = stkStack.size() - 4;
}
if (p.a->isinternal())
{
if (p.b->isinternal())
if(depth>treshold)
{
stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b->childs[0]);
stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b->childs[0]);
stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b->childs[1]);
stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b->childs[1]);
stkStack.resize(stkStack.size()*2);
treshold=stkStack.size()-4;
}
if(p.a->isinternal())
{
if(p.b->isinternal())
{
stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[0]);
stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[0]);
stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[1]);
stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[1]);
}
else
{
stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b);
stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b);
}
}
else
{
stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b);
stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b);
if(p.b->isinternal())
{
stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[0]);
stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[1]);
}
else
{
callback->Process(p.a,p.b);
}
}
}
else
{
if (p.b->isinternal())
{
stkStack[depth++] = btDbvt::sStkNN(p.a, p.b->childs[0]);
stkStack[depth++] = btDbvt::sStkNN(p.a, p.b->childs[1]);
}
else
{
callback->Process(p.a, p.b);
}
}
}
} while (depth);
}
} while(depth);
}
}
void btCompoundCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
const btCollisionObjectWrapper* col1ObjWrap = body1Wrap;
btAssert(col0ObjWrap->getCollisionShape()->isCompound());
btAssert(col1ObjWrap->getCollisionShape()->isCompound());
const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
const btCollisionObjectWrapper* col1ObjWrap= body1Wrap;
btAssert (col0ObjWrap->getCollisionShape()->isCompound());
btAssert (col1ObjWrap->getCollisionShape()->isCompound());
const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
@@ -296,7 +293,7 @@ void btCompoundCompoundCollisionAlgorithm::processCollision(const btCollisionObj
const btDbvt* tree1 = compoundShape1->getDynamicAabbTree();
if (!tree0 || !tree1)
{
return btCompoundCollisionAlgorithm::processCollision(body0Wrap, body1Wrap, dispatchInfo, resultOut);
return btCompoundCollisionAlgorithm::processCollision(body0Wrap,body1Wrap,dispatchInfo,resultOut);
}
///btCompoundShape might have changed:
////make sure the internal child collision algorithm caches are still valid
@@ -306,26 +303,24 @@ void btCompoundCompoundCollisionAlgorithm::processCollision(const btCollisionObj
removeChildAlgorithms();
m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
}
///we need to refresh all contact manifolds
///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
{
int i;
btManifoldArray manifoldArray;
#ifdef USE_LOCAL_STACK
btPersistentManifold localManifolds[4];
manifoldArray.initializeFromBuffer(&localManifolds, 0, 4);
#endif
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
for (i = 0; i < pairs.size(); i++)
for (i=0;i<pairs.size();i++)
{
if (pairs[i].m_userPointer)
{
btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
btCollisionAlgorithm* algo = (btCollisionAlgorithm*) pairs[i].m_userPointer;
algo->getAllContactManifolds(manifoldArray);
for (int m = 0; m < manifoldArray.size(); m++)
for (int m=0;m<manifoldArray.size();m++)
{
if (manifoldArray[m]->getNumContacts())
{
@@ -339,75 +334,93 @@ void btCompoundCompoundCollisionAlgorithm::processCollision(const btCollisionObj
}
}
btCompoundCompoundLeafCallback callback(col0ObjWrap, col1ObjWrap, this->m_dispatcher, dispatchInfo, resultOut, this->m_childCollisionAlgorithmCache, m_sharedManifold);
const btTransform xform = col0ObjWrap->getWorldTransform().inverse() * col1ObjWrap->getWorldTransform();
MycollideTT(tree0->m_root, tree1->m_root, xform, &callback, resultOut->m_closestPointDistanceThreshold);
btCompoundCompoundLeafCallback callback(col0ObjWrap,col1ObjWrap,this->m_dispatcher,dispatchInfo,resultOut,this->m_childCollisionAlgorithmCache,m_sharedManifold);
const btTransform xform=col0ObjWrap->getWorldTransform().inverse()*col1ObjWrap->getWorldTransform();
MycollideTT(tree0->m_root,tree1->m_root,xform,&callback);
//printf("#compound-compound child/leaf overlap =%d \r",callback.m_numOverlapPairs);
//remove non-overlapping child pairs
{
btAssert(m_removePairs.size() == 0);
btAssert(m_removePairs.size()==0);
//iterate over all children, perform an AABB check inside ProcessChildShape
btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
int i;
btManifoldArray manifoldArray;
btManifoldArray manifoldArray;
btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
for (i = 0; i < pairs.size(); i++)
btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
for (i=0;i<pairs.size();i++)
{
if (pairs[i].m_userPointer)
{
btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
{
btTransform orgTrans0;
const btCollisionShape* childShape0 = 0;
btTransform newChildWorldTrans0;
btTransform newChildWorldTrans0;
btTransform orgInterpolationTrans0;
childShape0 = compoundShape0->getChildShape(pairs[i].m_indexA);
orgTrans0 = col0ObjWrap->getWorldTransform();
orgInterpolationTrans0 = col0ObjWrap->getWorldTransform();
const btTransform& childTrans0 = compoundShape0->getChildTransform(pairs[i].m_indexA);
newChildWorldTrans0 = col0ObjWrap->getWorldTransform() * childTrans0;
childShape0->getAabb(newChildWorldTrans0, aabbMin0, aabbMax0);
newChildWorldTrans0 = orgTrans0*childTrans0 ;
childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0);
}
btVector3 thresholdVec(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold);
aabbMin0 -= thresholdVec;
aabbMax0 += thresholdVec;
{
btTransform orgInterpolationTrans1;
const btCollisionShape* childShape1 = 0;
btTransform newChildWorldTrans1;
btTransform orgTrans1;
btTransform newChildWorldTrans1;
childShape1 = compoundShape1->getChildShape(pairs[i].m_indexB);
orgTrans1 = col1ObjWrap->getWorldTransform();
orgInterpolationTrans1 = col1ObjWrap->getWorldTransform();
const btTransform& childTrans1 = compoundShape1->getChildTransform(pairs[i].m_indexB);
newChildWorldTrans1 = col1ObjWrap->getWorldTransform() * childTrans1;
childShape1->getAabb(newChildWorldTrans1, aabbMin1, aabbMax1);
newChildWorldTrans1 = orgTrans1*childTrans1 ;
childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1);
}
aabbMin1 -= thresholdVec;
aabbMax1 += thresholdVec;
if (!TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
algo->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algo);
m_removePairs.push_back(btSimplePair(pairs[i].m_indexA, pairs[i].m_indexB));
m_removePairs.push_back(btSimplePair(pairs[i].m_indexA,pairs[i].m_indexB));
}
}
}
for (int i = 0; i < m_removePairs.size(); i++)
for (int i=0;i<m_removePairs.size();i++)
{
m_childCollisionAlgorithmCache->removeOverlappingPair(m_removePairs[i].m_indexA, m_removePairs[i].m_indexB);
m_childCollisionAlgorithmCache->removeOverlappingPair(m_removePairs[i].m_indexA,m_removePairs[i].m_indexB);
}
m_removePairs.clear();
}
}
btScalar btCompoundCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btCompoundCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btAssert(0);
return 0.f;
}

View File

@@ -33,50 +33,57 @@ class btDispatcher;
class btCollisionObject;
class btCollisionShape;
typedef bool (*btShapePairCallback)(const btCollisionShape* pShape0, const btCollisionShape* pShape1);
extern btShapePairCallback gCompoundCompoundChildShapePairCallback;
/// btCompoundCompoundCollisionAlgorithm supports collision between two btCompoundCollisionShape shapes
class btCompoundCompoundCollisionAlgorithm : public btCompoundCollisionAlgorithm
class btCompoundCompoundCollisionAlgorithm : public btCompoundCollisionAlgorithm
{
class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
btSimplePairArray m_removePairs;
int m_compoundShapeRevision0; //to keep track of changes, so that childAlgorithm array can be updated
int m_compoundShapeRevision1;
void removeChildAlgorithms();
// void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
int m_compoundShapeRevision0;//to keep track of changes, so that childAlgorithm array can be updated
int m_compoundShapeRevision1;
void removeChildAlgorithms();
// void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
public:
btCompoundCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
btCompoundCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
virtual ~btCompoundCompoundCollisionAlgorithm();
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
struct CreateFunc : public btCollisionAlgorithmCreateFunc
virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm));
return new (mem) btCompoundCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
return new(mem) btCompoundCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
}
};
struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm));
return new (mem) btCompoundCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
return new(mem) btCompoundCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
}
};
};
#endif //BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
#endif //BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H

View File

@@ -22,6 +22,7 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
@@ -33,6 +34,8 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
@@ -42,28 +45,31 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
{
m_simplexSolver = simplexSolver;
m_pdSolver = pdSolver;
}
btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc()
{
btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc()
{
}
btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int /* numPerturbationIterations */, int /* minimumPointsPerturbationThreshold */)
: btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
m_simplexSolver(simplexSolver),
m_pdSolver(pdSolver),
m_ownManifold(false),
m_manifoldPtr(mf),
m_lowLevelOfDetail(false)
btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int /* numPerturbationIterations */, int /* minimumPointsPerturbationThreshold */)
: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_simplexSolver(simplexSolver),
m_pdSolver(pdSolver),
m_ownManifold (false),
m_manifoldPtr(mf),
m_lowLevelOfDetail(false)
{
(void)body0Wrap;
(void)body1Wrap;
}
btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm()
{
if (m_ownManifold)
@@ -73,22 +79,26 @@ btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm()
}
}
void btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
void btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
{
m_lowLevelOfDetail = useLowLevel;
}
extern btScalar gContactBreakingThreshold;
//
// Convex-Convex collision algorithm
//
void btConvex2dConvex2dAlgorithm ::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btConvex2dConvex2dAlgorithm ::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
{
//swapped?
m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
m_ownManifold = true;
}
resultOut->setPersistentManifold(m_manifoldPtr);
@@ -96,41 +106,49 @@ void btConvex2dConvex2dAlgorithm ::processCollision(const btCollisionObjectWrapp
//comment-out next line to test multi-contact generation
//resultOut->getPersistentManifold()->clearManifold();
const btConvexShape* min0 = static_cast<const btConvexShape*>(body0Wrap->getCollisionShape());
const btConvexShape* min1 = static_cast<const btConvexShape*>(body1Wrap->getCollisionShape());
btVector3 normalOnB;
btVector3 pointOnBWorld;
btVector3 normalOnB;
btVector3 pointOnBWorld;
{
btGjkPairDetector::ClosestPointInput input;
btGjkPairDetector gjkPairDetector(min0, min1, m_simplexSolver, m_pdSolver);
btGjkPairDetector gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver);
//TODO: if (dispatchInfo.m_useContinuous)
gjkPairDetector.setMinkowskiA(min0);
gjkPairDetector.setMinkowskiB(min1);
{
input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
input.m_maximumDistanceSquared *= input.m_maximumDistanceSquared;
input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
}
input.m_transformA = body0Wrap->getWorldTransform();
input.m_transformB = body1Wrap->getWorldTransform();
gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
btVector3 v0, v1;
btVector3 v0,v1;
btVector3 sepNormalWorldSpace;
}
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
}
btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
@@ -140,6 +158,7 @@ btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* c
///col0->m_worldTransform,
btScalar resultFraction = btScalar(1.);
btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
@@ -147,65 +166,77 @@ btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* c
squareMot1 < col1->getCcdSquareMotionThreshold())
return resultFraction;
//An adhoc way of testing the Continuous Collision Detection algorithms
//One object is approximated as a sphere, to simplify things
//Starting in penetration should report no time of impact
//For proper CCD, better accuracy and handling of 'allowed' penetration should be added
//also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
/// Convex0 against sphere for Convex1
{
btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
btConvexCast::CastResult result;
btVoronoiSimplexSolver voronoiSimplex;
//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
///Simplification, one object is simplified as a sphere
btGjkConvexCast ccd1(convex0, &sphere1, &voronoiSimplex);
btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
{
//store result.m_fraction in both bodies
if (col0->getHitFraction() > result.m_fraction)
col0->setHitFraction(result.m_fraction);
if (col0->getHitFraction()> result.m_fraction)
col0->setHitFraction( result.m_fraction );
if (col1->getHitFraction() > result.m_fraction)
col1->setHitFraction(result.m_fraction);
col1->setHitFraction( result.m_fraction);
if (resultFraction > result.m_fraction)
resultFraction = result.m_fraction;
}
}
/// Sphere (for convex0) against Convex1
{
btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
btConvexCast::CastResult result;
btVoronoiSimplexSolver voronoiSimplex;
//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
///Simplification, one object is simplified as a sphere
btGjkConvexCast ccd1(&sphere0, convex1, &voronoiSimplex);
btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
{
//store result.m_fraction in both bodies
if (col0->getHitFraction() > result.m_fraction)
col0->setHitFraction(result.m_fraction);
if (col0->getHitFraction() > result.m_fraction)
col0->setHitFraction( result.m_fraction);
if (col1->getHitFraction() > result.m_fraction)
col1->setHitFraction(result.m_fraction);
col1->setHitFraction( result.m_fraction);
if (resultFraction > result.m_fraction)
resultFraction = result.m_fraction;
}
}
return resultFraction;
}

View File

@@ -23,61 +23,70 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
class btConvexPenetrationDepthSolver;
///The convex2dConvex2dAlgorithm collision algorithm support 2d collision detection for btConvex2dShape
///Currently it requires the btMinkowskiPenetrationDepthSolver, it has support for 2d penetration depth computation
class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm
{
btSimplexSolverInterface* m_simplexSolver;
btSimplexSolverInterface* m_simplexSolver;
btConvexPenetrationDepthSolver* m_pdSolver;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_lowLevelOfDetail;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_lowLevelOfDetail;
public:
btConvex2dConvex2dAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
virtual ~btConvex2dConvex2dAlgorithm();
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
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);
const btPersistentManifold* getManifold()
void setLowLevelOfDetail(bool useLowLevel);
const btPersistentManifold* getManifold()
{
return m_manifoldPtr;
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
btConvexPenetrationDepthSolver* m_pdSolver;
btSimplexSolverInterface* m_simplexSolver;
btConvexPenetrationDepthSolver* m_pdSolver;
btSimplexSolverInterface* m_simplexSolver;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
virtual ~CreateFunc();
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvex2dConvex2dAlgorithm));
return new (mem) btConvex2dConvex2dAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_simplexSolver, m_pdSolver, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
return new(mem) btConvex2dConvex2dAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
}
};
};
#endif //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
#endif //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H

View File

@@ -13,8 +13,8 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btConvexConcaveCollisionAlgorithm.h"
#include "LinearMath/btQuickprof.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
@@ -26,12 +26,11 @@ subject to the following restrictions:
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#include "BulletCollision/CollisionShapes/btSdfCollisionShape.h"
btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
: btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
m_btConvexTriangleCallback(ci.m_dispatcher1, body0Wrap, body1Wrap, isSwapped),
m_isSwapped(isSwapped)
btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_isSwapped(isSwapped),
m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped)
{
}
@@ -39,7 +38,7 @@ btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
{
}
void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_btConvexTriangleCallback.m_manifoldPtr)
{
@@ -47,46 +46,55 @@ void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray&
}
}
btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped) : m_dispatcher(dispatcher),
m_dispatchInfoPtr(0)
btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped):
m_dispatcher(dispatcher),
m_dispatchInfoPtr(0)
{
m_convexBodyWrap = isSwapped ? body1Wrap : body0Wrap;
m_triBodyWrap = isSwapped ? body0Wrap : body1Wrap;
m_convexBodyWrap = isSwapped? body1Wrap:body0Wrap;
m_triBodyWrap = isSwapped? body0Wrap:body1Wrap;
//
// create the manifold from the dispatcher 'manifold pool'
//
m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBodyWrap->getCollisionObject(),m_triBodyWrap->getCollisionObject());
//
// create the manifold from the dispatcher 'manifold pool'
//
m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBodyWrap->getCollisionObject(), m_triBodyWrap->getCollisionObject());
clearCache();
clearCache();
}
btConvexTriangleCallback::~btConvexTriangleCallback()
{
clearCache();
m_dispatcher->releaseManifold(m_manifoldPtr);
m_dispatcher->releaseManifold( m_manifoldPtr );
}
void btConvexTriangleCallback::clearCache()
void btConvexTriangleCallback::clearCache()
{
m_dispatcher->clearManifold(m_manifoldPtr);
}
void btConvexTriangleCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
void btConvexTriangleCallback::processTriangle(btVector3* triangle,int
partId, int triangleIndex)
{
BT_PROFILE("btConvexTriangleCallback::processTriangle");
if (!TestTriangleAgainstAabb2(triangle, m_aabbMin, m_aabbMax))
{
return;
}
//just for debugging purposes
//printf("triangle %d",m_triangleCount++);
//just for debugging purposes
//printf("triangle %d",m_triangleCount++);
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = m_dispatcher;
#if 0
///debug drawing of the overlapping triangles
@@ -100,55 +108,52 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle, int partId,
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
}
#endif
if (m_convexBodyWrap->getCollisionShape()->isConvex())
{
btTriangleShape tm(triangle[0], triangle[1], triangle[2]);
btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
tm.setMargin(m_collisionMarginTriangle);
btCollisionObjectWrapper triObWrap(m_triBodyWrap,&tm,m_triBodyWrap->getCollisionObject(),m_triBodyWrap->getWorldTransform(),partId,triangleIndex);//correct transform?
btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap,&triObWrap,m_manifoldPtr);
btCollisionObjectWrapper triObWrap(m_triBodyWrap, &tm, m_triBodyWrap->getCollisionObject(), m_triBodyWrap->getWorldTransform(), partId, triangleIndex); //correct transform?
btCollisionAlgorithm* colAlgo = 0;
if (m_resultOut->m_closestPointDistanceThreshold > 0)
{
colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
}
else
{
colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, m_manifoldPtr, BT_CONTACT_POINT_ALGORITHMS);
}
const btCollisionObjectWrapper* tmpWrap = 0;
if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
{
tmpWrap = m_resultOut->getBody0Wrap();
m_resultOut->setBody0Wrap(&triObWrap);
m_resultOut->setShapeIdentifiersA(partId, triangleIndex);
m_resultOut->setShapeIdentifiersA(partId,triangleIndex);
}
else
{
tmpWrap = m_resultOut->getBody1Wrap();
m_resultOut->setBody1Wrap(&triObWrap);
m_resultOut->setShapeIdentifiersB(partId, triangleIndex);
m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
}
colAlgo->processCollision(m_convexBodyWrap, &triObWrap, *m_dispatchInfoPtr, m_resultOut);
colAlgo->processCollision(m_convexBodyWrap,&triObWrap,*m_dispatchInfoPtr,m_resultOut);
if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
{
m_resultOut->setBody0Wrap(tmpWrap);
}
else
} else
{
m_resultOut->setBody1Wrap(tmpWrap);
}
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
}
}
void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo& dispatchInfo, const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
{
m_convexBodyWrap = convexBodyWrap;
m_triBodyWrap = triBodyWrap;
@@ -162,120 +167,65 @@ void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTr
convexInTriangleSpace = m_triBodyWrap->getWorldTransform().inverse() * m_convexBodyWrap->getWorldTransform();
const btCollisionShape* convexShape = static_cast<const btCollisionShape*>(m_convexBodyWrap->getCollisionShape());
//CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
convexShape->getAabb(convexInTriangleSpace, m_aabbMin, m_aabbMax);
btScalar extraMargin = collisionMarginTriangle + resultOut->m_closestPointDistanceThreshold;
btVector3 extra(extraMargin, extraMargin, extraMargin);
convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
btScalar extraMargin = collisionMarginTriangle;
btVector3 extra(extraMargin,extraMargin,extraMargin);
m_aabbMax += extra;
m_aabbMin -= extra;
}
void btConvexConcaveCollisionAlgorithm::clearCache()
{
m_btConvexTriangleCallback.clearCache();
}
void btConvexConcaveCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btConvexConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
BT_PROFILE("btConvexConcaveCollisionAlgorithm::processCollision");
const btCollisionObjectWrapper* convexBodyWrap = m_isSwapped ? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* triBodyWrap = m_isSwapped ? body0Wrap : body1Wrap;
if (triBodyWrap->getCollisionShape()->isConcave())
{
if (triBodyWrap->getCollisionShape()->getShapeType() == SDF_SHAPE_PROXYTYPE)
const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>( triBodyWrap->getCollisionShape());
if (convexBodyWrap->getCollisionShape()->isConvex())
{
btSdfCollisionShape* sdfShape = (btSdfCollisionShape*)triBodyWrap->getCollisionShape();
if (convexBodyWrap->getCollisionShape()->isConvex())
{
btConvexShape* convex = (btConvexShape*)convexBodyWrap->getCollisionShape();
btAlignedObjectArray<btVector3> queryVertices;
btScalar collisionMarginTriangle = concaveShape->getMargin();
resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,convexBodyWrap,triBodyWrap,resultOut);
if (convex->isPolyhedral())
{
btPolyhedralConvexShape* poly = (btPolyhedralConvexShape*)convex;
for (int v = 0; v < poly->getNumVertices(); v++)
{
btVector3 vtx;
poly->getVertex(v, vtx);
queryVertices.push_back(vtx);
}
}
btScalar maxDist = SIMD_EPSILON;
m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(),triBodyWrap->getCollisionObject());
if (convex->getShapeType() == SPHERE_SHAPE_PROXYTYPE)
{
queryVertices.push_back(btVector3(0, 0, 0));
btSphereShape* sphere = (btSphereShape*)convex;
maxDist = sphere->getRadius() + SIMD_EPSILON;
}
if (queryVertices.size())
{
resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
//m_btConvexTriangleCallback.m_manifoldPtr->clearManifold();
concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
resultOut->refreshContactPoints();
btPolyhedralConvexShape* poly = (btPolyhedralConvexShape*)convex;
for (int v = 0; v < queryVertices.size(); v++)
{
const btVector3& vtx = queryVertices[v];
btVector3 vtxWorldSpace = convexBodyWrap->getWorldTransform() * vtx;
btVector3 vtxInSdf = triBodyWrap->getWorldTransform().invXform(vtxWorldSpace);
btVector3 normalLocal;
btScalar dist;
if (sdfShape->queryPoint(vtxInSdf, dist, normalLocal))
{
if (dist <= maxDist)
{
normalLocal.safeNormalize();
btVector3 normal = triBodyWrap->getWorldTransform().getBasis() * normalLocal;
if (convex->getShapeType() == SPHERE_SHAPE_PROXYTYPE)
{
btSphereShape* sphere = (btSphereShape*)convex;
dist -= sphere->getRadius();
vtxWorldSpace -= sphere->getRadius() * normal;
}
resultOut->addContactPoint(normal, vtxWorldSpace - normal * dist, dist);
}
}
}
resultOut->refreshContactPoints();
}
}
}
else
{
const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>(triBodyWrap->getCollisionShape());
if (convexBodyWrap->getCollisionShape()->isConvex())
{
btScalar collisionMarginTriangle = concaveShape->getMargin();
resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle, dispatchInfo, convexBodyWrap, triBodyWrap, resultOut);
m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(), triBodyWrap->getCollisionObject());
concaveShape->processAllTriangles(&m_btConvexTriangleCallback, m_btConvexTriangleCallback.getAabbMin(), m_btConvexTriangleCallback.getAabbMax());
resultOut->refreshContactPoints();
m_btConvexTriangleCallback.clearWrapperData();
}
m_btConvexTriangleCallback.clearWrapperData();
}
}
}
btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
btCollisionObject* triBody = m_isSwapped ? body0 : body1;
//quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
//only perform CCD above a certain threshold, this prevents blocking on the long run
@@ -294,26 +244,27 @@ btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObj
btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
struct LocalTriangleSphereCastCallback : public btTriangleCallback
struct LocalTriangleSphereCastCallback : public btTriangleCallback
{
btTransform m_ccdSphereFromTrans;
btTransform m_ccdSphereToTrans;
btTransform m_meshTransform;
btTransform m_meshTransform;
btScalar m_ccdSphereRadius;
btScalar m_hitFraction;
btScalar m_ccdSphereRadius;
btScalar m_hitFraction;
LocalTriangleSphereCastCallback(const btTransform& from, const btTransform& to, btScalar ccdSphereRadius, btScalar hitFraction)
: m_ccdSphereFromTrans(from),
m_ccdSphereToTrans(to),
m_ccdSphereRadius(ccdSphereRadius),
m_hitFraction(hitFraction)
{
LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
:m_ccdSphereFromTrans(from),
m_ccdSphereToTrans(to),
m_ccdSphereRadius(ccdSphereRadius),
m_hitFraction(hitFraction)
{
}
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
{
BT_PROFILE("processTriangle");
(void)partId;
(void)triangleIndex;
//do a swept sphere for now
@@ -321,23 +272,29 @@ btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObj
ident.setIdentity();
btConvexCast::CastResult castResult;
castResult.m_fraction = m_hitFraction;
btSphereShape pointShape(m_ccdSphereRadius);
btTriangleShape triShape(triangle[0], triangle[1], triangle[2]);
btVoronoiSimplexSolver simplexSolver;
btSubsimplexConvexCast convexCaster(&pointShape, &triShape, &simplexSolver);
btSphereShape pointShape(m_ccdSphereRadius);
btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
btVoronoiSimplexSolver simplexSolver;
btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
//GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
//ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
//local space?
if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans, m_ccdSphereToTrans,
ident, ident, castResult))
if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
ident,ident,castResult))
{
if (m_hitFraction > castResult.m_fraction)
m_hitFraction = castResult.m_fraction;
}
}
};
if (triBody->getCollisionShape()->isConcave())
{
btVector3 rayAabbMin = convexFromLocal.getOrigin();
@@ -345,30 +302,33 @@ btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObj
btVector3 rayAabbMax = convexFromLocal.getOrigin();
rayAabbMax.setMax(convexToLocal.getOrigin());
btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
rayAabbMin -= btVector3(ccdRadius0, ccdRadius0, ccdRadius0);
rayAabbMax += btVector3(ccdRadius0, ccdRadius0, ccdRadius0);
rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
btScalar curHitFraction = btScalar(1.); //is this available?
LocalTriangleSphereCastCallback raycastCallback(convexFromLocal, convexToLocal,
convexbody->getCcdSweptSphereRadius(), curHitFraction);
btScalar curHitFraction = btScalar(1.); //is this available?
LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
convexbody->getCcdSweptSphereRadius(),curHitFraction);
raycastCallback.m_hitFraction = convexbody->getHitFraction();
btCollisionObject* concavebody = triBody;
btConcaveShape* triangleMesh = (btConcaveShape*)concavebody->getCollisionShape();
btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
if (triangleMesh)
{
triangleMesh->processAllTriangles(&raycastCallback, rayAabbMin, rayAabbMax);
triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
}
if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
{
convexbody->setHitFraction(raycastCallback.m_hitFraction);
convexbody->setHitFraction( raycastCallback.m_hitFraction);
return raycastCallback.m_hitFraction;
}
}
return btScalar(1.);
}

View File

@@ -26,40 +26,38 @@ class btDispatcher;
#include "btCollisionCreateFunc.h"
///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
ATTRIBUTE_ALIGNED16(class)
btConvexTriangleCallback : public btTriangleCallback
class btConvexTriangleCallback : public btTriangleCallback
{
btVector3 m_aabbMin;
btVector3 m_aabbMax;
const btCollisionObjectWrapper* m_convexBodyWrap;
const btCollisionObjectWrapper* m_triBodyWrap;
btVector3 m_aabbMin;
btVector3 m_aabbMax ;
btManifoldResult* m_resultOut;
btDispatcher* m_dispatcher;
btDispatcher* m_dispatcher;
const btDispatcherInfo* m_dispatchInfoPtr;
btScalar m_collisionMarginTriangle;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
int m_triangleCount;
btPersistentManifold* m_manifoldPtr;
int m_triangleCount;
btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
btPersistentManifold* m_manifoldPtr;
void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut);
btConvexTriangleCallback(btDispatcher * dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
void setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo& dispatchInfo, const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut);
void clearWrapperData()
void clearWrapperData()
{
m_convexBodyWrap = 0;
m_triBodyWrap = 0;
}
virtual ~btConvexTriangleCallback();
virtual void processTriangle(btVector3 * triangle, int partId, int triangleIndex);
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
void clearCache();
SIMD_FORCE_INLINE const btVector3& getAabbMin() const
@@ -70,48 +68,54 @@ public:
{
return m_aabbMax;
}
};
/// btConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes.
ATTRIBUTE_ALIGNED16(class)
btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm
class btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_isSwapped;
btConvexTriangleCallback m_btConvexTriangleCallback;
bool m_isSwapped;
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btConvexConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
virtual ~btConvexConcaveCollisionAlgorithm();
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
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);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
void clearCache();
void clearCache();
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
return new (mem) btConvexConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
}
};
struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
return new (mem) btConvexConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
}
};
};
#endif //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
#endif //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H

View File

@@ -23,8 +23,7 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "btCollisionCreateFunc.h"
#include "btCollisionDispatcher.h"
#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h"
#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
class btConvexPenetrationDepthSolver;
@@ -41,61 +40,69 @@ class btConvexPenetrationDepthSolver;
class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm
{
#ifdef USE_SEPDISTANCE_UTIL2
btConvexSeparatingDistanceUtil m_sepDistance;
btConvexSeparatingDistanceUtil m_sepDistance;
#endif
btSimplexSolverInterface* m_simplexSolver;
btConvexPenetrationDepthSolver* m_pdSolver;
btVertexArray worldVertsB1;
btVertexArray worldVertsB2;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_lowLevelOfDetail;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_lowLevelOfDetail;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
///cache separating vector to speedup collision detection
public:
btConvexConvexAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
virtual ~btConvexConvexAlgorithm();
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
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);
const btPersistentManifold* getManifold()
void setLowLevelOfDetail(bool useLowLevel);
const btPersistentManifold* getManifold()
{
return m_manifoldPtr;
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
btConvexPenetrationDepthSolver* m_pdSolver;
btConvexPenetrationDepthSolver* m_pdSolver;
btSimplexSolverInterface* m_simplexSolver;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
CreateFunc(btConvexPenetrationDepthSolver* pdSolver);
CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
virtual ~CreateFunc();
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
return new (mem) btConvexConvexAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_pdSolver, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
}
};
};
#endif //BT_CONVEX_CONVEX_ALGORITHM_H
#endif //BT_CONVEX_CONVEX_ALGORITHM_H

View File

@@ -23,24 +23,25 @@ subject to the following restrictions:
//#include <stdio.h>
btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, bool isSwapped, int numPerturbationIterations, int minimumPointsPerturbationThreshold)
: btCollisionAlgorithm(ci),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped),
m_numPerturbationIterations(numPerturbationIterations),
m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold)
: btCollisionAlgorithm(ci),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped),
m_numPerturbationIterations(numPerturbationIterations),
m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
{
const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? col1Wrap : col0Wrap;
const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? col0Wrap : col1Wrap;
const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? col1Wrap : col0Wrap;
const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? col0Wrap : col1Wrap;
if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObjWrap->getCollisionObject(), planeObjWrap->getCollisionObject()))
if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObjWrap->getCollisionObject(),planeObjWrap->getCollisionObject()))
{
m_manifoldPtr = m_dispatcher->getNewManifold(convexObjWrap->getCollisionObject(), planeObjWrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(convexObjWrap->getCollisionObject(),planeObjWrap->getCollisionObject());
m_ownManifold = true;
}
}
btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
{
if (m_ownManifold)
@@ -50,32 +51,32 @@ btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
}
}
void btConvexPlaneCollisionAlgorithm::collideSingleContact(const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? body0Wrap: body1Wrap;
btConvexShape* convexShape = (btConvexShape*)convexObjWrap->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*)planeObjWrap->getCollisionShape();
btConvexShape* convexShape = (btConvexShape*) convexObjWrap->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObjWrap->getCollisionShape();
bool hasCollision = false;
bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
btTransform convexWorldTransform = convexObjWrap->getWorldTransform();
btTransform convexInPlaneTrans;
convexInPlaneTrans = planeObjWrap->getWorldTransform().inverse() * convexWorldTransform;
convexInPlaneTrans= planeObjWrap->getWorldTransform().inverse() * convexWorldTransform;
//now perturbe the convex-world transform
convexWorldTransform.getBasis() *= btMatrix3x3(perturbeRot);
convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot);
btTransform planeInConvex;
planeInConvex = convexWorldTransform.inverse() * planeObjWrap->getWorldTransform();
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis() * -planeNormal);
planeInConvex= convexWorldTransform.inverse() * planeObjWrap->getWorldTransform();
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
btVector3 vtxInPlaneProjected = vtxInPlane - distance * planeNormal;
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
@@ -85,69 +86,70 @@ void btConvexPlaneCollisionAlgorithm::collideSingleContact(const btQuaternion& p
/// report a contact. internally this will be kept persistent, and contact reduction is done
btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
btVector3 pOnB = vtxInPlaneWorld;
resultOut->addContactPoint(normalOnSurfaceB, pOnB, distance);
resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
}
}
void btConvexPlaneCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btConvexPlaneCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
if (!m_manifoldPtr)
return;
const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? body0Wrap: body1Wrap;
btConvexShape* convexShape = (btConvexShape*)convexObjWrap->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*)planeObjWrap->getCollisionShape();
btConvexShape* convexShape = (btConvexShape*) convexObjWrap->getCollisionShape();
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObjWrap->getCollisionShape();
bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
btTransform planeInConvex;
planeInConvex = convexObjWrap->getWorldTransform().inverse() * planeObjWrap->getWorldTransform();
planeInConvex= convexObjWrap->getWorldTransform().inverse() * planeObjWrap->getWorldTransform();
btTransform convexInPlaneTrans;
convexInPlaneTrans = planeObjWrap->getWorldTransform().inverse() * convexObjWrap->getWorldTransform();
convexInPlaneTrans= planeObjWrap->getWorldTransform().inverse() * convexObjWrap->getWorldTransform();
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis() * -planeNormal);
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
btVector3 vtxInPlaneProjected = vtxInPlane - distance * planeNormal;
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
resultOut->setPersistentManifold(m_manifoldPtr);
if (hasCollision)
{
/// report a contact. internally this will be kept persistent, and contact reduction is done
btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
btVector3 pOnB = vtxInPlaneWorld;
resultOut->addContactPoint(normalOnSurfaceB, pOnB, distance);
resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
}
//the perturbation algorithm doesn't work well with implicit surfaces such as spheres, cylinder and cones:
//they keep on rolling forever because of the additional off-center contact points
//so only enable the feature for polyhedral shapes (btBoxShape, btConvexHullShape etc)
if (convexShape->isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
if (convexShape->isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts()<m_minimumPointsPerturbationThreshold)
{
btVector3 v0, v1;
btPlaneSpace1(planeNormal, v0, v1);
btVector3 v0,v1;
btPlaneSpace1(planeNormal,v0,v1);
//now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
const btScalar angleLimit = 0.125f * SIMD_PI;
btScalar perturbeAngle;
btScalar radius = convexShape->getAngularMotionDisc();
perturbeAngle = gContactBreakingThreshold / radius;
if (perturbeAngle > angleLimit)
perturbeAngle = angleLimit;
if ( perturbeAngle > angleLimit )
perturbeAngle = angleLimit;
btQuaternion perturbeRot(v0, perturbeAngle);
for (int i = 0; i < m_numPerturbationIterations; i++)
btQuaternion perturbeRot(v0,perturbeAngle);
for (int i=0;i<m_numPerturbationIterations;i++)
{
btScalar iterationAngle = i * (SIMD_2_PI / btScalar(m_numPerturbationIterations));
btQuaternion rotq(planeNormal, iterationAngle);
collideSingleContact(rotq.inverse() * perturbeRot * rotq, body0Wrap, body1Wrap, dispatchInfo, resultOut);
btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
btQuaternion rotq(planeNormal,iterationAngle);
collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0Wrap,body1Wrap,dispatchInfo,resultOut);
}
}
@@ -160,7 +162,7 @@ void btConvexPlaneCollisionAlgorithm::processCollision(const btCollisionObjectWr
}
}
btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;

View File

@@ -28,24 +28,25 @@ class btPersistentManifold;
/// Other features are frame-coherency (persistent data) and collision response.
class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
public:
btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold);
virtual ~btConvexPlaneCollisionAlgorithm();
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
void collideSingleContact(const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
void collideSingleContact (const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
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)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
@@ -53,30 +54,31 @@ public:
}
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
int m_numPerturbationIterations;
int m_numPerturbationIterations;
int m_minimumPointsPerturbationThreshold;
CreateFunc()
CreateFunc()
: m_numPerturbationIterations(1),
m_minimumPointsPerturbationThreshold(0)
m_minimumPointsPerturbationThreshold(0)
{
}
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
if (!m_swapped)
{
return new (mem) btConvexPlaneCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
}
else
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
} else
{
return new (mem) btConvexPlaneCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
}
}
};
};
#endif //BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
#endif //BT_CONVEX_PLANE_COLLISION_ALGORITHM_H

View File

@@ -26,108 +26,115 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "LinearMath/btPoolAllocator.h"
btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool)
{
void* mem = NULL;
void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16);
m_simplexSolver = new (mem)btVoronoiSimplexSolver();
if (constructionInfo.m_useEpaPenetrationAlgorithm)
{
mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver), 16);
m_pdSolver = new (mem) btGjkEpaPenetrationDepthSolver;
}
else
mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16);
m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver;
}else
{
mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver), 16);
m_pdSolver = new (mem) btMinkowskiPenetrationDepthSolver;
mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16);
m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver;
}
//default CreationFunctions, filling the m_doubleDispatch table
mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc), 16);
m_convexConvexCreateFunc = new (mem) btConvexConvexAlgorithm::CreateFunc(m_pdSolver);
mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc), 16);
m_convexConcaveCreateFunc = new (mem) btConvexConcaveCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc), 16);
m_swappedConvexConcaveCreateFunc = new (mem) btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc), 16);
m_compoundCreateFunc = new (mem) btCompoundCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16);
m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver);
mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16);
m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btCompoundCompoundCollisionAlgorithm::CreateFunc), 16);
m_compoundCompoundCreateFunc = new (mem) btCompoundCompoundCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btCompoundCompoundCollisionAlgorithm::CreateFunc),16);
m_compoundCompoundCreateFunc = new (mem)btCompoundCompoundCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc), 16);
m_swappedCompoundCreateFunc = new (mem) btCompoundCollisionAlgorithm::SwappedCreateFunc;
mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc), 16);
m_emptyCreateFunc = new (mem) btEmptyAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc), 16);
m_sphereSphereCF = new (mem) btSphereSphereCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16);
m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc;
mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16);
m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16);
m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc;
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc), 16);
m_sphereBoxCF = new (mem) btSphereBoxCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc), 16);
m_boxSphereCF = new (mem) btSphereBoxCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc;
m_boxSphereCF->m_swapped = true;
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc), 16);
m_sphereTriangleCF = new (mem) btSphereTriangleCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc), 16);
m_triangleSphereCF = new (mem) btSphereTriangleCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
m_triangleSphereCF->m_swapped = true;
mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc), 16);
m_boxBoxCF = new (mem) btBoxBoxCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16);
m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc;
//convex versus plane
mem = btAlignedAlloc(sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc), 16);
mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc), 16);
mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
m_planeConvexCF->m_swapped = true;
///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
int maxSize = sizeof(btConvexConvexAlgorithm);
int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
int maxSize3 = sizeof(btCompoundCollisionAlgorithm);
int maxSize4 = sizeof(btCompoundCompoundCollisionAlgorithm);
int collisionAlgorithmMaxElementSize = btMax(maxSize, constructionInfo.m_customCollisionAlgorithmMaxElementSize);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize2);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize3);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize4);
int collisionAlgorithmMaxElementSize = btMax(maxSize,constructionInfo.m_customCollisionAlgorithmMaxElementSize);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3);
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4);
if (constructionInfo.m_persistentManifoldPool)
{
m_ownsPersistentManifoldPool = false;
m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool;
}
else
} else
{
m_ownsPersistentManifoldPool = true;
void* mem = btAlignedAlloc(sizeof(btPoolAllocator), 16);
m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold), constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
}
collisionAlgorithmMaxElementSize = (collisionAlgorithmMaxElementSize + 16) & 0xffffffffffff0;
if (constructionInfo.m_collisionAlgorithmPool)
{
m_ownsCollisionAlgorithmPool = false;
m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool;
}
else
} else
{
m_ownsCollisionAlgorithmPool = true;
void* mem = btAlignedAlloc(sizeof(btPoolAllocator), 16);
m_collisionAlgorithmPool = new (mem) btPoolAllocator(collisionAlgorithmMaxElementSize, constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
}
}
btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
@@ -144,159 +151,95 @@ btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
}
m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_convexConvexCreateFunc);
btAlignedFree( m_convexConvexCreateFunc);
m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_convexConcaveCreateFunc);
btAlignedFree( m_convexConcaveCreateFunc);
m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_swappedConvexConcaveCreateFunc);
btAlignedFree( m_swappedConvexConcaveCreateFunc);
m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_compoundCreateFunc);
btAlignedFree( m_compoundCreateFunc);
m_compoundCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_compoundCompoundCreateFunc);
m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_swappedCompoundCreateFunc);
btAlignedFree( m_swappedCompoundCreateFunc);
m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_emptyCreateFunc);
btAlignedFree( m_emptyCreateFunc);
m_sphereSphereCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_sphereSphereCF);
btAlignedFree( m_sphereSphereCF);
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
m_sphereBoxCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_sphereBoxCF);
btAlignedFree( m_sphereBoxCF);
m_boxSphereCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_boxSphereCF);
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
btAlignedFree( m_boxSphereCF);
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_sphereTriangleCF);
btAlignedFree( m_sphereTriangleCF);
m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_triangleSphereCF);
btAlignedFree( m_triangleSphereCF);
m_boxBoxCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_boxBoxCF);
btAlignedFree( m_boxBoxCF);
m_convexPlaneCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_convexPlaneCF);
btAlignedFree( m_convexPlaneCF);
m_planeConvexCF->~btCollisionAlgorithmCreateFunc();
btAlignedFree(m_planeConvexCF);
btAlignedFree( m_planeConvexCF);
m_simplexSolver->~btVoronoiSimplexSolver();
btAlignedFree(m_simplexSolver);
m_pdSolver->~btConvexPenetrationDepthSolver();
btAlignedFree(m_pdSolver);
}
btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1)
btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
{
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
{
return m_sphereSphereCF;
return m_sphereSphereCF;
}
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE))
{
return m_sphereBoxCF;
return m_sphereBoxCF;
}
if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
{
return m_boxSphereCF;
return m_boxSphereCF;
}
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE))
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE))
{
return m_sphereTriangleCF;
return m_sphereTriangleCF;
}
if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
{
return m_triangleSphereCF;
}
if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
{
return m_convexPlaneCF;
}
if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE))
{
return m_planeConvexCF;
}
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) && btBroadphaseProxy::isCompound(proxyType1))
{
return m_compoundCompoundCreateFunc;
}
if (btBroadphaseProxy::isCompound(proxyType0))
{
return m_compoundCreateFunc;
}
else
{
if (btBroadphaseProxy::isCompound(proxyType1))
{
return m_swappedCompoundCreateFunc;
}
}
//failed to find an algorithm
return m_emptyCreateFunc;
}
btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1)
{
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
{
return m_sphereSphereCF;
}
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
{
return m_sphereBoxCF;
}
if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
{
return m_boxSphereCF;
}
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE))
{
return m_sphereTriangleCF;
}
if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
{
return m_triangleSphereCF;
}
return m_triangleSphereCF;
}
if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
{
return m_boxBoxCF;
}
if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
{
return m_convexPlaneCF;
@@ -306,6 +249,8 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
{
return m_planeConvexCF;
}
if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
{
@@ -322,6 +267,7 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
return m_swappedConvexConcaveCreateFunc;
}
if (btBroadphaseProxy::isCompound(proxyType0) && btBroadphaseProxy::isCompound(proxyType1))
{
return m_compoundCompoundCreateFunc;
@@ -330,8 +276,7 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
if (btBroadphaseProxy::isCompound(proxyType0))
{
return m_compoundCreateFunc;
}
else
} else
{
if (btBroadphaseProxy::isCompound(proxyType1))
{
@@ -345,17 +290,17 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg
void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
{
btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*)m_convexConvexCreateFunc;
btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*) m_convexConvexCreateFunc;
convexConvex->m_numPerturbationIterations = numPerturbationIterations;
convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
}
void btDefaultCollisionConfiguration::setPlaneConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
void btDefaultCollisionConfiguration::setPlaneConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
{
btConvexPlaneCollisionAlgorithm::CreateFunc* cpCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_convexPlaneCF;
cpCF->m_numPerturbationIterations = numPerturbationIterations;
cpCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
btConvexPlaneCollisionAlgorithm::CreateFunc* pcCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_planeConvexCF;
pcCF->m_numPerturbationIterations = numPerturbationIterations;
pcCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;

View File

@@ -20,68 +20,77 @@ subject to the following restrictions:
class btVoronoiSimplexSolver;
class btConvexPenetrationDepthSolver;
struct btDefaultCollisionConstructionInfo
struct btDefaultCollisionConstructionInfo
{
btPoolAllocator* m_persistentManifoldPool;
btPoolAllocator* m_collisionAlgorithmPool;
int m_defaultMaxPersistentManifoldPoolSize;
int m_defaultMaxCollisionAlgorithmPoolSize;
int m_customCollisionAlgorithmMaxElementSize;
int m_useEpaPenetrationAlgorithm;
btPoolAllocator* m_persistentManifoldPool;
btPoolAllocator* m_collisionAlgorithmPool;
int m_defaultMaxPersistentManifoldPoolSize;
int m_defaultMaxCollisionAlgorithmPoolSize;
int m_customCollisionAlgorithmMaxElementSize;
int m_useEpaPenetrationAlgorithm;
btDefaultCollisionConstructionInfo()
: m_persistentManifoldPool(0),
m_collisionAlgorithmPool(0),
m_defaultMaxPersistentManifoldPoolSize(4096),
m_defaultMaxCollisionAlgorithmPoolSize(4096),
m_customCollisionAlgorithmMaxElementSize(0),
m_useEpaPenetrationAlgorithm(true)
:m_persistentManifoldPool(0),
m_collisionAlgorithmPool(0),
m_defaultMaxPersistentManifoldPoolSize(4096),
m_defaultMaxCollisionAlgorithmPoolSize(4096),
m_customCollisionAlgorithmMaxElementSize(0),
m_useEpaPenetrationAlgorithm(true)
{
}
};
///btCollisionConfiguration allows to configure Bullet collision detection
///stack allocator, pool memory allocators
///@todo: describe the meaning
class btDefaultCollisionConfiguration : public btCollisionConfiguration
class btDefaultCollisionConfiguration : public btCollisionConfiguration
{
protected:
int m_persistentManifoldPoolSize;
btPoolAllocator* m_persistentManifoldPool;
bool m_ownsPersistentManifoldPool;
int m_persistentManifoldPoolSize;
btPoolAllocator* m_collisionAlgorithmPool;
bool m_ownsCollisionAlgorithmPool;
btPoolAllocator* m_persistentManifoldPool;
bool m_ownsPersistentManifoldPool;
//default penetration depth solver
btConvexPenetrationDepthSolver* m_pdSolver;
btPoolAllocator* m_collisionAlgorithmPool;
bool m_ownsCollisionAlgorithmPool;
//default simplex/penetration depth solvers
btVoronoiSimplexSolver* m_simplexSolver;
btConvexPenetrationDepthSolver* m_pdSolver;
//default CreationFunctions, filling the m_doubleDispatch table
btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_compoundCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_compoundCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
btCollisionAlgorithmCreateFunc* m_boxSphereCF;
btCollisionAlgorithmCreateFunc* m_boxBoxCF;
btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
btCollisionAlgorithmCreateFunc* m_planeConvexCF;
btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
btCollisionAlgorithmCreateFunc* m_planeConvexCF;
btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
public:
btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
virtual ~btDefaultCollisionConfiguration();
///memory pools
///memory pools
virtual btPoolAllocator* getPersistentManifoldPool()
{
return m_persistentManifoldPool;
@@ -92,9 +101,14 @@ public:
return m_collisionAlgorithmPool;
}
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1);
virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1);
virtual btVoronoiSimplexSolver* getSimplexSolver()
{
return m_simplexSolver;
}
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm.
///By default, this feature is disabled for best performance.
@@ -103,9 +117,11 @@ public:
///3 is a good value for both params, if you want to enable the feature. This is because the default contact cache contains a maximum of 4 points, and one collision query at the unperturbed orientation is performed first.
///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points.
///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection.
void setConvexConvexMultipointIterations(int numPerturbationIterations = 3, int minimumPointsPerturbationThreshold = 3);
void setConvexConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3);
void setPlaneConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3);
void setPlaneConvexMultipointIterations(int numPerturbationIterations = 3, int minimumPointsPerturbationThreshold = 3);
};
#endif //BT_DEFAULT_COLLISION_CONFIGURATION
#endif //BT_DEFAULT_COLLISION_CONFIGURATION

View File

@@ -15,16 +15,20 @@ subject to the following restrictions:
#include "btEmptyCollisionAlgorithm.h"
btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btCollisionAlgorithm(ci)
{
}
void btEmptyAlgorithm::processCollision(const btCollisionObjectWrapper*, const btCollisionObjectWrapper*, const btDispatcherInfo&, btManifoldResult*)
void btEmptyAlgorithm::processCollision (const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* ,const btDispatcherInfo& ,btManifoldResult* )
{
}
btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject*, btCollisionObject*, const btDispatcherInfo&, btManifoldResult*)
btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* )
{
return btScalar(1.);
}

View File

@@ -25,28 +25,30 @@ subject to the following restrictions:
///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame.
class btEmptyAlgorithm : public btCollisionAlgorithm
{
public:
btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
}
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
(void)body0Wrap;
(void)body1Wrap;
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
return new (mem) btEmptyAlgorithm(ci);
return new(mem) btEmptyAlgorithm(ci);
}
};
} ATTRIBUTE_ALIGNED(16);
#endif //BT_EMPTY_ALGORITH
#endif //BT_EMPTY_ALGORITH

View File

@@ -29,58 +29,60 @@ btGhostObject::~btGhostObject()
btAssert(!m_overlappingObjects.size());
}
void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy)
void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index == m_overlappingObjects.size())
if (index==m_overlappingObjects.size())
{
//not found
m_overlappingObjects.push_back(otherObject);
}
}
void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy)
void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index < m_overlappingObjects.size())
if (index<m_overlappingObjects.size())
{
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
m_overlappingObjects.pop_back();
}
}
btPairCachingGhostObject::btPairCachingGhostObject()
{
m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16)) btHashedOverlappingPairCache();
m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
}
btPairCachingGhostObject::~btPairCachingGhostObject()
{
m_hashPairCache->~btHashedOverlappingPairCache();
btAlignedFree(m_hashPairCache);
btAlignedFree( m_hashPairCache );
}
void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy)
void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
{
btBroadphaseProxy* actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
btAssert(actualThisProxy);
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index == m_overlappingObjects.size())
if (index==m_overlappingObjects.size())
{
m_overlappingObjects.push_back(otherObject);
m_hashPairCache->addOverlappingPair(actualThisProxy, otherProxy);
m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy);
}
}
void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy1)
void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1)
{
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle();
@@ -88,79 +90,82 @@ void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy
btAssert(otherObject);
int index = m_overlappingObjects.findLinearSearch(otherObject);
if (index < m_overlappingObjects.size())
if (index<m_overlappingObjects.size())
{
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
m_overlappingObjects.pop_back();
m_hashPairCache->removeOverlappingPair(actualThisProxy, otherProxy, dispatcher);
m_hashPairCache->removeOverlappingPair(actualThisProxy,otherProxy,dispatcher);
}
}
void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
{
btTransform convexFromTrans, convexToTrans;
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);
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);
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_overlappingObjects.size(); i++)
for (i=0;i<m_overlappingObjects.size();i++)
{
btCollisionObject* collisionObject = m_overlappingObjects[i];
btCollisionObject* collisionObject= m_overlappingObjects[i];
//only perform raycast if filterMask matches
if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
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 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))
if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
{
btCollisionWorld::objectQuerySingle(castShape, convexFromTrans, convexToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback,
allowedCcdPenetration);
btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback,
allowedCcdPenetration);
}
}
}
}
void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
{
btTransform rayFromTrans;
rayFromTrans.setIdentity();
rayFromTrans.setOrigin(rayFromWorld);
btTransform rayToTrans;
btTransform rayToTrans;
rayToTrans.setIdentity();
rayToTrans.setOrigin(rayToWorld);
int i;
for (i = 0; i < m_overlappingObjects.size(); i++)
for (i=0;i<m_overlappingObjects.size();i++)
{
btCollisionObject* collisionObject = m_overlappingObjects[i];
btCollisionObject* collisionObject= m_overlappingObjects[i];
//only perform raycast if filterMask matches
if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback);
btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
resultCallback);
}
}
}

View File

@@ -16,6 +16,7 @@ subject to the following restrictions:
#ifndef BT_GHOST_OBJECT_H
#define BT_GHOST_OBJECT_H
#include "btCollisionObject.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
#include "LinearMath/btAlignedAllocator.h"
@@ -30,47 +31,48 @@ class btDispatcher;
///By default, this overlap is based on the AABB
///This is useful for creating a character controller, collision sensors/triggers, explosions etc.
///We plan on adding rayTest and other queries for the btGhostObject
ATTRIBUTE_ALIGNED16(class)
btGhostObject : public btCollisionObject
ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject
{
protected:
btAlignedObjectArray<btCollisionObject*> m_overlappingObjects;
public:
btGhostObject();
virtual ~btGhostObject();
void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
///this method is mainly for expert/internal use only.
virtual void addOverlappingObjectInternal(btBroadphaseProxy * otherProxy, btBroadphaseProxy* thisProxy = 0);
virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
///this method is mainly for expert/internal use only.
virtual void removeOverlappingObjectInternal(btBroadphaseProxy * otherProxy, btDispatcher * dispatcher, btBroadphaseProxy* thisProxy = 0);
virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
int getNumOverlappingObjects() const
int getNumOverlappingObjects() const
{
return m_overlappingObjects.size();
}
btCollisionObject* getOverlappingObject(int index)
btCollisionObject* getOverlappingObject(int index)
{
return m_overlappingObjects[index];
}
const btCollisionObject* getOverlappingObject(int index) const
const btCollisionObject* getOverlappingObject(int index) const
{
return m_overlappingObjects[index];
}
btAlignedObjectArray<btCollisionObject*>& getOverlappingPairs()
btAlignedObjectArray<btCollisionObject*>& getOverlappingPairs()
{
return m_overlappingObjects;
}
const btAlignedObjectArray<btCollisionObject*> getOverlappingPairs() const
const btAlignedObjectArray<btCollisionObject*> getOverlappingPairs() const
{
return m_overlappingObjects;
}
@@ -79,43 +81,49 @@ public:
// internal cast
//
static const btGhostObject* upcast(const btCollisionObject* colObj)
static const btGhostObject* upcast(const btCollisionObject* colObj)
{
if (colObj->getInternalType() == CO_GHOST_OBJECT)
if (colObj->getInternalType()==CO_GHOST_OBJECT)
return (const btGhostObject*)colObj;
return 0;
}
static btGhostObject* upcast(btCollisionObject * colObj)
static btGhostObject* upcast(btCollisionObject* colObj)
{
if (colObj->getInternalType() == CO_GHOST_OBJECT)
if (colObj->getInternalType()==CO_GHOST_OBJECT)
return (btGhostObject*)colObj;
return 0;
}
};
class btPairCachingGhostObject : public btGhostObject
class btPairCachingGhostObject : public btGhostObject
{
btHashedOverlappingPairCache* m_hashPairCache;
btHashedOverlappingPairCache* m_hashPairCache;
public:
btPairCachingGhostObject();
virtual ~btPairCachingGhostObject();
///this method is mainly for expert/internal use only.
virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy = 0);
virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy = 0);
virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
btHashedOverlappingPairCache* getOverlappingPairCache()
btHashedOverlappingPairCache* getOverlappingPairCache()
{
return m_hashPairCache;
}
};
///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject.
class btGhostPairCallback : public btOverlappingPairCallback
{
public:
btGhostPairCallback()
{
@@ -123,14 +131,15 @@ public:
virtual ~btGhostPairCallback()
{
}
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
btCollisionObject* colObj0 = (btCollisionObject*)proxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)proxy1->m_clientObject;
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
if (ghost0)
ghost0->addOverlappingObjectInternal(proxy1, proxy0);
if (ghost1)
@@ -138,25 +147,29 @@ public:
return 0;
}
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
{
btCollisionObject* colObj0 = (btCollisionObject*)proxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)proxy1->m_clientObject;
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
if (ghost0)
ghost0->removeOverlappingObjectInternal(proxy1, dispatcher, proxy0);
ghost0->removeOverlappingObjectInternal(proxy1,dispatcher,proxy0);
if (ghost1)
ghost1->removeOverlappingObjectInternal(proxy0, dispatcher, proxy1);
ghost1->removeOverlappingObjectInternal(proxy0,dispatcher,proxy1);
return 0;
}
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/, btDispatcher* /*dispatcher*/)
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
{
btAssert(0);
//need to keep track of all ghost objects and call them here
//m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
}
};
#endif

View File

@@ -13,49 +13,61 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btHashedSimplePairCache.h"
#include <stdio.h>
#ifdef BT_DEBUG_COLLISION_PAIRS
int gOverlappingSimplePairs = 0;
int gRemoveSimplePairs = 0;
int gAddedSimplePairs = 0;
int gFindSimplePairs = 0;
#endif //BT_DEBUG_COLLISION_PAIRS
int gOverlappingSimplePairs = 0;
int gRemoveSimplePairs =0;
int gAddedSimplePairs =0;
int gFindSimplePairs =0;
btHashedSimplePairCache::btHashedSimplePairCache()
{
int initialAllocatedSize = 2;
btHashedSimplePairCache::btHashedSimplePairCache() {
int initialAllocatedSize= 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
growTables();
}
btHashedSimplePairCache::~btHashedSimplePairCache()
{
}
void btHashedSimplePairCache::removeAllPairs()
{
m_overlappingPairArray.clear();
m_hashTable.clear();
m_next.clear();
int initialAllocatedSize = 2;
int initialAllocatedSize= 2;
m_overlappingPairArray.reserve(initialAllocatedSize);
growTables();
}
btSimplePair* btHashedSimplePairCache::findPair(int indexA, int indexB)
{
#ifdef BT_DEBUG_COLLISION_PAIRS
gFindSimplePairs++;
#endif
/*if (indexA > indexB)
btSwap(indexA, indexB);*/
int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1));
if (hash >= m_hashTable.size())
{
@@ -80,8 +92,9 @@ btSimplePair* btHashedSimplePairCache::findPair(int indexA, int indexB)
//#include <stdio.h>
void btHashedSimplePairCache::growTables()
void btHashedSimplePairCache::growTables()
{
int newCapacity = m_overlappingPairArray.capacity();
if (m_hashTable.size() < newCapacity)
@@ -92,9 +105,10 @@ void btHashedSimplePairCache::growTables()
m_hashTable.resize(newCapacity);
m_next.resize(newCapacity);
int i;
for (i = 0; i < newCapacity; ++i)
for (i= 0; i < newCapacity; ++i)
{
m_hashTable[i] = BT_SIMPLE_NULL_PAIR;
}
@@ -103,22 +117,27 @@ void btHashedSimplePairCache::growTables()
m_next[i] = BT_SIMPLE_NULL_PAIR;
}
for (i = 0; i < curHashtableSize; i++)
for(i=0;i<curHashtableSize;i++)
{
const btSimplePair& pair = m_overlappingPairArray[i];
int indexA = pair.m_indexA;
int indexB = pair.m_indexB;
int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
m_next[i] = m_hashTable[hashValue];
m_hashTable[hashValue] = i;
}
}
}
btSimplePair* btHashedSimplePairCache::internalAddPair(int indexA, int indexB)
{
int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
btSimplePair* pair = internalFindPair(indexA, indexB, hash);
if (pair != NULL)
@@ -136,29 +155,30 @@ btSimplePair* btHashedSimplePairCache::internalAddPair(int indexA, int indexB)
{
growTables();
//hash with new capacity
hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1));
}
pair = new (mem) btSimplePair(indexA, indexB);
pair = new (mem) btSimplePair(indexA,indexB);
pair->m_userPointer = 0;
m_next[count] = m_hashTable[hash];
m_hashTable[hash] = count;
return pair;
}
void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
{
#ifdef BT_DEBUG_COLLISION_PAIRS
gRemoveSimplePairs++;
#endif
/*if (indexA > indexB)
btSwap(indexA, indexB);*/
int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA),static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity()-1));
btSimplePair* pair = internalFindPair(indexA, indexB, hash);
if (pair == NULL)
@@ -166,8 +186,10 @@ void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
return 0;
}
void* userData = pair->m_userPointer;
int pairIndex = int(pair - &m_overlappingPairArray[0]);
btAssert(pairIndex < m_overlappingPairArray.size());
@@ -207,8 +229,8 @@ void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
// Remove the last pair from the hash table.
const btSimplePair* last = &m_overlappingPairArray[lastPairIndex];
/* missing swap here too, Nat. */
int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_indexA), static_cast<unsigned int>(last->m_indexB)) & (m_overlappingPairArray.capacity() - 1));
/* missing swap here too, Nat. */
int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_indexA), static_cast<unsigned int>(last->m_indexB)) & (m_overlappingPairArray.capacity()-1));
index = m_hashTable[lastHash];
btAssert(index != BT_SIMPLE_NULL_PAIR);
@@ -242,3 +264,13 @@ void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
return userData;
}
//#include <stdio.h>

View File

@@ -16,126 +16,142 @@ subject to the following restrictions:
#ifndef BT_HASHED_SIMPLE_PAIR_CACHE_H
#define BT_HASHED_SIMPLE_PAIR_CACHE_H
#include "LinearMath/btAlignedObjectArray.h"
const int BT_SIMPLE_NULL_PAIR = 0xffffffff;
const int BT_SIMPLE_NULL_PAIR=0xffffffff;
struct btSimplePair
{
btSimplePair(int indexA, int indexB)
: m_indexA(indexA),
m_indexB(indexB),
m_userPointer(0)
btSimplePair(int indexA,int indexB)
:m_indexA(indexA),
m_indexB(indexB),
m_userPointer(0)
{
}
int m_indexA;
int m_indexB;
union {
void* m_userPointer;
int m_userValue;
union
{
void* m_userPointer;
int m_userValue;
};
};
typedef btAlignedObjectArray<btSimplePair> btSimplePairArray;
typedef btAlignedObjectArray<btSimplePair> btSimplePairArray;
#ifdef BT_DEBUG_COLLISION_PAIRS
extern int gOverlappingSimplePairs;
extern int gRemoveSimplePairs;
extern int gAddedSimplePairs;
extern int gFindSimplePairs;
#endif //BT_DEBUG_COLLISION_PAIRS
class btHashedSimplePairCache
{
btSimplePairArray m_overlappingPairArray;
btSimplePairArray m_overlappingPairArray;
protected:
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
public:
btHashedSimplePairCache();
virtual ~btHashedSimplePairCache();
void removeAllPairs();
virtual void* removeOverlappingPair(int indexA, int indexB);
virtual void* removeOverlappingPair(int indexA,int indexB);
// 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 btSimplePair* addOverlappingPair(int indexA, int indexB)
virtual btSimplePair* addOverlappingPair(int indexA,int indexB)
{
#ifdef BT_DEBUG_COLLISION_PAIRS
gAddedSimplePairs++;
#endif
return internalAddPair(indexA, indexB);
return internalAddPair(indexA,indexB);
}
virtual btSimplePair* getOverlappingPairArrayPtr()
virtual btSimplePair* getOverlappingPairArrayPtr()
{
return &m_overlappingPairArray[0];
}
const btSimplePair* getOverlappingPairArrayPtr() const
const btSimplePair* getOverlappingPairArrayPtr() const
{
return &m_overlappingPairArray[0];
}
btSimplePairArray& getOverlappingPairArray()
btSimplePairArray& getOverlappingPairArray()
{
return m_overlappingPairArray;
}
const btSimplePairArray& getOverlappingPairArray() const
const btSimplePairArray& getOverlappingPairArray() const
{
return m_overlappingPairArray;
}
btSimplePair* findPair(int indexA, int indexB);
btSimplePair* findPair(int indexA,int indexB);
int GetCount() const { return m_overlappingPairArray.size(); }
int getNumOverlappingPairs() const
int getNumOverlappingPairs() const
{
return m_overlappingPairArray.size();
}
private:
btSimplePair* internalAddPair(int indexA, int indexB);
btSimplePair* internalAddPair(int indexA, int indexB);
void growTables();
void growTables();
SIMD_FORCE_INLINE bool equalsPair(const btSimplePair& pair, int indexA, int indexB)
{
{
return pair.m_indexA == indexA && pair.m_indexB == indexB;
}
SIMD_FORCE_INLINE unsigned int getHash(unsigned int indexA, unsigned int indexB)
SIMD_FORCE_INLINE unsigned int getHash(unsigned int indexA, unsigned int indexB)
{
unsigned int key = indexA | (indexB << 16);
int key = static_cast<int>(((unsigned int)indexA) | (((unsigned int)indexB) <<16));
// Thomas Wang's hash
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
key ^= (key >> 16);
return static_cast<unsigned int>(key);
}
SIMD_FORCE_INLINE btSimplePair* internalFindPair(int proxyIdA, int proxyIdB, int hash)
SIMD_FORCE_INLINE btSimplePair* internalFindPair(int proxyIdA , int proxyIdB, int hash)
{
int index = m_hashTable[hash];
while (index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyIdA, proxyIdB) == false)
while( index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyIdA, proxyIdB) == false)
{
index = m_next[index];
}
if (index == BT_SIMPLE_NULL_PAIR)
if ( index == BT_SIMPLE_NULL_PAIR )
{
return NULL;
}
@@ -144,6 +160,13 @@ private:
return &m_overlappingPairArray[index];
}
};
#endif //BT_HASHED_SIMPLE_PAIR_CACHE_H
#endif //BT_HASHED_SIMPLE_PAIR_CACHE_H

View File

@@ -15,30 +15,33 @@ class btCollisionObject;
struct btCollisionObjectWrapper;
class btManifoldPoint;
class btIDebugDraw;
class btHeightfieldTerrainShape;
enum btInternalEdgeAdjustFlags
{
BT_TRIANGLE_CONVEX_BACKFACE_MODE = 1,
BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended
BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended
BT_TRIANGLE_CONVEX_DOUBLE_SIDED = 4
};
///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap);
///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo)
///If this info map is missing, or the triangle is not store in this map, nothing will be done
void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap, const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap,const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly.
///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap
//#define BT_INTERNAL_EDGE_DEBUG_DRAW
#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
void btSetDebugDrawer(btIDebugDraw* debugDrawer);
#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
void btSetDebugDrawer(btIDebugDraw* debugDrawer);
#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
#endif //BT_INTERNAL_EDGE_UTILITY_H
#endif //BT_INTERNAL_EDGE_UTILITY_H

View File

@@ -13,191 +13,142 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btManifoldResult.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
///This is to allow MaterialCombiner/Custom Friction/Restitution values
ContactAddedCallback gContactAddedCallback = 0;
ContactAddedCallback gContactAddedCallback=0;
CalculateCombinedCallback gCalculateCombinedRestitutionCallback = &btManifoldResult::calculateCombinedRestitution;
CalculateCombinedCallback gCalculateCombinedFrictionCallback = &btManifoldResult::calculateCombinedFriction;
CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback = &btManifoldResult::calculateCombinedRollingFriction;
CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback = &btManifoldResult::calculateCombinedSpinningFriction;
CalculateCombinedCallback gCalculateCombinedContactDampingCallback = &btManifoldResult::calculateCombinedContactDamping;
CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback = &btManifoldResult::calculateCombinedContactStiffness;
btScalar btManifoldResult::calculateCombinedRollingFriction(const btCollisionObject* body0, const btCollisionObject* body1)
{
btScalar friction = body0->getRollingFriction() * body1->getFriction() + body1->getRollingFriction() * body0->getFriction();
const btScalar MAX_FRICTION = btScalar(10.);
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;
}
btScalar btManifoldResult::calculateCombinedSpinningFriction(const btCollisionObject* body0, const btCollisionObject* body1)
{
btScalar friction = body0->getSpinningFriction() * body1->getFriction() + body1->getSpinningFriction() * body0->getFriction();
const btScalar MAX_FRICTION = btScalar(10.);
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;
}
///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
btScalar btManifoldResult::calculateCombinedFriction(const btCollisionObject* body0, const btCollisionObject* body1)
inline btScalar calculateCombinedRollingFriction(const btCollisionObject* body0,const btCollisionObject* body1)
{
btScalar friction = body0->getRollingFriction() * body1->getRollingFriction();
const btScalar MAX_FRICTION = btScalar(10.);
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;
}
///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
btScalar btManifoldResult::calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1)
{
btScalar friction = body0->getFriction() * body1->getFriction();
const btScalar MAX_FRICTION = btScalar(10.);
const btScalar MAX_FRICTION = btScalar(10.);
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;
}
btScalar btManifoldResult::calculateCombinedRestitution(const btCollisionObject* body0, const btCollisionObject* body1)
btScalar btManifoldResult::calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1)
{
return body0->getRestitution() * body1->getRestitution();
}
btScalar btManifoldResult::calculateCombinedContactDamping(const btCollisionObject* body0, const btCollisionObject* body1)
{
return body0->getContactDamping() + body1->getContactDamping();
}
btScalar btManifoldResult::calculateCombinedContactStiffness(const btCollisionObject* body0, const btCollisionObject* body1)
{
btScalar s0 = body0->getContactStiffness();
btScalar s1 = body1->getContactStiffness();
btScalar tmp0 = btScalar(1) / s0;
btScalar tmp1 = btScalar(1) / s1;
btScalar combinedStiffness = btScalar(1) / (tmp0 + tmp1);
return combinedStiffness;
}
btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
: m_manifoldPtr(0),
m_body0Wrap(body0Wrap),
m_body1Wrap(body1Wrap)
btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
:m_manifoldPtr(0),
m_body0Wrap(body0Wrap),
m_body1Wrap(body1Wrap)
#ifdef DEBUG_PART_INDEX
,
m_partId0(-1),
m_partId1(-1),
m_index0(-1),
m_index1(-1)
#endif //DEBUG_PART_INDEX
,
m_closestPointDistanceThreshold(0)
,m_partId0(-1),
m_partId1(-1),
m_index0(-1),
m_index1(-1)
#endif //DEBUG_PART_INDEX
{
}
void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
{
btAssert(m_manifoldPtr);
//order in manifold needs to match
if (depth > m_manifoldPtr->getContactBreakingThreshold())
// if (depth > m_manifoldPtr->getContactProcessingThreshold())
// if (depth > m_manifoldPtr->getContactProcessingThreshold())
return;
bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
bool isNewCollision = m_manifoldPtr->getNumContacts() == 0;
btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
btVector3 localA;
btVector3 localB;
if (isSwapped)
{
localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
}
else
} else
{
localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
}
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);
newPt.m_combinedFriction = gCalculateCombinedFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
newPt.m_combinedRestitution = gCalculateCombinedRestitutionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
newPt.m_combinedRollingFriction = gCalculateCombinedRollingFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
newPt.m_combinedSpinningFriction = gCalculateCombinedSpinningFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
newPt.m_combinedFriction = calculateCombinedFriction(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
newPt.m_combinedRollingFriction = calculateCombinedRollingFriction(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
btPlaneSpace1(newPt.m_normalWorldOnB,newPt.m_lateralFrictionDir1,newPt.m_lateralFrictionDir2);
if ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING) ||
(m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING))
{
newPt.m_combinedContactDamping1 = gCalculateCombinedContactDampingCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
newPt.m_combinedContactStiffness1 = gCalculateCombinedContactStiffnessCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
newPt.m_contactPointFlags |= BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING;
}
if ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_FRICTION_ANCHOR) ||
(m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_FRICTION_ANCHOR))
{
newPt.m_contactPointFlags |= BT_CONTACT_FLAG_FRICTION_ANCHOR;
}
btPlaneSpace1(newPt.m_normalWorldOnB, newPt.m_lateralFrictionDir1, newPt.m_lateralFrictionDir2);
//BP mod, store contact triangles.
//BP mod, store contact triangles.
if (isSwapped)
{
newPt.m_partId0 = m_partId1;
newPt.m_partId1 = m_partId0;
newPt.m_index0 = m_index1;
newPt.m_index1 = m_index0;
}
else
newPt.m_index0 = m_index1;
newPt.m_index1 = m_index0;
} else
{
newPt.m_partId0 = m_partId0;
newPt.m_partId1 = m_partId1;
newPt.m_index0 = m_index0;
newPt.m_index1 = m_index1;
newPt.m_index0 = m_index0;
newPt.m_index1 = m_index1;
}
//printf("depth=%f\n",depth);
///@todo, check this for any side effects
if (insertIndex >= 0)
{
//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
m_manifoldPtr->replaceContactPoint(newPt, insertIndex);
}
else
m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
} else
{
insertIndex = m_manifoldPtr->addManifoldPoint(newPt);
}
//User can override friction and/or restitution
if (gContactAddedCallback &&
//and if either of the two bodies requires custom material
((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
(m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
(m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
{
//experimental feature info, for per-triangle material etc.
const btCollisionObjectWrapper* obj0Wrap = isSwapped ? m_body1Wrap : m_body0Wrap;
const btCollisionObjectWrapper* obj1Wrap = isSwapped ? m_body0Wrap : m_body1Wrap;
(*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex), obj0Wrap, newPt.m_partId0, newPt.m_index0, obj1Wrap, newPt.m_partId1, newPt.m_index1);
const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap;
const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap;
(*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1);
}
if (gContactStartedCallback && isNewCollision)
{
gContactStartedCallback(m_manifoldPtr);
}
}

View File

@@ -13,6 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_MANIFOLD_RESULT_H
#define BT_MANIFOLD_RESULT_H
@@ -28,81 +29,74 @@ class btManifoldPoint;
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1);
extern ContactAddedCallback gContactAddedCallback;
typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1);
extern ContactAddedCallback gContactAddedCallback;
//#define DEBUG_PART_INDEX 1
/// These callbacks are used to customize the algorith that combine restitution, friction, damping, Stiffness
typedef btScalar (*CalculateCombinedCallback)(const btCollisionObject* body0, const btCollisionObject* body1);
extern CalculateCombinedCallback gCalculateCombinedRestitutionCallback;
extern CalculateCombinedCallback gCalculateCombinedFrictionCallback;
extern CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback;
extern CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback;
extern CalculateCombinedCallback gCalculateCombinedContactDampingCallback;
extern CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback;
///btManifoldResult is a helper class to manage contact results.
class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result
{
protected:
btPersistentManifold* m_manifoldPtr;
const btCollisionObjectWrapper* m_body0Wrap;
const btCollisionObjectWrapper* m_body1Wrap;
int m_partId0;
int m_partId0;
int m_partId1;
int m_index0;
int m_index1;
public:
btManifoldResult()
:
#ifdef DEBUG_PART_INDEX
m_partId0(-1),
m_partId1(-1),
m_index0(-1),
m_index1(-1)
#endif //DEBUG_PART_INDEX
m_closestPointDistanceThreshold(0)
btManifoldResult()
#ifdef DEBUG_PART_INDEX
:
m_partId0(-1),
m_partId1(-1),
m_index0(-1),
m_index1(-1)
#endif //DEBUG_PART_INDEX
{
}
btManifoldResult(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btManifoldResult(){};
virtual ~btManifoldResult() {};
void setPersistentManifold(btPersistentManifold* manifoldPtr)
void setPersistentManifold(btPersistentManifold* manifoldPtr)
{
m_manifoldPtr = manifoldPtr;
}
const btPersistentManifold* getPersistentManifold() const
const btPersistentManifold* getPersistentManifold() const
{
return m_manifoldPtr;
}
btPersistentManifold* getPersistentManifold()
btPersistentManifold* getPersistentManifold()
{
return m_manifoldPtr;
}
virtual void setShapeIdentifiersA(int partId0, int index0)
virtual void setShapeIdentifiersA(int partId0,int index0)
{
m_partId0 = partId0;
m_index0 = index0;
m_partId0=partId0;
m_index0=index0;
}
virtual void setShapeIdentifiersB(int partId1, int index1)
virtual void setShapeIdentifiersB( int partId1,int index1)
{
m_partId1 = partId1;
m_index1 = index1;
m_partId1=partId1;
m_index1=index1;
}
virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth);
SIMD_FORCE_INLINE void refreshContactPoints()
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth);
SIMD_FORCE_INLINE void refreshContactPoints()
{
btAssert(m_manifoldPtr);
if (!m_manifoldPtr->getNumContacts())
@@ -112,11 +106,10 @@ public:
if (isSwapped)
{
m_manifoldPtr->refreshContactPoints(m_body1Wrap->getCollisionObject()->getWorldTransform(), m_body0Wrap->getCollisionObject()->getWorldTransform());
}
else
m_manifoldPtr->refreshContactPoints(m_body1Wrap->getCollisionObject()->getWorldTransform(),m_body0Wrap->getCollisionObject()->getWorldTransform());
} else
{
m_manifoldPtr->refreshContactPoints(m_body0Wrap->getCollisionObject()->getWorldTransform(), m_body1Wrap->getCollisionObject()->getWorldTransform());
m_manifoldPtr->refreshContactPoints(m_body0Wrap->getCollisionObject()->getWorldTransform(),m_body1Wrap->getCollisionObject()->getWorldTransform());
}
}
@@ -149,15 +142,9 @@ public:
return m_body1Wrap->getCollisionObject();
}
btScalar m_closestPointDistanceThreshold;
/// in the future we can let the user override the methods to combine restitution and friction
static btScalar calculateCombinedRestitution(const btCollisionObject* body0, const btCollisionObject* body1);
static btScalar calculateCombinedFriction(const btCollisionObject* body0, const btCollisionObject* body1);
static btScalar calculateCombinedRollingFriction(const btCollisionObject* body0, const btCollisionObject* body1);
static btScalar calculateCombinedSpinningFriction(const btCollisionObject* body0, const btCollisionObject* body1);
static btScalar calculateCombinedContactDamping(const btCollisionObject* body0, const btCollisionObject* body1);
static btScalar calculateCombinedContactStiffness(const btCollisionObject* body0, const btCollisionObject* body1);
static btScalar calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1);
static btScalar calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1);
};
#endif //BT_MANIFOLD_RESULT_H
#endif //BT_MANIFOLD_RESULT_H

View File

@@ -14,6 +14,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btScalar.h"
#include "btSimulationIslandManager.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
@@ -24,7 +25,8 @@ subject to the following restrictions:
//#include <stdio.h>
#include "LinearMath/btQuickprof.h"
btSimulationIslandManager::btSimulationIslandManager() : m_splitIslands(true)
btSimulationIslandManager::btSimulationIslandManager():
m_splitIslands(true)
{
}
@@ -32,47 +34,53 @@ btSimulationIslandManager::~btSimulationIslandManager()
{
}
void btSimulationIslandManager::initUnionFind(int n)
{
m_unionFind.reset(n);
m_unionFind.reset(n);
}
void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */, btCollisionWorld* colWorld)
void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
{
{
btOverlappingPairCache* pairCachePtr = colWorld->getPairCache();
const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs();
if (numOverlappingPairs)
{
btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr();
btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr();
for (int i=0;i<numOverlappingPairs;i++)
{
const btBroadphasePair& collisionPair = pairPtr[i];
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
for (int i = 0; i < numOverlappingPairs; i++)
if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
((colObj1) && ((colObj1)->mergesSimulationIslands())))
{
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())) &&
((colObj1) && ((colObj1)->mergesSimulationIslands())))
{
m_unionFind.unite((colObj0)->getIslandTag(),
(colObj1)->getIslandTag());
}
m_unionFind.unite((colObj0)->getIslandTag(),
(colObj1)->getIslandTag());
}
}
}
}
}
#ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher)
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
{
// put the index into m_controllers into m_tag
// put the index into m_controllers into m_tag
int index = 0;
{
int i;
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];
//Adding filtering here
if (!collisionObject->isStaticOrKinematicObject())
{
@@ -84,29 +92,28 @@ void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld
}
// do the union find
initUnionFind(index);
initUnionFind( index );
findUnions(dispatcher, colWorld);
findUnions(dispatcher,colWorld);
}
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
{
// put the islandId ('find' value) into m_tag
// put the islandId ('find' value) into m_tag
{
int index = 0;
int i;
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->isStaticOrKinematicObject())
{
collisionObject->setIslandTag(m_unionFind.find(index));
collisionObject->setIslandTag( m_unionFind.find(index) );
//Set the correct object offset in Collision Object Array
m_unionFind.getElement(index).m_sz = i;
collisionObject->setCompanionId(-1);
index++;
}
else
} else
{
collisionObject->setIslandTag(-1);
collisionObject->setCompanionId(-2);
@@ -115,44 +122,49 @@ void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* col
}
}
#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher)
{
initUnionFind(int(colWorld->getCollisionObjectArray().size()));
// put the index into m_controllers into m_tag
#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
{
initUnionFind( int (colWorld->getCollisionObjectArray().size()));
// put the index into m_controllers into m_tag
{
int index = 0;
int i;
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];
collisionObject->setIslandTag(index);
collisionObject->setCompanionId(-1);
collisionObject->setHitFraction(btScalar(1.));
index++;
}
}
// do the union find
findUnions(dispatcher, colWorld);
findUnions(dispatcher,colWorld);
}
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
{
// put the islandId ('find' value) into m_tag
// put the islandId ('find' value) into m_tag
{
int index = 0;
int i;
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->isStaticOrKinematicObject())
{
collisionObject->setIslandTag(m_unionFind.find(index));
collisionObject->setIslandTag( m_unionFind.find(index) );
collisionObject->setCompanionId(-1);
}
else
} else
{
collisionObject->setIslandTag(-1);
collisionObject->setCompanionId(-2);
@@ -162,59 +174,56 @@ void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* col
}
}
#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
inline int getIslandId(const btPersistentManifold* lhs)
inline int getIslandId(const btPersistentManifold* lhs)
{
int islandId;
const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
islandId = rcolObj0->getIslandTag() >= 0 ? rcolObj0->getIslandTag() : rcolObj1->getIslandTag();
islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag();
return islandId;
}
/// function object that routes calls to operator<
class btPersistentManifoldSortPredicate
{
public:
SIMD_FORCE_INLINE bool operator()(const btPersistentManifold* lhs, const btPersistentManifold* rhs) const
{
return getIslandId(lhs) < getIslandId(rhs);
}
public:
SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) const
{
return getIslandId(lhs) < getIslandId(rhs);
}
};
class btPersistentManifoldSortPredicateDeterministic
{
public:
SIMD_FORCE_INLINE bool operator()(const btPersistentManifold* lhs, const btPersistentManifold* rhs) const
{
return (
(getIslandId(lhs) < getIslandId(rhs)) || ((getIslandId(lhs) == getIslandId(rhs)) && lhs->getBody0()->getBroadphaseHandle()->m_uniqueId < rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) || ((getIslandId(lhs) == getIslandId(rhs)) && (lhs->getBody0()->getBroadphaseHandle()->m_uniqueId == rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) && (lhs->getBody1()->getBroadphaseHandle()->m_uniqueId < rhs->getBody1()->getBroadphaseHandle()->m_uniqueId)));
}
};
void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld)
void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld)
{
BT_PROFILE("islandUnionFindAndQuickSort");
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
m_islandmanifold.resize(0);
//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
getUnionFind().sortIslands();
int numElem = getUnionFind().getNumElements();
int endIslandIndex = 1;
int endIslandIndex=1;
int startIslandIndex;
//update the sleeping state for bodies, if all are sleeping
for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
{
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
for (endIslandIndex = startIslandIndex + 1; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
{
}
@@ -223,69 +232,71 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
bool allSleeping = true;
int idx;
for (idx = startIslandIndex; idx < endIslandIndex; idx++)
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
// printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
if (colObj0->getActivationState() == ACTIVE_TAG ||
colObj0->getActivationState() == DISABLE_DEACTIVATION)
if (colObj0->getActivationState()== ACTIVE_TAG)
{
allSleeping = false;
}
if (colObj0->getActivationState()== DISABLE_DEACTIVATION)
{
allSleeping = false;
break;
}
}
}
if (allSleeping)
{
int idx;
for (idx = startIslandIndex; idx < endIslandIndex; idx++)
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
// printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
colObj0->setActivationState(ISLAND_SLEEPING);
colObj0->setActivationState( ISLAND_SLEEPING );
}
}
}
else
} else
{
int idx;
for (idx = startIslandIndex; idx < endIslandIndex; idx++)
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
{
int i = getUnionFind().getElement(idx).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
// printf("error in island management\n");
// printf("error in island management\n");
}
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
if (colObj0->getIslandTag() == islandId)
{
if (colObj0->getActivationState() == ISLAND_SLEEPING)
if ( colObj0->getActivationState() == ISLAND_SLEEPING)
{
colObj0->setActivationState(WANTS_DEACTIVATION);
colObj0->setActivationState( WANTS_DEACTIVATION);
colObj0->setDeactivationTime(0.f);
}
}
@@ -293,30 +304,29 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
}
}
int i;
int maxNumManifolds = dispatcher->getNumManifolds();
//#define SPLIT_ISLANDS 1
//#ifdef SPLIT_ISLANDS
//#define SPLIT_ISLANDS 1
//#ifdef SPLIT_ISLANDS
//#endif //SPLIT_ISLANDS
//#endif //SPLIT_ISLANDS
for (i = 0; i < maxNumManifolds; i++)
for (i=0;i<maxNumManifolds ;i++)
{
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
if (collisionWorld->getDispatchInfo().m_deterministicOverlappingPairs)
{
if (manifold->getNumContacts() == 0)
continue;
}
const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
///@todo: check sleeping conditions!
if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
///@todo: check sleeping conditions!
if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
{
//kinematic objects don't merge islands, but wake up all connected objects
if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
{
@@ -328,10 +338,10 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
if (colObj1->hasContactResponse())
colObj0->activate();
}
if (m_splitIslands)
{
if(m_splitIslands)
{
//filtering for response
if (dispatcher->needsResponse(colObj0, colObj1))
if (dispatcher->needsResponse(colObj0,colObj1))
m_islandmanifold.push_back(manifold);
}
}
@@ -339,27 +349,25 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisi
}
///@todo: this is random access, it can be walked 'cache friendly'!
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
{
buildIslands(dispatcher, collisionWorld);
processIslands(dispatcher, collisionWorld, callback);
}
void btSimulationIslandManager::processIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
///@todo: this is random access, it can be walked 'cache friendly'!
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback)
{
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
int endIslandIndex = 1;
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
buildIslands(dispatcher,collisionWorld);
int endIslandIndex=1;
int startIslandIndex;
int numElem = getUnionFind().getNumElements();
BT_PROFILE("processIslands");
if (!m_splitIslands)
if(!m_splitIslands)
{
btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
int maxNumManifolds = dispatcher->getNumManifolds();
callback->processIsland(&collisionObjects[0], collisionObjects.size(), manifold, maxNumManifolds, -1);
callback->processIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1);
}
else
{
@@ -367,21 +375,11 @@ void btSimulationIslandManager::processIslands(btDispatcher* dispatcher, btColli
// Sort the vector using predicate and std::sort
//std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
int numManifolds = int(m_islandmanifold.size());
int numManifolds = int (m_islandmanifold.size());
//tried a radix sort, but quicksort/heapsort seems still faster
//@todo rewrite island management
//btPersistentManifoldSortPredicateDeterministic sorts contact manifolds based on islandid,
//but also based on object0 unique id and object1 unique id
if (collisionWorld->getDispatchInfo().m_deterministicOverlappingPairs)
{
m_islandmanifold.quickSort(btPersistentManifoldSortPredicateDeterministic());
}
else
{
m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
}
m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
//m_islandmanifold.heapSort(btPersistentManifoldSortPredicate());
//now process all active islands (sets of manifolds for now)
@@ -391,49 +389,55 @@ void btSimulationIslandManager::processIslands(btDispatcher* dispatcher, btColli
//int islandId;
// printf("Start Islands\n");
// printf("Start Islands\n");
//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)
{
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
bool islandSleeping = true;
for (endIslandIndex = startIslandIndex; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
{
int i = getUnionFind().getElement(endIslandIndex).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
m_islandBodies.push_back(colObj0);
if (colObj0->isActive())
islandSleeping = false;
}
bool islandSleeping = true;
for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
{
int i = getUnionFind().getElement(endIslandIndex).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
m_islandBodies.push_back(colObj0);
if (colObj0->isActive())
islandSleeping = false;
}
//find the accompanying contact manifold for this islandId
int numIslandManifolds = 0;
btPersistentManifold** startManifold = 0;
if (startManifoldIndex < numManifolds)
if (startManifoldIndex<numManifolds)
{
int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
if (curIslandId == islandId)
{
startManifold = &m_islandmanifold[startManifoldIndex];
for (endManifoldIndex = startManifoldIndex + 1; (endManifoldIndex < numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex])); endManifoldIndex++)
for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
{
}
/// Process the actual simulation, only if not sleeping/deactivated
numIslandManifolds = endManifoldIndex - startManifoldIndex;
numIslandManifolds = endManifoldIndex-startManifoldIndex;
}
}
if (!islandSleeping)
{
callback->processIsland(&m_islandBodies[0], m_islandBodies.size(), startManifold, numIslandManifolds, islandId);
// printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
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)
{
startManifoldIndex = endManifoldIndex;
@@ -441,5 +445,6 @@ void btSimulationIslandManager::processIslands(btDispatcher* dispatcher, btColli
m_islandBodies.resize(0);
}
} // else if(!splitIslands)
} // else if(!splitIslands)
}

View File

@@ -26,42 +26,46 @@ class btCollisionWorld;
class btDispatcher;
class btPersistentManifold;
///SimulationIslandManager creates and handles simulation islands, using btUnionFind
class btSimulationIslandManager
{
btUnionFind m_unionFind;
btAlignedObjectArray<btPersistentManifold*> m_islandmanifold;
btAlignedObjectArray<btCollisionObject*> m_islandBodies;
btAlignedObjectArray<btPersistentManifold*> m_islandmanifold;
btAlignedObjectArray<btCollisionObject* > m_islandBodies;
bool m_splitIslands;
public:
btSimulationIslandManager();
virtual ~btSimulationIslandManager();
void initUnionFind(int n);
btUnionFind& getUnionFind() { return m_unionFind; }
void initUnionFind(int n);
btUnionFind& getUnionFind() { return m_unionFind;}
virtual void updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher);
virtual void storeIslandActivationState(btCollisionWorld* world);
virtual void updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher);
virtual void storeIslandActivationState(btCollisionWorld* world);
void findUnions(btDispatcher* dispatcher, btCollisionWorld* colWorld);
struct IslandCallback
void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld);
struct IslandCallback
{
virtual ~IslandCallback(){};
virtual ~IslandCallback() {};
virtual void processIsland(btCollisionObject** bodies, int numBodies, class btPersistentManifold** manifolds, int numManifolds, int islandId) = 0;
virtual void processIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold** manifolds,int numManifolds, int islandId) = 0;
};
void buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
void buildIslands(btDispatcher* dispatcher, btCollisionWorld* colWorld);
void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback);
void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld);
void processIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
bool getSplitIslands()
{
return m_splitIslands;
@@ -70,6 +74,8 @@ public:
{
m_splitIslands = doSplitIslands;
}
};
#endif //BT_SIMULATION_ISLAND_MANAGER_H
#endif //BT_SIMULATION_ISLAND_MANAGER_H

View File

@@ -21,22 +21,23 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
//#include <stdio.h>
btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, bool isSwapped)
: btActivatingCollisionAlgorithm(ci, col0Wrap, col1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped)
btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap, bool isSwapped)
: btActivatingCollisionAlgorithm(ci,col0Wrap,col1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped)
{
const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped ? col1Wrap : col0Wrap;
const btCollisionObjectWrapper* boxObjWrap = m_isSwapped ? col0Wrap : col1Wrap;
if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObjWrap->getCollisionObject(), boxObjWrap->getCollisionObject()))
const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped? col1Wrap : col0Wrap;
const btCollisionObjectWrapper* boxObjWrap = m_isSwapped? col0Wrap : col1Wrap;
if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObjWrap->getCollisionObject(),boxObjWrap->getCollisionObject()))
{
m_manifoldPtr = m_dispatcher->getNewManifold(sphereObjWrap->getCollisionObject(), boxObjWrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(sphereObjWrap->getCollisionObject(),boxObjWrap->getCollisionObject());
m_ownManifold = true;
}
}
btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
{
if (m_ownManifold)
@@ -46,15 +47,17 @@ btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
}
}
void btSphereBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btSphereBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)dispatchInfo;
(void)resultOut;
if (!m_manifoldPtr)
return;
const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* boxObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped? body1Wrap : body0Wrap;
const btCollisionObjectWrapper* boxObjWrap = m_isSwapped? body0Wrap : body1Wrap;
btVector3 pOnBox;
@@ -80,9 +83,10 @@ void btSphereBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrap
resultOut->refreshContactPoints();
}
}
}
btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
@@ -93,26 +97,27 @@ btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
return btScalar(1.);
}
bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& pointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& sphereCenter, btScalar fRadius, btScalar maxContactDistance)
bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& pointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& sphereCenter, btScalar fRadius, btScalar maxContactDistance )
{
const btBoxShape* boxShape = (const btBoxShape*)boxObjWrap->getCollisionShape();
btVector3 const& boxHalfExtent = boxShape->getHalfExtentsWithoutMargin();
const btBoxShape* boxShape= (const btBoxShape*)boxObjWrap->getCollisionShape();
btVector3 const &boxHalfExtent = boxShape->getHalfExtentsWithoutMargin();
btScalar boxMargin = boxShape->getMargin();
penetrationDepth = 1.0f;
// convert the sphere position to the box's local space
btTransform const& m44T = boxObjWrap->getWorldTransform();
btTransform const &m44T = boxObjWrap->getWorldTransform();
btVector3 sphereRelPos = m44T.invXform(sphereCenter);
// Determine the closest point to the sphere center in the box
btVector3 closestPoint = sphereRelPos;
closestPoint.setX(btMin(boxHalfExtent.getX(), closestPoint.getX()));
closestPoint.setX(btMax(-boxHalfExtent.getX(), closestPoint.getX()));
closestPoint.setY(btMin(boxHalfExtent.getY(), closestPoint.getY()));
closestPoint.setY(btMax(-boxHalfExtent.getY(), closestPoint.getY()));
closestPoint.setZ(btMin(boxHalfExtent.getZ(), closestPoint.getZ()));
closestPoint.setZ(btMax(-boxHalfExtent.getZ(), closestPoint.getZ()));
closestPoint.setX( btMin(boxHalfExtent.getX(), closestPoint.getX()) );
closestPoint.setX( btMax(-boxHalfExtent.getX(), closestPoint.getX()) );
closestPoint.setY( btMin(boxHalfExtent.getY(), closestPoint.getY()) );
closestPoint.setY( btMax(-boxHalfExtent.getY(), closestPoint.getY()) );
closestPoint.setZ( btMin(boxHalfExtent.getZ(), closestPoint.getZ()) );
closestPoint.setZ( btMax(-boxHalfExtent.getZ(), closestPoint.getZ()) );
btScalar intersectionDist = fRadius + boxMargin;
btScalar contactDist = intersectionDist + maxContactDistance;
normal = sphereRelPos - closestPoint;
@@ -131,42 +136,42 @@ bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWra
{
distance = -getSpherePenetration(boxHalfExtent, sphereRelPos, closestPoint, normal);
}
else //compute the penetration details
else //compute the penetration details
{
distance = normal.length();
normal /= distance;
}
pointOnBox = closestPoint + normal * boxMargin;
// v3PointOnSphere = sphereRelPos - (normal * fRadius);
// v3PointOnSphere = sphereRelPos - (normal * fRadius);
penetrationDepth = distance - intersectionDist;
// transform back in world space
btVector3 tmp = m44T(pointOnBox);
pointOnBox = tmp;
// tmp = m44T(v3PointOnSphere);
// v3PointOnSphere = tmp;
// tmp = m44T(v3PointOnSphere);
// v3PointOnSphere = tmp;
tmp = m44T.getBasis() * normal;
normal = tmp;
return true;
}
btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& boxHalfExtent, btVector3 const& sphereRelPos, btVector3& closestPoint, btVector3& normal)
btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btVector3 const &boxHalfExtent, btVector3 const &sphereRelPos, btVector3 &closestPoint, btVector3& normal )
{
//project the center of the sphere on the closest face of the box
btScalar faceDist = boxHalfExtent.getX() - sphereRelPos.getX();
btScalar minDist = faceDist;
closestPoint.setX(boxHalfExtent.getX());
normal.setValue(btScalar(1.0f), btScalar(0.0f), btScalar(0.0f));
closestPoint.setX( boxHalfExtent.getX() );
normal.setValue(btScalar(1.0f), btScalar(0.0f), btScalar(0.0f));
faceDist = boxHalfExtent.getX() + sphereRelPos.getX();
if (faceDist < minDist)
{
minDist = faceDist;
closestPoint = sphereRelPos;
closestPoint.setX(-boxHalfExtent.getX());
normal.setValue(btScalar(-1.0f), btScalar(0.0f), btScalar(0.0f));
closestPoint.setX( -boxHalfExtent.getX() );
normal.setValue(btScalar(-1.0f), btScalar(0.0f), btScalar(0.0f));
}
faceDist = boxHalfExtent.getY() - sphereRelPos.getY();
@@ -174,8 +179,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& bo
{
minDist = faceDist;
closestPoint = sphereRelPos;
closestPoint.setY(boxHalfExtent.getY());
normal.setValue(btScalar(0.0f), btScalar(1.0f), btScalar(0.0f));
closestPoint.setY( boxHalfExtent.getY() );
normal.setValue(btScalar(0.0f), btScalar(1.0f), btScalar(0.0f));
}
faceDist = boxHalfExtent.getY() + sphereRelPos.getY();
@@ -183,8 +188,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& bo
{
minDist = faceDist;
closestPoint = sphereRelPos;
closestPoint.setY(-boxHalfExtent.getY());
normal.setValue(btScalar(0.0f), btScalar(-1.0f), btScalar(0.0f));
closestPoint.setY( -boxHalfExtent.getY() );
normal.setValue(btScalar(0.0f), btScalar(-1.0f), btScalar(0.0f));
}
faceDist = boxHalfExtent.getZ() - sphereRelPos.getZ();
@@ -192,8 +197,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& bo
{
minDist = faceDist;
closestPoint = sphereRelPos;
closestPoint.setZ(boxHalfExtent.getZ());
normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f));
closestPoint.setZ( boxHalfExtent.getZ() );
normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f));
}
faceDist = boxHalfExtent.getZ() + sphereRelPos.getZ();
@@ -201,8 +206,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& bo
{
minDist = faceDist;
closestPoint = sphereRelPos;
closestPoint.setZ(-boxHalfExtent.getZ());
normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(-1.0f));
closestPoint.setZ( -boxHalfExtent.getZ() );
normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(-1.0f));
}
return minDist;

View File

@@ -28,20 +28,21 @@ class btPersistentManifold;
/// Other features are frame-coherency (persistent data) and collision response.
class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_isSwapped;
public:
btSphereBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
virtual ~btSphereBoxCollisionAlgorithm();
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
@@ -49,25 +50,26 @@ public:
}
}
bool getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& v3PointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& v3SphereCenter, btScalar fRadius, btScalar maxContactDistance);
bool getSphereDistance( const btCollisionObjectWrapper* boxObjWrap, btVector3& v3PointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& v3SphereCenter, btScalar fRadius, btScalar maxContactDistance );
btScalar getSpherePenetration(btVector3 const& boxHalfExtent, btVector3 const& sphereRelPos, btVector3& closestPoint, btVector3& normal);
struct CreateFunc : public btCollisionAlgorithmCreateFunc
btScalar getSpherePenetration( btVector3 const &boxHalfExtent, btVector3 const &sphereRelPos, btVector3 &closestPoint, btVector3& normal );
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
if (!m_swapped)
{
return new (mem) btSphereBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false);
}
else
return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false);
} else
{
return new (mem) btSphereBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true);
return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true);
}
}
};
};
#endif //BT_SPHERE_BOX_COLLISION_ALGORITHM_H
#endif //BT_SPHERE_BOX_COLLISION_ALGORITHM_H

View File

@@ -12,7 +12,6 @@ subject to the following restrictions:
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.
*/
#define CLEAR_MANIFOLD 1
#include "btSphereSphereCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
@@ -20,14 +19,14 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap)
: btActivatingCollisionAlgorithm(ci, col0Wrap, col1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap)
: btActivatingCollisionAlgorithm(ci,col0Wrap,col1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
{
if (!m_manifoldPtr)
{
m_manifoldPtr = m_dispatcher->getNewManifold(col0Wrap->getCollisionObject(), col1Wrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(col0Wrap->getCollisionObject(),col1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -41,7 +40,7 @@ btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm()
}
}
void btSphereSphereCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btSphereSphereCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
@@ -53,27 +52,27 @@ void btSphereSphereCollisionAlgorithm::processCollision(const btCollisionObjectW
btSphereShape* sphere0 = (btSphereShape*)col0Wrap->getCollisionShape();
btSphereShape* sphere1 = (btSphereShape*)col1Wrap->getCollisionShape();
btVector3 diff = col0Wrap->getWorldTransform().getOrigin() - col1Wrap->getWorldTransform().getOrigin();
btVector3 diff = col0Wrap->getWorldTransform().getOrigin()- col1Wrap->getWorldTransform().getOrigin();
btScalar len = diff.length();
btScalar radius0 = sphere0->getRadius();
btScalar radius1 = sphere1->getRadius();
#ifdef CLEAR_MANIFOLD
m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
#endif
///iff distance positive, don't generate a new contact
if (len > (radius0 + radius1 + resultOut->m_closestPointDistanceThreshold))
if ( len > (radius0+radius1))
{
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
#endif //CLEAR_MANIFOLD
return;
}
///distance (negative means penetration)
btScalar dist = len - (radius0 + radius1);
btScalar dist = len - (radius0+radius1);
btVector3 normalOnSurfaceB(1, 0, 0);
btVector3 normalOnSurfaceB(1,0,0);
if (len > SIMD_EPSILON)
{
normalOnSurfaceB = diff / len;
@@ -82,18 +81,20 @@ void btSphereSphereCollisionAlgorithm::processCollision(const btCollisionObjectW
///point on A (worldspace)
///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
///point on B (worldspace)
btVector3 pos1 = col1Wrap->getWorldTransform().getOrigin() + radius1 * normalOnSurfaceB;
btVector3 pos1 = col1Wrap->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->addContactPoint(normalOnSurfaceB, pos1, dist);
resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
#ifndef CLEAR_MANIFOLD
resultOut->refreshContactPoints();
#endif //CLEAR_MANIFOLD
#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)
{
(void)col0;
(void)col1;

View File

@@ -28,37 +28,39 @@ class btPersistentManifold;
/// Also provides the most basic sample for custom/user btCollisionAlgorithm
class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
public:
btSphereSphereCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap);
btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap);
btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
virtual ~btSphereSphereCollisionAlgorithm();
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
return new (mem) btSphereSphereCollisionAlgorithm(0, ci, col0Wrap, col1Wrap);
return new(mem) btSphereSphereCollisionAlgorithm(0,ci,col0Wrap,col1Wrap);
}
};
};
#endif //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
#endif //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H

View File

@@ -13,6 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "btSphereTriangleCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
@@ -20,15 +21,15 @@ subject to the following restrictions:
#include "SphereTriangleDetector.h"
#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool swapped)
: btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf),
m_swapped(swapped)
btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool swapped)
: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf),
m_swapped(swapped)
{
if (!m_manifoldPtr)
{
m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -42,35 +43,36 @@ btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm()
}
}
void btSphereTriangleCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
void btSphereTriangleCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
const btCollisionObjectWrapper* sphereObjWrap = m_swapped ? col1Wrap : col0Wrap;
const btCollisionObjectWrapper* triObjWrap = m_swapped ? col0Wrap : col1Wrap;
const btCollisionObjectWrapper* sphereObjWrap = m_swapped? col1Wrap : col0Wrap;
const btCollisionObjectWrapper* triObjWrap = m_swapped? col0Wrap : col1Wrap;
btSphereShape* sphere = (btSphereShape*)sphereObjWrap->getCollisionShape();
btTriangleShape* triangle = (btTriangleShape*)triObjWrap->getCollisionShape();
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
SphereTriangleDetector detector(sphere, triangle, m_manifoldPtr->getContactBreakingThreshold() + resultOut->m_closestPointDistanceThreshold);
SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold());
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT); ///@todo: tighter bounds
input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);///@todo: tighter bounds
input.m_transformA = sphereObjWrap->getWorldTransform();
input.m_transformB = triObjWrap->getWorldTransform();
bool swapResults = m_swapped;
detector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw, swapResults);
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults);
if (m_ownManifold)
resultOut->refreshContactPoints();
}
btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;

View File

@@ -27,39 +27,43 @@ class btPersistentManifold;
/// Also provides the most basic sample for custom/user btCollisionAlgorithm
class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_swapped;
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
bool m_swapped;
public:
btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool swapped);
btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool swapped);
btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
{
if (m_manifoldPtr && m_ownManifold)
{
manifoldArray.push_back(m_manifoldPtr);
}
}
virtual ~btSphereTriangleCollisionAlgorithm();
struct CreateFunc : public btCollisionAlgorithmCreateFunc
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
return new (mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_swapped);
return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_swapped);
}
};
};
#endif //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
#endif //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H

View File

@@ -15,60 +15,68 @@ subject to the following restrictions:
#include "btUnionFind.h"
btUnionFind::~btUnionFind()
{
Free();
}
btUnionFind::btUnionFind()
{
{
}
void btUnionFind::allocate(int N)
void btUnionFind::allocate(int N)
{
m_elements.resize(N);
}
void btUnionFind::Free()
void btUnionFind::Free()
{
m_elements.clear();
}
void btUnionFind::reset(int N)
void btUnionFind::reset(int N)
{
allocate(N);
for (int i = 0; i < N; i++)
{
m_elements[i].m_id = i;
m_elements[i].m_sz = 1;
}
for (int i = 0; i < N; i++)
{
m_elements[i].m_id = i; m_elements[i].m_sz = 1;
}
}
class btUnionFindElementSortPredicate
{
public:
bool operator()(const btElement& lhs, const btElement& rhs) const
{
return lhs.m_id < rhs.m_id;
}
public:
bool operator() ( const btElement& lhs, const btElement& rhs ) const
{
return lhs.m_id < rhs.m_id;
}
};
///this is a special operation, destroying the content of btUnionFind.
///it sorts the elements, based on island id, in order to make it easy to iterate over islands
void btUnionFind::sortIslands()
void btUnionFind::sortIslands()
{
//first store the original body index, and islandId
int numElements = m_elements.size();
for (int i = 0; i < numElements; i++)
for (int i=0;i<numElements;i++)
{
m_elements[i].m_id = find(i);
#ifndef STATIC_SIMULATION_ISLAND_OPTIMIZATION
m_elements[i].m_sz = i;
#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
}
// Sort the vector using predicate and std::sort
//std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
m_elements.quickSort(btUnionFindElementSortPredicate());
// Sort the vector using predicate and std::sort
//std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
m_elements.quickSort(btUnionFindElementSortPredicate());
}

View File

@@ -23,101 +23,107 @@ subject to the following restrictions:
///see for discussion of static island optimizations by Vroonsh here: http://code.google.com/p/bullet/issues/detail?id=406
#define STATIC_SIMULATION_ISLAND_OPTIMIZATION 1
struct btElement
struct btElement
{
int m_id;
int m_sz;
int m_id;
int m_sz;
};
///UnionFind calculates connected subsets
// Implements weighted Quick Union with path compression
// optimization: could use short ints instead of ints (halving memory, would limit the number of rigid bodies to 64k, sounds reasonable)
class btUnionFind
{
private:
btAlignedObjectArray<btElement> m_elements;
{
private:
btAlignedObjectArray<btElement> m_elements;
public:
btUnionFind();
~btUnionFind();
public:
btUnionFind();
~btUnionFind();
//this is a special operation, destroying the content of btUnionFind.
//it sorts the elements, based on island id, in order to make it easy to iterate over islands
void sortIslands();
//this is a special operation, destroying the content of btUnionFind.
//it sorts the elements, based on island id, in order to make it easy to iterate over islands
void sortIslands();
void reset(int N);
void reset(int N);
SIMD_FORCE_INLINE int getNumElements() const
{
return int(m_elements.size());
}
SIMD_FORCE_INLINE bool isRoot(int x) const
{
return (x == m_elements[x].m_id);
}
SIMD_FORCE_INLINE int getNumElements() const
{
return int(m_elements.size());
}
SIMD_FORCE_INLINE bool isRoot(int x) const
{
return (x == m_elements[x].m_id);
}
btElement& getElement(int index)
{
return m_elements[index];
}
const btElement& getElement(int index) const
{
return m_elements[index];
}
btElement& getElement(int index)
{
return m_elements[index];
}
const btElement& getElement(int index) const
{
return m_elements[index];
}
void allocate(int N);
void Free();
void allocate(int N);
void Free();
int find(int p, int q)
{
return (find(p) == find(q));
}
void unite(int p, int q)
{
int i = find(p), j = find(q);
if (i == j)
return;
int find(int p, int q)
{
return (find(p) == find(q));
}
void unite(int p, int q)
{
int i = find(p), j = find(q);
if (i == j)
return;
#ifndef USE_PATH_COMPRESSION
//weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) )
if (m_elements[i].m_sz < m_elements[j].m_sz)
{
m_elements[i].m_id = j;
m_elements[j].m_sz += m_elements[i].m_sz;
}
else
{
m_elements[j].m_id = i;
m_elements[i].m_sz += m_elements[j].m_sz;
}
//weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) )
if (m_elements[i].m_sz < m_elements[j].m_sz)
{
m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz;
}
else
{
m_elements[j].m_id = i; m_elements[i].m_sz += m_elements[j].m_sz;
}
#else
m_elements[i].m_id = j;
m_elements[j].m_sz += m_elements[i].m_sz;
#endif //USE_PATH_COMPRESSION
}
m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz;
#endif //USE_PATH_COMPRESSION
}
int find(int x)
{
//btAssert(x < m_N);
//btAssert(x >= 0);
while (x != m_elements[x].m_id)
{
//not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically
#ifdef USE_PATH_COMPRESSION
const btElement* elementPtr = &m_elements[m_elements[x].m_id];
m_elements[x].m_id = elementPtr->m_id;
x = elementPtr->m_id;
#else //
x = m_elements[x].m_id;
#endif
int find(int x)
{
//btAssert(x < m_N);
//btAssert(x >= 0);
}
return x;
}
};
#endif //BT_UNION_FIND_H
while (x != m_elements[x].m_id)
{
//not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically
#ifdef USE_PATH_COMPRESSION
const btElement* elementPtr = &m_elements[m_elements[x].m_id];
m_elements[x].m_id = elementPtr->m_id;
x = elementPtr->m_id;
#else//
x = m_elements[x].m_id;
#endif
//btAssert(x < m_N);
//btAssert(x >= 0);
}
return x;
}
};
#endif //BT_UNION_FIND_H

View File

@@ -15,23 +15,28 @@ subject to the following restrictions:
#include "btBox2dShape.h"
//{
void btBox2dShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
//{
void btBox2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
btTransformAabb(getHalfExtentsWithoutMargin(), getMargin(), t, aabbMin, aabbMax);
btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
}
void btBox2dShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
void btBox2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
//btScalar margin = btScalar(0.);
btVector3 halfExtents = getHalfExtentsWithMargin();
btScalar lx = btScalar(2.) * (halfExtents.x());
btScalar ly = btScalar(2.) * (halfExtents.y());
btScalar lz = btScalar(2.) * (halfExtents.z());
btScalar lx=btScalar(2.)*(halfExtents.x());
btScalar ly=btScalar(2.)*(halfExtents.y());
btScalar lz=btScalar(2.)*(halfExtents.z());
inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
mass/(btScalar(12.0)) * (lx*lx + lz*lz),
mass/(btScalar(12.0)) * (lx*lx + ly*ly));
inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
mass / (btScalar(12.0)) * (lx * lx + lz * lz),
mass / (btScalar(12.0)) * (lx * lx + ly * ly));
}

View File

@@ -23,9 +23,9 @@ subject to the following restrictions:
#include "LinearMath/btMinMax.h"
///The btBox2dShape 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.
ATTRIBUTE_ALIGNED16(class)
btBox2dShape : public btPolyhedralConvexShape
ATTRIBUTE_ALIGNED16(class) btBox2dShape: public btPolyhedralConvexShape
{
//btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
btVector3 m_centroid;
@@ -33,111 +33,122 @@ btBox2dShape : public btPolyhedralConvexShape
btVector3 m_normals[4];
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
btVector3 getHalfExtentsWithMargin() const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
btVector3 margin(getMargin(), getMargin(), getMargin());
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
return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
}
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
btVector3 margin(getMargin(), getMargin(), getMargin());
btVector3 margin(getMargin(),getMargin(),getMargin());
halfExtents += margin;
return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
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
{
const btVector3& halfExtents = getHalfExtentsWithoutMargin();
for (int i = 0; i < numVectors; i++)
for (int i=0;i<numVectors;i++)
{
const btVector3& vec = vectors[i];
supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
}
///a btBox2dShape is a flat 2D box in the X-Y plane (Z extents are zero)
btBox2dShape(const btVector3& boxHalfExtents)
: btPolyhedralConvexShape(),
m_centroid(0, 0, 0)
{
m_vertices[0].setValue(-boxHalfExtents.getX(), -boxHalfExtents.getY(), 0);
m_vertices[1].setValue(boxHalfExtents.getX(), -boxHalfExtents.getY(), 0);
m_vertices[2].setValue(boxHalfExtents.getX(), boxHalfExtents.getY(), 0);
m_vertices[3].setValue(-boxHalfExtents.getX(), boxHalfExtents.getY(), 0);
m_normals[0].setValue(0, -1, 0);
m_normals[1].setValue(1, 0, 0);
m_normals[2].setValue(0, 1, 0);
m_normals[3].setValue(-1, 0, 0);
///a btBox2dShape is a flat 2D box in the X-Y plane (Z extents are zero)
btBox2dShape( const btVector3& boxHalfExtents)
: btPolyhedralConvexShape(),
m_centroid(0,0,0)
{
m_vertices[0].setValue(-boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
m_vertices[1].setValue(boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
m_vertices[2].setValue(boxHalfExtents.getX(),boxHalfExtents.getY(),0);
m_vertices[3].setValue(-boxHalfExtents.getX(),boxHalfExtents.getY(),0);
m_normals[0].setValue(0,-1,0);
m_normals[1].setValue(1,0,0);
m_normals[2].setValue(0,1,0);
m_normals[3].setValue(-1,0,0);
btScalar minDimension = boxHalfExtents.getX();
if (minDimension > boxHalfExtents.getY())
if (minDimension>boxHalfExtents.getY())
minDimension = boxHalfExtents.getY();
setSafeMargin(minDimension);
m_shapeType = BOX_2D_SHAPE_PROXYTYPE;
btVector3 margin(getMargin(), getMargin(), getMargin());
btVector3 margin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
setSafeMargin(minDimension);
};
virtual void setMargin(btScalar collisionMargin)
{
//correct the m_implicitShapeDimensions for the margin
btVector3 oldMargin(getMargin(), getMargin(), getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
btVector3 oldMargin(getMargin(),getMargin(),getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
btConvexInternalShape::setMargin(collisionMargin);
btVector3 newMargin(getMargin(), getMargin(), getMargin());
btVector3 newMargin(getMargin(),getMargin(),getMargin());
m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
}
virtual void setLocalScaling(const btVector3& scaling)
virtual void setLocalScaling(const btVector3& scaling)
{
btVector3 oldMargin(getMargin(), getMargin(), getMargin());
btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
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) const;
int getVertexCount() const
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
int getVertexCount() const
{
return 4;
}
virtual int getNumVertices() const
virtual int getNumVertices()const
{
return 4;
}
@@ -152,70 +163,82 @@ public:
return &m_normals[0];
}
virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const
{
//this plane might not be aligned...
btVector4 plane;
getPlaneEquation(plane, i);
planeNormal = btVector3(plane.getX(), plane.getY(), plane.getZ());
btVector4 plane ;
getPlaneEquation(plane,i);
planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
planeSupport = localGetSupportingVertex(-planeNormal);
}
const btVector3& getCentroid() const
{
return m_centroid;
}
virtual int getNumPlanes() const
{
return 6;
}
}
virtual int getNumEdges() const
{
return 12;
}
virtual void getVertex(int i, btVector3& vtx) const
virtual void getVertex(int i,btVector3& vtx) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
vtx = btVector3(
halfExtents.x() * (1 - (i & 1)) - halfExtents.x() * (i & 1),
halfExtents.y() * (1 - ((i & 2) >> 1)) - halfExtents.y() * ((i & 2) >> 1),
halfExtents.z() * (1 - ((i & 4) >> 2)) - halfExtents.z() * ((i & 4) >> 2));
halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
}
virtual void getPlaneEquation(btVector4 & plane, int i) const
virtual void getPlaneEquation(btVector4& plane,int i) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
switch (i)
{
case 0:
plane.setValue(btScalar(1.), btScalar(0.), btScalar(0.), -halfExtents.x());
break;
case 1:
plane.setValue(btScalar(-1.), btScalar(0.), btScalar(0.), -halfExtents.x());
break;
case 2:
plane.setValue(btScalar(0.), btScalar(1.), btScalar(0.), -halfExtents.y());
break;
case 3:
plane.setValue(btScalar(0.), btScalar(-1.), btScalar(0.), -halfExtents.y());
break;
case 4:
plane.setValue(btScalar(0.), btScalar(0.), btScalar(1.), -halfExtents.z());
break;
case 5:
plane.setValue(btScalar(0.), btScalar(0.), btScalar(-1.), -halfExtents.z());
break;
default:
btAssert(0);
case 0:
plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x());
break;
case 1:
plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x());
break;
case 2:
plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y());
break;
case 3:
plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y());
break;
case 4:
plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z());
break;
case 5:
plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z());
break;
default:
btAssert(0);
}
}
virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
//virtual void getEdge(int i,Edge& edge) const
{
int edgeVert0 = 0;
@@ -223,117 +246,126 @@ public:
switch (i)
{
case 0:
case 0:
edgeVert0 = 0;
edgeVert1 = 1;
break;
case 1:
break;
case 1:
edgeVert0 = 0;
edgeVert1 = 2;
break;
case 2:
edgeVert0 = 1;
edgeVert1 = 3;
break;
case 2:
edgeVert0 = 1;
edgeVert1 = 3;
break;
case 3:
edgeVert0 = 2;
edgeVert1 = 3;
break;
case 4:
edgeVert0 = 0;
edgeVert1 = 4;
break;
case 5:
edgeVert0 = 1;
edgeVert1 = 5;
break;
case 3:
edgeVert0 = 2;
edgeVert1 = 3;
break;
case 4:
edgeVert0 = 0;
edgeVert1 = 4;
break;
case 5:
edgeVert0 = 1;
edgeVert1 = 5;
break;
case 6:
edgeVert0 = 2;
edgeVert1 = 6;
break;
case 7:
edgeVert0 = 3;
edgeVert1 = 7;
break;
case 8:
edgeVert0 = 4;
edgeVert1 = 5;
break;
case 9:
edgeVert0 = 4;
edgeVert1 = 6;
break;
case 10:
edgeVert0 = 5;
edgeVert1 = 7;
break;
case 11:
edgeVert0 = 6;
edgeVert1 = 7;
break;
default:
btAssert(0);
break;
case 6:
edgeVert0 = 2;
edgeVert1 = 6;
break;
case 7:
edgeVert0 = 3;
edgeVert1 = 7;
break;
case 8:
edgeVert0 = 4;
edgeVert1 = 5;
break;
case 9:
edgeVert0 = 4;
edgeVert1 = 6;
break;
case 10:
edgeVert0 = 5;
edgeVert1 = 7;
break;
case 11:
edgeVert0 = 6;
edgeVert1 = 7;
break;
default:
btAssert(0);
}
getVertex(edgeVert0, pa);
getVertex(edgeVert1, pb);
getVertex(edgeVert0,pa );
getVertex(edgeVert1,pb );
}
virtual bool isInside(const btVector3& pt, btScalar tolerance) const
virtual bool isInside(const btVector3& pt,btScalar tolerance) const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
//btScalar minDist = 2*tolerance;
bool result = (pt.x() <= (halfExtents.x() + tolerance)) &&
(pt.x() >= (-halfExtents.x() - tolerance)) &&
(pt.y() <= (halfExtents.y() + tolerance)) &&
(pt.y() >= (-halfExtents.y() - tolerance)) &&
(pt.z() <= (halfExtents.z() + tolerance)) &&
(pt.z() >= (-halfExtents.z() - tolerance));
bool result = (pt.x() <= (halfExtents.x()+tolerance)) &&
(pt.x() >= (-halfExtents.x()-tolerance)) &&
(pt.y() <= (halfExtents.y()+tolerance)) &&
(pt.y() >= (-halfExtents.y()-tolerance)) &&
(pt.z() <= (halfExtents.z()+tolerance)) &&
(pt.z() >= (-halfExtents.z()-tolerance));
return result;
}
//debugging
virtual const char* getName() const
virtual const char* getName()const
{
return "Box2d";
}
virtual int getNumPreferredPenetrationDirections() const
virtual int getNumPreferredPenetrationDirections() const
{
return 6;
}
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
{
switch (index)
{
case 0:
penetrationVector.setValue(btScalar(1.), btScalar(0.), btScalar(0.));
break;
case 1:
penetrationVector.setValue(btScalar(-1.), btScalar(0.), btScalar(0.));
break;
case 2:
penetrationVector.setValue(btScalar(0.), btScalar(1.), btScalar(0.));
break;
case 3:
penetrationVector.setValue(btScalar(0.), btScalar(-1.), btScalar(0.));
break;
case 4:
penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(1.));
break;
case 5:
penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(-1.));
break;
default:
btAssert(0);
case 0:
penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
break;
case 1:
penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
break;
case 2:
penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
break;
case 3:
penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
break;
case 4:
penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
break;
case 5:
penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
break;
default:
btAssert(0);
}
}
};
#endif //BT_OBB_BOX_2D_SHAPE_H
#endif //BT_OBB_BOX_2D_SHAPE_H

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