├── CMakeLists.txt ├── README.md ├── pybullet_cpp_example.cpp └── src ├── Bullet3Common ├── b3AlignedAllocator.cpp ├── b3AlignedAllocator.h ├── b3AlignedObjectArray.h ├── b3CommandLineArgs.h ├── b3FileUtils.h ├── b3HashMap.h ├── b3Logging.cpp ├── b3Logging.h ├── b3Matrix3x3.h ├── b3MinMax.h ├── b3PoolAllocator.h ├── b3QuadWord.h ├── b3Quaternion.h ├── b3Random.h ├── b3ResizablePool.h ├── b3Scalar.h ├── b3StackAlloc.h ├── b3Transform.h ├── b3TransformUtil.h ├── b3Vector3.cpp ├── b3Vector3.h └── shared │ ├── b3Float4.h │ ├── b3Int2.h │ ├── b3Int4.h │ ├── b3Mat3x3.h │ ├── b3PlatformDefinitions.h │ └── b3Quat.h ├── CMakeLists.txt ├── LinearMath ├── TaskScheduler │ ├── btTaskScheduler.cpp │ ├── btThreadSupportInterface.h │ ├── btThreadSupportPosix.cpp │ └── btThreadSupportWin32.cpp ├── btAabbUtil2.h ├── btAlignedAllocator.cpp ├── btAlignedAllocator.h ├── btAlignedObjectArray.h ├── btConvexHull.cpp ├── btConvexHull.h ├── btConvexHullComputer.cpp ├── btConvexHullComputer.h ├── btCpuFeatureUtility.h ├── btDefaultMotionState.h ├── btGeometryUtil.cpp ├── btGeometryUtil.h ├── btGrahamScan2dConvexHull.h ├── btHashMap.h ├── btIDebugDraw.h ├── btImplicitQRSVD.h ├── btList.h ├── btMatrix3x3.h ├── btMatrixX.h ├── btMinMax.h ├── btModifiedGramSchmidt.h ├── btMotionState.h ├── btPolarDecomposition.cpp ├── btPolarDecomposition.h ├── btPoolAllocator.h ├── btQuadWord.h ├── btQuaternion.h ├── btQuickprof.cpp ├── btQuickprof.h ├── btRandom.h ├── btReducedVector.cpp ├── btReducedVector.h ├── btScalar.h ├── btSerializer.cpp ├── btSerializer.h ├── btSerializer64.cpp ├── btSpatialAlgebra.h ├── btStackAlloc.h ├── btThreads.cpp ├── btThreads.h ├── btTransform.h ├── btTransformUtil.h ├── btVector3.cpp └── btVector3.h ├── Serialize └── BulletFileLoader │ ├── autogenerated │ └── bullet.h │ ├── bChunk.cpp │ ├── bChunk.h │ ├── bCommon.h │ ├── bDNA.cpp │ ├── bDNA.h │ ├── bDefines.h │ ├── bFile.cpp │ ├── bFile.h │ ├── btBulletFile.cpp │ └── btBulletFile.h ├── SharedMemory ├── BodyJointInfoUtility.h ├── InProcessMemory.cpp ├── InProcessMemory.h ├── PhysicsClient.cpp ├── PhysicsClient.h ├── PhysicsClientC_API.cpp ├── PhysicsClientC_API.h ├── PhysicsClientSharedMemory.cpp ├── PhysicsClientSharedMemory.h ├── PhysicsClientSharedMemory_C_API.cpp ├── PhysicsClientSharedMemory_C_API.h ├── PhysicsCommandProcessorInterface.h ├── PosixSharedMemory.cpp ├── PosixSharedMemory.h ├── SharedMemoryBlock.h ├── SharedMemoryCommandProcessor.cpp ├── SharedMemoryCommandProcessor.h ├── SharedMemoryCommands.h ├── SharedMemoryCommon.h ├── SharedMemoryInterface.h ├── SharedMemoryPublic.h ├── SharedMemoryUserData.h ├── Win32SharedMemory.cpp ├── Win32SharedMemory.h ├── b3RobotSimulatorClientAPI_InternalData.h ├── b3RobotSimulatorClientAPI_NoDirect.cpp ├── b3RobotSimulatorClientAPI_NoDirect.h ├── urdfStringSplit.cpp └── urdfStringSplit.h └── Utils ├── ChromeTraceUtil.cpp ├── ChromeTraceUtil.h ├── RobotLoggingUtil.cpp ├── RobotLoggingUtil.h ├── b3BulletDefaultFileIO.h ├── b3Clock.cpp ├── b3Clock.h ├── b3Quickprof.cpp ├── b3Quickprof.h ├── b3ResourcePath.cpp └── b3ResourcePath.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | PROJECT(pybullet_cpp_sharedmemory) 4 | 5 | cmake_minimum_required(VERSION 3.12) 6 | 7 | SUBDIRS(src) 8 | 9 | 10 | add_executable(pybullet_cpp_example pybullet_cpp_example.cpp) 11 | 12 | target_link_libraries(pybullet_cpp_example PUBLIC pybullet_cpp) 13 | 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hello PyBullet CPP example 2 | 3 | A minimal example showing how to use PyBullet from C++ over shared memory. 4 | 5 | In on terminal run a PyBullet GUI server using: 6 | ``` 7 | pip3 install pybullet==3.1.0 8 | python3 -m pybullet_utils.runServer 9 | ``` 10 | 11 | Install [Visual Studio 2019 Community Edition](https://visualstudio.microsoft.com/vs/community/) in the default location and also a git client such as [TortoiseGit](https://tortoisegit.org) and [cmake](https://cmake.org). 12 | Then run this command to open a x64 terminal, +R, copy this command into the RUN window and hit enter: 13 | ``` 14 | %comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" 15 | ``` 16 | Now you should be in a "Visual Studio 2019 Developer Command Prompt" 17 | Compile the C++ code and run the client using: 18 | ``` 19 | git clone https://github.com/erwincoumans/pybullet_cpp_sharedmemory_example 20 | cd pybullet_cpp_sharedmemory_example 21 | mkdir build 22 | cd build 23 | cmake .. 24 | cmake --build . --config Release 25 | Release\pybullet_cpp_example.exe or ./pybullet_cpp_example 26 | ``` 27 | -------------------------------------------------------------------------------- /pybullet_cpp_example.cpp: -------------------------------------------------------------------------------- 1 | #include "SharedMemory/b3RobotSimulatorClientAPI_NoDirect.h" 2 | #include "SharedMemory/PhysicsClientSharedMemory_C_API.h" 3 | #include "SharedMemory/b3RobotSimulatorClientAPI_InternalData.h" 4 | #include 5 | 6 | int main() 7 | { 8 | b3PhysicsClientHandle client = b3ConnectSharedMemory(SHARED_MEMORY_KEY); 9 | if (!b3CanSubmitCommand(client)) 10 | { 11 | printf("Not connected, start a PyBullet server first, using python -m pybullet_utils.runServer\n"); 12 | exit(0); 13 | } 14 | b3RobotSimulatorClientAPI_InternalData data; 15 | data.m_physicsClientHandle = client; 16 | data.m_guiHelper = 0; 17 | b3RobotSimulatorClientAPI_NoDirect api; 18 | api.setInternalData(&data); 19 | api.resetSimulation(); 20 | 21 | int plane = api.loadURDF("plane.urdf"); 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/Bullet3Common/b3AlignedAllocator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Bullet Continuous Collision Detection and Physics Library 3 | Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #include "b3AlignedAllocator.h" 17 | 18 | #ifdef B3_ALLOCATOR_STATISTICS 19 | int b3g_numAlignedAllocs = 0; 20 | int b3g_numAlignedFree = 0; 21 | int b3g_totalBytesAlignedAllocs = 0; //detect memory leaks 22 | #endif 23 | 24 | static void *b3AllocDefault(size_t size) 25 | { 26 | return malloc(size); 27 | } 28 | 29 | static void b3FreeDefault(void *ptr) 30 | { 31 | free(ptr); 32 | } 33 | 34 | static b3AllocFunc *b3s_allocFunc = b3AllocDefault; 35 | static b3FreeFunc *b3s_freeFunc = b3FreeDefault; 36 | 37 | #if defined(B3_HAS_ALIGNED_ALLOCATOR) 38 | #include 39 | static void *b3AlignedAllocDefault(size_t size, int alignment) 40 | { 41 | return _aligned_malloc(size, (size_t)alignment); 42 | } 43 | 44 | static void b3AlignedFreeDefault(void *ptr) 45 | { 46 | _aligned_free(ptr); 47 | } 48 | #elif defined(__CELLOS_LV2__) 49 | #include 50 | 51 | static inline void *b3AlignedAllocDefault(size_t size, int alignment) 52 | { 53 | return memalign(alignment, size); 54 | } 55 | 56 | static inline void b3AlignedFreeDefault(void *ptr) 57 | { 58 | free(ptr); 59 | } 60 | #else 61 | 62 | static inline void *b3AlignedAllocDefault(size_t size, int alignment) 63 | { 64 | void *ret; 65 | char *real; 66 | real = (char *)b3s_allocFunc(size + sizeof(void *) + (alignment - 1)); 67 | if (real) 68 | { 69 | ret = b3AlignPointer(real + sizeof(void *), alignment); 70 | *((void **)(ret)-1) = (void *)(real); 71 | } 72 | else 73 | { 74 | ret = (void *)(real); 75 | } 76 | return (ret); 77 | } 78 | 79 | static inline void b3AlignedFreeDefault(void *ptr) 80 | { 81 | void *real; 82 | 83 | if (ptr) 84 | { 85 | real = *((void **)(ptr)-1); 86 | b3s_freeFunc(real); 87 | } 88 | } 89 | #endif 90 | 91 | static b3AlignedAllocFunc *b3s_alignedAllocFunc = b3AlignedAllocDefault; 92 | static b3AlignedFreeFunc *b3s_alignedFreeFunc = b3AlignedFreeDefault; 93 | 94 | void b3AlignedAllocSetCustomAligned(b3AlignedAllocFunc *allocFunc, b3AlignedFreeFunc *freeFunc) 95 | { 96 | b3s_alignedAllocFunc = allocFunc ? allocFunc : b3AlignedAllocDefault; 97 | b3s_alignedFreeFunc = freeFunc ? freeFunc : b3AlignedFreeDefault; 98 | } 99 | 100 | void b3AlignedAllocSetCustom(b3AllocFunc *allocFunc, b3FreeFunc *freeFunc) 101 | { 102 | b3s_allocFunc = allocFunc ? allocFunc : b3AllocDefault; 103 | b3s_freeFunc = freeFunc ? freeFunc : b3FreeDefault; 104 | } 105 | 106 | #ifdef B3_DEBUG_MEMORY_ALLOCATIONS 107 | //this generic allocator provides the total allocated number of bytes 108 | #include 109 | 110 | void *b3AlignedAllocInternal(size_t size, int alignment, int line, char *filename) 111 | { 112 | void *ret; 113 | char *real; 114 | #ifdef B3_ALLOCATOR_STATISTICS 115 | b3g_totalBytesAlignedAllocs += size; 116 | b3g_numAlignedAllocs++; 117 | #endif 118 | real = (char *)b3s_allocFunc(size + 2 * sizeof(void *) + (alignment - 1)); 119 | if (real) 120 | { 121 | ret = (void *)b3AlignPointer(real + 2 * sizeof(void *), alignment); 122 | *((void **)(ret)-1) = (void *)(real); 123 | *((int *)(ret)-2) = size; 124 | } 125 | else 126 | { 127 | ret = (void *)(real); //?? 128 | } 129 | 130 | b3Printf("allocation#%d at address %x, from %s,line %d, size %d\n", b3g_numAlignedAllocs, real, filename, line, size); 131 | 132 | int *ptr = (int *)ret; 133 | *ptr = 12; 134 | return (ret); 135 | } 136 | 137 | void b3AlignedFreeInternal(void *ptr, int line, char *filename) 138 | { 139 | void *real; 140 | #ifdef B3_ALLOCATOR_STATISTICS 141 | b3g_numAlignedFree++; 142 | #endif 143 | if (ptr) 144 | { 145 | real = *((void **)(ptr)-1); 146 | int size = *((int *)(ptr)-2); 147 | #ifdef B3_ALLOCATOR_STATISTICS 148 | b3g_totalBytesAlignedAllocs -= size; 149 | #endif 150 | b3Printf("free #%d at address %x, from %s,line %d, size %d\n", b3g_numAlignedFree, real, filename, line, size); 151 | 152 | b3s_freeFunc(real); 153 | } 154 | else 155 | { 156 | b3Printf("NULL ptr\n"); 157 | } 158 | } 159 | 160 | #else //B3_DEBUG_MEMORY_ALLOCATIONS 161 | 162 | void *b3AlignedAllocInternal(size_t size, int alignment) 163 | { 164 | #ifdef B3_ALLOCATOR_STATISTICS 165 | b3g_numAlignedAllocs++; 166 | #endif 167 | void *ptr; 168 | ptr = b3s_alignedAllocFunc(size, alignment); 169 | // b3Printf("b3AlignedAllocInternal %d, %x\n",size,ptr); 170 | return ptr; 171 | } 172 | 173 | void b3AlignedFreeInternal(void *ptr) 174 | { 175 | if (!ptr) 176 | { 177 | return; 178 | } 179 | #ifdef B3_ALLOCATOR_STATISTICS 180 | b3g_numAlignedFree++; 181 | #endif 182 | // b3Printf("b3AlignedFreeInternal %x\n",ptr); 183 | b3s_alignedFreeFunc(ptr); 184 | } 185 | 186 | #endif //B3_DEBUG_MEMORY_ALLOCATIONS 187 | -------------------------------------------------------------------------------- /src/Bullet3Common/b3AlignedAllocator.h: -------------------------------------------------------------------------------- 1 | /* 2 | Bullet Continuous Collision Detection and Physics Library 3 | Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #ifndef B3_ALIGNED_ALLOCATOR 17 | #define B3_ALIGNED_ALLOCATOR 18 | 19 | ///we probably replace this with our own aligned memory allocator 20 | ///so we replace _aligned_malloc and _aligned_free with our own 21 | ///that is better portable and more predictable 22 | 23 | #include "b3Scalar.h" 24 | //#define B3_DEBUG_MEMORY_ALLOCATIONS 1 25 | #ifdef B3_DEBUG_MEMORY_ALLOCATIONS 26 | 27 | #define b3AlignedAlloc(a, b) \ 28 | b3AlignedAllocInternal(a, b, __LINE__, __FILE__) 29 | 30 | #define b3AlignedFree(ptr) \ 31 | b3AlignedFreeInternal(ptr, __LINE__, __FILE__) 32 | 33 | void* b3AlignedAllocInternal(size_t size, int alignment, int line, char* filename); 34 | 35 | void b3AlignedFreeInternal(void* ptr, int line, char* filename); 36 | 37 | #else 38 | void* b3AlignedAllocInternal(size_t size, int alignment); 39 | void b3AlignedFreeInternal(void* ptr); 40 | 41 | #define b3AlignedAlloc(size, alignment) b3AlignedAllocInternal(size, alignment) 42 | #define b3AlignedFree(ptr) b3AlignedFreeInternal(ptr) 43 | 44 | #endif 45 | typedef int btSizeType; 46 | 47 | typedef void*(b3AlignedAllocFunc)(size_t size, int alignment); 48 | typedef void(b3AlignedFreeFunc)(void* memblock); 49 | typedef void*(b3AllocFunc)(size_t size); 50 | typedef void(b3FreeFunc)(void* memblock); 51 | 52 | ///The developer can let all Bullet memory allocations go through a custom memory allocator, using b3AlignedAllocSetCustom 53 | void b3AlignedAllocSetCustom(b3AllocFunc* allocFunc, b3FreeFunc* freeFunc); 54 | ///If the developer has already an custom aligned allocator, then b3AlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it. 55 | void b3AlignedAllocSetCustomAligned(b3AlignedAllocFunc* allocFunc, b3AlignedFreeFunc* freeFunc); 56 | 57 | ///The b3AlignedAllocator is a portable class for aligned memory allocations. 58 | ///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using b3AlignedAllocSetCustom and b3AlignedAllocSetCustomAligned. 59 | template 60 | class b3AlignedAllocator 61 | { 62 | typedef b3AlignedAllocator self_type; 63 | 64 | public: 65 | //just going down a list: 66 | b3AlignedAllocator() {} 67 | /* 68 | b3AlignedAllocator( const self_type & ) {} 69 | */ 70 | 71 | template 72 | b3AlignedAllocator(const b3AlignedAllocator&) 73 | { 74 | } 75 | 76 | typedef const T* const_pointer; 77 | typedef const T& const_reference; 78 | typedef T* pointer; 79 | typedef T& reference; 80 | typedef T value_type; 81 | 82 | pointer address(reference ref) const { return &ref; } 83 | const_pointer address(const_reference ref) const { return &ref; } 84 | pointer allocate(btSizeType n, const_pointer* hint = 0) 85 | { 86 | (void)hint; 87 | return reinterpret_cast(b3AlignedAlloc(sizeof(value_type) * n, Alignment)); 88 | } 89 | void construct(pointer ptr, const value_type& value) { new (ptr) value_type(value); } 90 | void deallocate(pointer ptr) 91 | { 92 | b3AlignedFree(reinterpret_cast(ptr)); 93 | } 94 | void destroy(pointer ptr) { ptr->~value_type(); } 95 | 96 | template 97 | struct rebind 98 | { 99 | typedef b3AlignedAllocator other; 100 | }; 101 | template 102 | self_type& operator=(const b3AlignedAllocator&) 103 | { 104 | return *this; 105 | } 106 | 107 | friend bool operator==(const self_type&, const self_type&) { return true; } 108 | }; 109 | 110 | #endif //B3_ALIGNED_ALLOCATOR 111 | -------------------------------------------------------------------------------- /src/Bullet3Common/b3CommandLineArgs.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMAND_LINE_ARGS_H 2 | #define COMMAND_LINE_ARGS_H 3 | 4 | /****************************************************************************** 5 | * Command-line parsing 6 | ******************************************************************************/ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | class b3CommandLineArgs 13 | { 14 | protected: 15 | std::map pairs; 16 | 17 | public: 18 | // Constructor 19 | b3CommandLineArgs(int argc, char **argv) 20 | { 21 | addArgs(argc, argv); 22 | } 23 | 24 | void addArgs(int argc, char **argv) 25 | { 26 | for (int i = 1; i < argc; i++) 27 | { 28 | std::string arg = argv[i]; 29 | 30 | if ((arg.length() < 2) || (arg[0] != '-') || (arg[1] != '-')) 31 | { 32 | continue; 33 | } 34 | 35 | std::string::size_type pos; 36 | std::string key, val; 37 | if ((pos = arg.find('=')) == std::string::npos) 38 | { 39 | key = std::string(arg, 2, arg.length() - 2); 40 | val = ""; 41 | } 42 | else 43 | { 44 | key = std::string(arg, 2, pos - 2); 45 | val = std::string(arg, pos + 1, arg.length() - 1); 46 | } 47 | 48 | //only add new keys, don't replace existing 49 | if (pairs.find(key) == pairs.end()) 50 | { 51 | pairs[key] = val; 52 | } 53 | } 54 | } 55 | 56 | bool CheckCmdLineFlag(const char *arg_name) 57 | { 58 | std::map::iterator itr; 59 | if ((itr = pairs.find(arg_name)) != pairs.end()) 60 | { 61 | return true; 62 | } 63 | return false; 64 | } 65 | 66 | template 67 | bool GetCmdLineArgument(const char *arg_name, T &val); 68 | 69 | int ParsedArgc() 70 | { 71 | return pairs.size(); 72 | } 73 | }; 74 | 75 | template 76 | inline bool b3CommandLineArgs::GetCmdLineArgument(const char *arg_name, T &val) 77 | { 78 | std::map::iterator itr; 79 | if ((itr = pairs.find(arg_name)) != pairs.end()) 80 | { 81 | std::istringstream strstream(itr->second); 82 | strstream >> val; 83 | return true; 84 | } 85 | return false; 86 | } 87 | 88 | template <> 89 | inline bool b3CommandLineArgs::GetCmdLineArgument(const char *arg_name, char *&val) 90 | { 91 | std::map::iterator itr; 92 | if ((itr = pairs.find(arg_name)) != pairs.end()) 93 | { 94 | std::string s = itr->second; 95 | val = (char *)malloc(sizeof(char) * (s.length() + 1)); 96 | std::strcpy(val, s.c_str()); 97 | return true; 98 | } 99 | else 100 | { 101 | val = NULL; 102 | } 103 | return false; 104 | } 105 | 106 | #endif //COMMAND_LINE_ARGS_H 107 | -------------------------------------------------------------------------------- /src/Bullet3Common/b3FileUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef B3_FILE_UTILS_H 2 | #define B3_FILE_UTILS_H 3 | 4 | #include 5 | #include "b3Scalar.h" 6 | #include //ptrdiff_h 7 | #include 8 | 9 | struct b3FileUtils 10 | { 11 | b3FileUtils() 12 | { 13 | } 14 | virtual ~b3FileUtils() 15 | { 16 | } 17 | 18 | static bool findFile(const char* orgFileName, char* relativeFileName, int maxRelativeFileNameMaxLen) 19 | { 20 | FILE* f = 0; 21 | f = fopen(orgFileName, "rb"); 22 | if (f) 23 | { 24 | //printf("original file found: [%s]\n", orgFileName); 25 | sprintf(relativeFileName, "%s", orgFileName); 26 | fclose(f); 27 | return true; 28 | } 29 | 30 | //printf("Trying various directories, relative to current working directory\n"); 31 | const char* prefix[] = {"./", "./data/", "../data/", "../../data/", "../../../data/", "../../../../data/"}; 32 | int numPrefixes = sizeof(prefix) / sizeof(const char*); 33 | 34 | f = 0; 35 | bool fileFound = false; 36 | 37 | for (int i = 0; !f && i < numPrefixes; i++) 38 | { 39 | #ifdef _MSC_VER 40 | sprintf_s(relativeFileName, maxRelativeFileNameMaxLen, "%s%s", prefix[i], orgFileName); 41 | #else 42 | sprintf(relativeFileName, "%s%s", prefix[i], orgFileName); 43 | #endif 44 | f = fopen(relativeFileName, "rb"); 45 | if (f) 46 | { 47 | fileFound = true; 48 | break; 49 | } 50 | } 51 | if (f) 52 | { 53 | fclose(f); 54 | } 55 | 56 | return fileFound; 57 | } 58 | 59 | static const char* strip2(const char* name, const char* pattern) 60 | { 61 | size_t const patlen = strlen(pattern); 62 | size_t patcnt = 0; 63 | const char* oriptr; 64 | const char* patloc; 65 | // find how many times the pattern occurs in the original string 66 | for (oriptr = name; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen) 67 | { 68 | patcnt++; 69 | } 70 | return oriptr; 71 | } 72 | 73 | static int extractPath(const char* fileName, char* path, int maxPathLength) 74 | { 75 | const char* stripped = strip2(fileName, "/"); 76 | stripped = strip2(stripped, "\\"); 77 | 78 | ptrdiff_t len = stripped - fileName; 79 | b3Assert((len + 1) < maxPathLength); 80 | 81 | if (len && ((len + 1) < maxPathLength)) 82 | { 83 | for (int i = 0; i < len; i++) 84 | { 85 | path[i] = fileName[i]; 86 | } 87 | path[len] = 0; 88 | } 89 | else 90 | { 91 | len = 0; 92 | b3Assert(maxPathLength > 0); 93 | if (maxPathLength > 0) 94 | { 95 | path[len] = 0; 96 | } 97 | } 98 | return len; 99 | } 100 | 101 | static char toLowerChar(const char t) 102 | { 103 | if (t >= (char)'A' && t <= (char)'Z') 104 | return t + ((char)'a' - (char)'A'); 105 | else 106 | return t; 107 | } 108 | 109 | static void toLower(char* str) 110 | { 111 | int len = strlen(str); 112 | for (int i = 0; i < len; i++) 113 | { 114 | str[i] = toLowerChar(str[i]); 115 | } 116 | } 117 | 118 | /*static const char* strip2(const char* name, const char* pattern) 119 | { 120 | size_t const patlen = strlen(pattern); 121 | size_t patcnt = 0; 122 | const char * oriptr; 123 | const char * patloc; 124 | // find how many times the pattern occurs in the original string 125 | for (oriptr = name; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen) 126 | { 127 | patcnt++; 128 | } 129 | return oriptr; 130 | } 131 | */ 132 | }; 133 | #endif //B3_FILE_UTILS_H 134 | -------------------------------------------------------------------------------- /src/Bullet3Common/b3Logging.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Advanced Micro Devices, Inc. 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | //Originally written by Erwin Coumans 15 | 16 | #include "b3Logging.h" 17 | 18 | #include 19 | #include 20 | 21 | #ifdef _WIN32 22 | #include 23 | #endif //_WIN32 24 | 25 | void b3PrintfFuncDefault(const char* msg) 26 | { 27 | #ifdef _WIN32 28 | OutputDebugStringA(msg); 29 | #endif 30 | printf("%s", msg); 31 | //is this portable? 32 | fflush(stdout); 33 | } 34 | 35 | void b3WarningMessageFuncDefault(const char* msg) 36 | { 37 | #ifdef _WIN32 38 | OutputDebugStringA(msg); 39 | #endif 40 | printf("%s", msg); 41 | //is this portable? 42 | fflush(stdout); 43 | } 44 | 45 | void b3ErrorMessageFuncDefault(const char* msg) 46 | { 47 | #ifdef _WIN32 48 | OutputDebugStringA(msg); 49 | #endif 50 | printf("%s", msg); 51 | 52 | //is this portable? 53 | fflush(stdout); 54 | } 55 | 56 | static b3PrintfFunc* b3s_printfFunc = b3PrintfFuncDefault; 57 | static b3WarningMessageFunc* b3s_warningMessageFunc = b3WarningMessageFuncDefault; 58 | static b3ErrorMessageFunc* b3s_errorMessageFunc = b3ErrorMessageFuncDefault; 59 | 60 | ///The developer can route b3Printf output using their own implementation 61 | void b3SetCustomPrintfFunc(b3PrintfFunc* printfFunc) 62 | { 63 | b3s_printfFunc = printfFunc; 64 | } 65 | void b3SetCustomWarningMessageFunc(b3PrintfFunc* warningMessageFunc) 66 | { 67 | b3s_warningMessageFunc = warningMessageFunc; 68 | } 69 | void b3SetCustomErrorMessageFunc(b3PrintfFunc* errorMessageFunc) 70 | { 71 | b3s_errorMessageFunc = errorMessageFunc; 72 | } 73 | 74 | //#define B3_MAX_DEBUG_STRING_LENGTH 2048 75 | #define B3_MAX_DEBUG_STRING_LENGTH 32768 76 | 77 | void b3OutputPrintfVarArgsInternal(const char* str, ...) 78 | { 79 | char strDebug[B3_MAX_DEBUG_STRING_LENGTH] = {0}; 80 | va_list argList; 81 | va_start(argList, str); 82 | #ifdef _MSC_VER 83 | vsprintf_s(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList); 84 | #else 85 | vsnprintf(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList); 86 | #endif 87 | (b3s_printfFunc)(strDebug); 88 | va_end(argList); 89 | } 90 | void b3OutputWarningMessageVarArgsInternal(const char* str, ...) 91 | { 92 | char strDebug[B3_MAX_DEBUG_STRING_LENGTH] = {0}; 93 | va_list argList; 94 | va_start(argList, str); 95 | #ifdef _MSC_VER 96 | vsprintf_s(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList); 97 | #else 98 | vsnprintf(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList); 99 | #endif 100 | (b3s_warningMessageFunc)(strDebug); 101 | va_end(argList); 102 | } 103 | void b3OutputErrorMessageVarArgsInternal(const char* str, ...) 104 | { 105 | char strDebug[B3_MAX_DEBUG_STRING_LENGTH] = {0}; 106 | va_list argList; 107 | va_start(argList, str); 108 | #ifdef _MSC_VER 109 | vsprintf_s(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList); 110 | #else 111 | vsnprintf(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList); 112 | #endif 113 | (b3s_errorMessageFunc)(strDebug); 114 | va_end(argList); 115 | } 116 | 117 | void b3EnterProfileZoneDefault(const char* name) 118 | { 119 | } 120 | void b3LeaveProfileZoneDefault() 121 | { 122 | } 123 | static b3EnterProfileZoneFunc* b3s_enterFunc = b3EnterProfileZoneDefault; 124 | static b3LeaveProfileZoneFunc* b3s_leaveFunc = b3LeaveProfileZoneDefault; 125 | void b3EnterProfileZone(const char* name) 126 | { 127 | (b3s_enterFunc)(name); 128 | } 129 | void b3LeaveProfileZone() 130 | { 131 | (b3s_leaveFunc)(); 132 | } 133 | 134 | void b3SetCustomEnterProfileZoneFunc(b3EnterProfileZoneFunc* enterFunc) 135 | { 136 | b3s_enterFunc = enterFunc; 137 | } 138 | void b3SetCustomLeaveProfileZoneFunc(b3LeaveProfileZoneFunc* leaveFunc) 139 | { 140 | b3s_leaveFunc = leaveFunc; 141 | } 142 | 143 | #ifndef _MSC_VER 144 | #undef vsprintf_s 145 | #endif 146 | -------------------------------------------------------------------------------- /src/Bullet3Common/b3Logging.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef B3_LOGGING_H 3 | #define B3_LOGGING_H 4 | 5 | #ifdef __cplusplus 6 | extern "C" 7 | { 8 | #endif 9 | 10 | ///We add the do/while so that the statement "if (condition) b3Printf("test"); else {...}" would fail 11 | ///You can also customize the message by uncommenting out a different line below 12 | #define b3Printf(...) b3OutputPrintfVarArgsInternal(__VA_ARGS__) 13 | //#define b3Printf(...) do {b3OutputPrintfVarArgsInternal("b3Printf[%s,%d]:",__FILE__,__LINE__);b3OutputPrintfVarArgsInternal(__VA_ARGS__); } while(0) 14 | //#define b3Printf b3OutputPrintfVarArgsInternal 15 | //#define b3Printf(...) printf(__VA_ARGS__) 16 | //#define b3Printf(...) 17 | #define b3Warning(...) do{ b3OutputWarningMessageVarArgsInternal("b3Warning[%s,%d]:\n", __FILE__, __LINE__);b3OutputWarningMessageVarArgsInternal(__VA_ARGS__);} while (0) 18 | #define b3Error(...)do {b3OutputErrorMessageVarArgsInternal("b3Error[%s,%d]:\n", __FILE__, __LINE__);b3OutputErrorMessageVarArgsInternal(__VA_ARGS__);} while (0) 19 | #ifndef B3_NO_PROFILE 20 | 21 | void b3EnterProfileZone(const char* name); 22 | void b3LeaveProfileZone(); 23 | #ifdef __cplusplus 24 | 25 | class b3ProfileZone 26 | { 27 | public: 28 | b3ProfileZone(const char* name) 29 | { 30 | b3EnterProfileZone(name); 31 | } 32 | 33 | ~b3ProfileZone() 34 | { 35 | b3LeaveProfileZone(); 36 | } 37 | }; 38 | 39 | #define B3_PROFILE(name) b3ProfileZone __profile(name) 40 | #endif 41 | 42 | #else //B3_NO_PROFILE 43 | 44 | #define B3_PROFILE(name) 45 | #define b3StartProfile(a) 46 | #define b3StopProfile 47 | 48 | #endif //#ifndef B3_NO_PROFILE 49 | 50 | typedef void(b3PrintfFunc)(const char* msg); 51 | typedef void(b3WarningMessageFunc)(const char* msg); 52 | typedef void(b3ErrorMessageFunc)(const char* msg); 53 | typedef void(b3EnterProfileZoneFunc)(const char* msg); 54 | typedef void(b3LeaveProfileZoneFunc)(); 55 | 56 | ///The developer can route b3Printf output using their own implementation 57 | void b3SetCustomPrintfFunc(b3PrintfFunc* printfFunc); 58 | void b3SetCustomWarningMessageFunc(b3WarningMessageFunc* warningMsgFunc); 59 | void b3SetCustomErrorMessageFunc(b3ErrorMessageFunc* errorMsgFunc); 60 | 61 | ///Set custom profile zone functions (zones can be nested) 62 | void b3SetCustomEnterProfileZoneFunc(b3EnterProfileZoneFunc* enterFunc); 63 | void b3SetCustomLeaveProfileZoneFunc(b3LeaveProfileZoneFunc* leaveFunc); 64 | 65 | ///Don't use those internal functions directly, use the b3Printf or b3SetCustomPrintfFunc instead (or warning/error version) 66 | void b3OutputPrintfVarArgsInternal(const char* str, ...); 67 | void b3OutputWarningMessageVarArgsInternal(const char* str, ...); 68 | void b3OutputErrorMessageVarArgsInternal(const char* str, ...); 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | 74 | #endif //B3_LOGGING_H -------------------------------------------------------------------------------- /src/Bullet3Common/b3MinMax.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | #ifndef B3_GEN_MINMAX_H 16 | #define B3_GEN_MINMAX_H 17 | 18 | #include "b3Scalar.h" 19 | 20 | template 21 | B3_FORCE_INLINE const T& b3Min(const T& a, const T& b) 22 | { 23 | return a < b ? a : b; 24 | } 25 | 26 | template 27 | B3_FORCE_INLINE const T& b3Max(const T& a, const T& b) 28 | { 29 | return a > b ? a : b; 30 | } 31 | 32 | template 33 | B3_FORCE_INLINE const T& b3Clamped(const T& a, const T& lb, const T& ub) 34 | { 35 | return a < lb ? lb : (ub < a ? ub : a); 36 | } 37 | 38 | template 39 | B3_FORCE_INLINE void b3SetMin(T& a, const T& b) 40 | { 41 | if (b < a) 42 | { 43 | a = b; 44 | } 45 | } 46 | 47 | template 48 | B3_FORCE_INLINE void b3SetMax(T& a, const T& b) 49 | { 50 | if (a < b) 51 | { 52 | a = b; 53 | } 54 | } 55 | 56 | template 57 | B3_FORCE_INLINE void b3Clamp(T& a, const T& lb, const T& ub) 58 | { 59 | if (a < lb) 60 | { 61 | a = lb; 62 | } 63 | else if (ub < a) 64 | { 65 | a = ub; 66 | } 67 | } 68 | 69 | #endif //B3_GEN_MINMAX_H 70 | -------------------------------------------------------------------------------- /src/Bullet3Common/b3PoolAllocator.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | #ifndef _BT_POOL_ALLOCATOR_H 16 | #define _BT_POOL_ALLOCATOR_H 17 | 18 | #include "b3Scalar.h" 19 | #include "b3AlignedAllocator.h" 20 | 21 | ///The b3PoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately. 22 | class b3PoolAllocator 23 | { 24 | int m_elemSize; 25 | int m_maxElements; 26 | int m_freeCount; 27 | void* m_firstFree; 28 | unsigned char* m_pool; 29 | 30 | public: 31 | b3PoolAllocator(int elemSize, int maxElements) 32 | : m_elemSize(elemSize), 33 | m_maxElements(maxElements) 34 | { 35 | m_pool = (unsigned char*)b3AlignedAlloc(static_cast(m_elemSize * m_maxElements), 16); 36 | 37 | unsigned char* p = m_pool; 38 | m_firstFree = p; 39 | m_freeCount = m_maxElements; 40 | int count = m_maxElements; 41 | while (--count) 42 | { 43 | *(void**)p = (p + m_elemSize); 44 | p += m_elemSize; 45 | } 46 | *(void**)p = 0; 47 | } 48 | 49 | ~b3PoolAllocator() 50 | { 51 | b3AlignedFree(m_pool); 52 | } 53 | 54 | int getFreeCount() const 55 | { 56 | return m_freeCount; 57 | } 58 | 59 | int getUsedCount() const 60 | { 61 | return m_maxElements - m_freeCount; 62 | } 63 | 64 | int getMaxCount() const 65 | { 66 | return m_maxElements; 67 | } 68 | 69 | void* allocate(int size) 70 | { 71 | // release mode fix 72 | (void)size; 73 | b3Assert(!size || size <= m_elemSize); 74 | b3Assert(m_freeCount > 0); 75 | void* result = m_firstFree; 76 | m_firstFree = *(void**)m_firstFree; 77 | --m_freeCount; 78 | return result; 79 | } 80 | 81 | bool validPtr(void* ptr) 82 | { 83 | if (ptr) 84 | { 85 | if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize)) 86 | { 87 | return true; 88 | } 89 | } 90 | return false; 91 | } 92 | 93 | void freeMemory(void* ptr) 94 | { 95 | if (ptr) 96 | { 97 | b3Assert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize); 98 | 99 | *(void**)ptr = m_firstFree; 100 | m_firstFree = ptr; 101 | ++m_freeCount; 102 | } 103 | } 104 | 105 | int getElementSize() const 106 | { 107 | return m_elemSize; 108 | } 109 | 110 | unsigned char* getPoolAddress() 111 | { 112 | return m_pool; 113 | } 114 | 115 | const unsigned char* getPoolAddress() const 116 | { 117 | return m_pool; 118 | } 119 | }; 120 | 121 | #endif //_BT_POOL_ALLOCATOR_H 122 | -------------------------------------------------------------------------------- /src/Bullet3Common/b3Random.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | #ifndef B3_GEN_RANDOM_H 16 | #define B3_GEN_RANDOM_H 17 | 18 | #include "b3Scalar.h" 19 | 20 | #ifdef MT19937 21 | 22 | #include 23 | #include 24 | 25 | #define B3_RAND_MAX UINT_MAX 26 | 27 | B3_FORCE_INLINE void b3Srand(unsigned int seed) { init_genrand(seed); } 28 | B3_FORCE_INLINE unsigned int b3rand() { return genrand_int32(); } 29 | 30 | #else 31 | 32 | #include 33 | 34 | #define B3_RAND_MAX RAND_MAX 35 | 36 | B3_FORCE_INLINE void b3Srand(unsigned int seed) { srand(seed); } 37 | B3_FORCE_INLINE unsigned int b3rand() { return rand(); } 38 | 39 | #endif 40 | 41 | inline b3Scalar b3RandRange(b3Scalar minRange, b3Scalar maxRange) 42 | { 43 | return (b3rand() / (b3Scalar(B3_RAND_MAX) + b3Scalar(1.0))) * (maxRange - minRange) + minRange; 44 | } 45 | 46 | #endif //B3_GEN_RANDOM_H 47 | -------------------------------------------------------------------------------- /src/Bullet3Common/b3ResizablePool.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef B3_RESIZABLE_POOL_H 3 | #define B3_RESIZABLE_POOL_H 4 | 5 | #include "Bullet3Common/b3AlignedObjectArray.h" 6 | 7 | enum 8 | { 9 | B3_POOL_HANDLE_TERMINAL_FREE = -1, 10 | B3_POOL_HANDLE_TERMINAL_USED = -2 11 | }; 12 | 13 | template 14 | struct b3PoolBodyHandle : public U 15 | { 16 | B3_DECLARE_ALIGNED_ALLOCATOR(); 17 | 18 | int m_nextFreeHandle; 19 | void setNextFree(int next) 20 | { 21 | m_nextFreeHandle = next; 22 | } 23 | int getNextFree() const 24 | { 25 | return m_nextFreeHandle; 26 | } 27 | }; 28 | 29 | template 30 | class b3ResizablePool 31 | { 32 | protected: 33 | b3AlignedObjectArray m_bodyHandles; 34 | int m_numUsedHandles; // number of active handles 35 | int m_firstFreeHandle; // free handles list 36 | 37 | T* getHandleInternal(int handle) 38 | { 39 | return &m_bodyHandles[handle]; 40 | } 41 | const T* getHandleInternal(int handle) const 42 | { 43 | return &m_bodyHandles[handle]; 44 | } 45 | 46 | public: 47 | b3ResizablePool() 48 | { 49 | initHandles(); 50 | } 51 | 52 | virtual ~b3ResizablePool() 53 | { 54 | exitHandles(); 55 | } 56 | ///handle management 57 | 58 | int getNumHandles() const 59 | { 60 | return m_bodyHandles.size(); 61 | } 62 | 63 | void getUsedHandles(b3AlignedObjectArray& usedHandles) const 64 | { 65 | for (int i = 0; i < m_bodyHandles.size(); i++) 66 | { 67 | if (m_bodyHandles[i].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED) 68 | { 69 | usedHandles.push_back(i); 70 | } 71 | } 72 | } 73 | 74 | T* getHandle(int handle) 75 | { 76 | b3Assert(handle >= 0); 77 | b3Assert(handle < m_bodyHandles.size()); 78 | if ((handle < 0) || (handle >= m_bodyHandles.size())) 79 | { 80 | return 0; 81 | } 82 | 83 | if (m_bodyHandles[handle].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED) 84 | { 85 | return &m_bodyHandles[handle]; 86 | } 87 | return 0; 88 | } 89 | const T* getHandle(int handle) const 90 | { 91 | b3Assert(handle >= 0); 92 | b3Assert(handle < m_bodyHandles.size()); 93 | if ((handle < 0) || (handle >= m_bodyHandles.size())) 94 | { 95 | return 0; 96 | } 97 | 98 | if (m_bodyHandles[handle].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED) 99 | { 100 | return &m_bodyHandles[handle]; 101 | } 102 | return 0; 103 | } 104 | 105 | void increaseHandleCapacity(int extraCapacity) 106 | { 107 | int curCapacity = m_bodyHandles.size(); 108 | //b3Assert(curCapacity == m_numUsedHandles); 109 | int newCapacity = curCapacity + extraCapacity; 110 | m_bodyHandles.resize(newCapacity); 111 | 112 | { 113 | for (int i = curCapacity; i < newCapacity; i++) 114 | m_bodyHandles[i].setNextFree(i + 1); 115 | 116 | m_bodyHandles[newCapacity - 1].setNextFree(-1); 117 | } 118 | m_firstFreeHandle = curCapacity; 119 | } 120 | void initHandles() 121 | { 122 | m_numUsedHandles = 0; 123 | m_firstFreeHandle = -1; 124 | 125 | increaseHandleCapacity(1); 126 | } 127 | 128 | void exitHandles() 129 | { 130 | m_bodyHandles.resize(0); 131 | m_firstFreeHandle = -1; 132 | m_numUsedHandles = 0; 133 | } 134 | 135 | int allocHandle() 136 | { 137 | b3Assert(m_firstFreeHandle >= 0); 138 | 139 | int handle = m_firstFreeHandle; 140 | m_firstFreeHandle = getHandleInternal(handle)->getNextFree(); 141 | m_numUsedHandles++; 142 | 143 | if (m_firstFreeHandle < 0) 144 | { 145 | //int curCapacity = m_bodyHandles.size(); 146 | int additionalCapacity = m_bodyHandles.size(); 147 | increaseHandleCapacity(additionalCapacity); 148 | 149 | getHandleInternal(handle)->setNextFree(m_firstFreeHandle); 150 | } 151 | getHandleInternal(handle)->setNextFree(B3_POOL_HANDLE_TERMINAL_USED); 152 | getHandleInternal(handle)->clear(); 153 | return handle; 154 | } 155 | 156 | void freeHandle(int handle) 157 | { 158 | b3Assert(handle >= 0); 159 | 160 | if (m_bodyHandles[handle].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED) 161 | { 162 | getHandleInternal(handle)->clear(); 163 | getHandleInternal(handle)->setNextFree(m_firstFreeHandle); 164 | m_firstFreeHandle = handle; 165 | m_numUsedHandles--; 166 | } 167 | } 168 | }; 169 | ///end handle management 170 | 171 | #endif //B3_RESIZABLE_POOL_H 172 | -------------------------------------------------------------------------------- /src/Bullet3Common/b3StackAlloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | /* 16 | StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson 17 | Nov.2006 18 | */ 19 | 20 | #ifndef B3_STACK_ALLOC 21 | #define B3_STACK_ALLOC 22 | 23 | #include "b3Scalar.h" //for b3Assert 24 | #include "b3AlignedAllocator.h" 25 | 26 | ///The b3Block class is an internal structure for the b3StackAlloc memory allocator. 27 | struct b3Block 28 | { 29 | b3Block* previous; 30 | unsigned char* address; 31 | }; 32 | 33 | ///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out) 34 | class b3StackAlloc 35 | { 36 | public: 37 | b3StackAlloc(unsigned int size) 38 | { 39 | ctor(); 40 | create(size); 41 | } 42 | ~b3StackAlloc() { destroy(); } 43 | 44 | inline void create(unsigned int size) 45 | { 46 | destroy(); 47 | data = (unsigned char*)b3AlignedAlloc(size, 16); 48 | totalsize = size; 49 | } 50 | inline void destroy() 51 | { 52 | b3Assert(usedsize == 0); 53 | //Raise(L"StackAlloc is still in use"); 54 | 55 | if (usedsize == 0) 56 | { 57 | if (!ischild && data) 58 | b3AlignedFree(data); 59 | 60 | data = 0; 61 | usedsize = 0; 62 | } 63 | } 64 | 65 | int getAvailableMemory() const 66 | { 67 | return static_cast(totalsize - usedsize); 68 | } 69 | 70 | unsigned char* allocate(unsigned int size) 71 | { 72 | const unsigned int nus(usedsize + size); 73 | if (nus < totalsize) 74 | { 75 | usedsize = nus; 76 | return (data + (usedsize - size)); 77 | } 78 | b3Assert(0); 79 | //&& (L"Not enough memory")); 80 | 81 | return (0); 82 | } 83 | B3_FORCE_INLINE b3Block* beginBlock() 84 | { 85 | b3Block* pb = (b3Block*)allocate(sizeof(b3Block)); 86 | pb->previous = current; 87 | pb->address = data + usedsize; 88 | current = pb; 89 | return (pb); 90 | } 91 | B3_FORCE_INLINE void endBlock(b3Block* block) 92 | { 93 | b3Assert(block == current); 94 | //Raise(L"Unmatched blocks"); 95 | if (block == current) 96 | { 97 | current = block->previous; 98 | usedsize = (unsigned int)((block->address - data) - sizeof(b3Block)); 99 | } 100 | } 101 | 102 | private: 103 | void ctor() 104 | { 105 | data = 0; 106 | totalsize = 0; 107 | usedsize = 0; 108 | current = 0; 109 | ischild = false; 110 | } 111 | unsigned char* data; 112 | unsigned int totalsize; 113 | unsigned int usedsize; 114 | b3Block* current; 115 | bool ischild; 116 | }; 117 | 118 | #endif //B3_STACK_ALLOC 119 | -------------------------------------------------------------------------------- /src/Bullet3Common/shared/b3Float4.h: -------------------------------------------------------------------------------- 1 | #ifndef B3_FLOAT4_H 2 | #define B3_FLOAT4_H 3 | 4 | #include "Bullet3Common/shared/b3PlatformDefinitions.h" 5 | 6 | #ifdef __cplusplus 7 | #include "Bullet3Common/b3Vector3.h" 8 | #define b3Float4 b3Vector3 9 | #define b3Float4ConstArg const b3Vector3& 10 | #define b3Dot3F4 b3Dot 11 | #define b3Cross3 b3Cross 12 | #define b3MakeFloat4 b3MakeVector3 13 | inline b3Vector3 b3Normalized(const b3Vector3& vec) 14 | { 15 | return vec.normalized(); 16 | } 17 | 18 | inline b3Float4 b3FastNormalized3(b3Float4ConstArg v) 19 | { 20 | return v.normalized(); 21 | } 22 | 23 | inline b3Float4 b3MaxFloat4(const b3Float4& a, const b3Float4& b) 24 | { 25 | b3Float4 tmp = a; 26 | tmp.setMax(b); 27 | return tmp; 28 | } 29 | inline b3Float4 b3MinFloat4(const b3Float4& a, const b3Float4& b) 30 | { 31 | b3Float4 tmp = a; 32 | tmp.setMin(b); 33 | return tmp; 34 | } 35 | 36 | #else 37 | typedef float4 b3Float4; 38 | #define b3Float4ConstArg const b3Float4 39 | #define b3MakeFloat4 (float4) 40 | float b3Dot3F4(b3Float4ConstArg v0, b3Float4ConstArg v1) 41 | { 42 | float4 a1 = b3MakeFloat4(v0.xyz, 0.f); 43 | float4 b1 = b3MakeFloat4(v1.xyz, 0.f); 44 | return dot(a1, b1); 45 | } 46 | b3Float4 b3Cross3(b3Float4ConstArg v0, b3Float4ConstArg v1) 47 | { 48 | float4 a1 = b3MakeFloat4(v0.xyz, 0.f); 49 | float4 b1 = b3MakeFloat4(v1.xyz, 0.f); 50 | return cross(a1, b1); 51 | } 52 | #define b3MinFloat4 min 53 | #define b3MaxFloat4 max 54 | 55 | #define b3Normalized(a) normalize(a) 56 | 57 | #endif 58 | 59 | inline bool b3IsAlmostZero(b3Float4ConstArg v) 60 | { 61 | if (b3Fabs(v.x) > 1e-6 || b3Fabs(v.y) > 1e-6 || b3Fabs(v.z) > 1e-6) 62 | return false; 63 | return true; 64 | } 65 | 66 | inline int b3MaxDot(b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut) 67 | { 68 | float maxDot = -B3_INFINITY; 69 | int i = 0; 70 | int ptIndex = -1; 71 | for (i = 0; i < vecLen; i++) 72 | { 73 | float dot = b3Dot3F4(vecArray[i], vec); 74 | 75 | if (dot > maxDot) 76 | { 77 | maxDot = dot; 78 | ptIndex = i; 79 | } 80 | } 81 | b3Assert(ptIndex >= 0); 82 | if (ptIndex < 0) 83 | { 84 | ptIndex = 0; 85 | } 86 | *dotOut = maxDot; 87 | return ptIndex; 88 | } 89 | 90 | #endif //B3_FLOAT4_H 91 | -------------------------------------------------------------------------------- /src/Bullet3Common/shared/b3Int2.h: -------------------------------------------------------------------------------- 1 | /* 2 | Bullet Continuous Collision Detection and Physics Library 3 | Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #ifndef B3_INT2_H 17 | #define B3_INT2_H 18 | 19 | #ifdef __cplusplus 20 | 21 | struct b3UnsignedInt2 22 | { 23 | union { 24 | struct 25 | { 26 | unsigned int x, y; 27 | }; 28 | struct 29 | { 30 | unsigned int s[2]; 31 | }; 32 | }; 33 | }; 34 | 35 | struct b3Int2 36 | { 37 | union { 38 | struct 39 | { 40 | int x, y; 41 | }; 42 | struct 43 | { 44 | int s[2]; 45 | }; 46 | }; 47 | }; 48 | 49 | inline b3Int2 b3MakeInt2(int x, int y) 50 | { 51 | b3Int2 v; 52 | v.s[0] = x; 53 | v.s[1] = y; 54 | return v; 55 | } 56 | #else 57 | 58 | #define b3UnsignedInt2 uint2 59 | #define b3Int2 int2 60 | #define b3MakeInt2 (int2) 61 | 62 | #endif //__cplusplus 63 | #endif -------------------------------------------------------------------------------- /src/Bullet3Common/shared/b3Int4.h: -------------------------------------------------------------------------------- 1 | #ifndef B3_INT4_H 2 | #define B3_INT4_H 3 | 4 | #ifdef __cplusplus 5 | 6 | #include "Bullet3Common/b3Scalar.h" 7 | 8 | B3_ATTRIBUTE_ALIGNED16(struct) 9 | b3UnsignedInt4 10 | { 11 | B3_DECLARE_ALIGNED_ALLOCATOR(); 12 | 13 | union { 14 | struct 15 | { 16 | unsigned int x, y, z, w; 17 | }; 18 | struct 19 | { 20 | unsigned int s[4]; 21 | }; 22 | }; 23 | }; 24 | 25 | B3_ATTRIBUTE_ALIGNED16(struct) 26 | b3Int4 27 | { 28 | B3_DECLARE_ALIGNED_ALLOCATOR(); 29 | 30 | union { 31 | struct 32 | { 33 | int x, y, z, w; 34 | }; 35 | struct 36 | { 37 | int s[4]; 38 | }; 39 | }; 40 | }; 41 | 42 | B3_FORCE_INLINE b3Int4 b3MakeInt4(int x, int y, int z, int w = 0) 43 | { 44 | b3Int4 v; 45 | v.s[0] = x; 46 | v.s[1] = y; 47 | v.s[2] = z; 48 | v.s[3] = w; 49 | return v; 50 | } 51 | 52 | B3_FORCE_INLINE b3UnsignedInt4 b3MakeUnsignedInt4(unsigned int x, unsigned int y, unsigned int z, unsigned int w = 0) 53 | { 54 | b3UnsignedInt4 v; 55 | v.s[0] = x; 56 | v.s[1] = y; 57 | v.s[2] = z; 58 | v.s[3] = w; 59 | return v; 60 | } 61 | 62 | #else 63 | 64 | #define b3UnsignedInt4 uint4 65 | #define b3Int4 int4 66 | #define b3MakeInt4 (int4) 67 | #define b3MakeUnsignedInt4 (uint4) 68 | 69 | #endif //__cplusplus 70 | 71 | #endif //B3_INT4_H 72 | -------------------------------------------------------------------------------- /src/Bullet3Common/shared/b3Mat3x3.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef B3_MAT3x3_H 3 | #define B3_MAT3x3_H 4 | 5 | #include "Bullet3Common/shared/b3Quat.h" 6 | 7 | #ifdef __cplusplus 8 | 9 | #include "Bullet3Common/b3Matrix3x3.h" 10 | 11 | #define b3Mat3x3 b3Matrix3x3 12 | #define b3Mat3x3ConstArg const b3Matrix3x3& 13 | 14 | inline b3Mat3x3 b3QuatGetRotationMatrix(b3QuatConstArg quat) 15 | { 16 | return b3Mat3x3(quat); 17 | } 18 | 19 | inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg mat) 20 | { 21 | return mat.absolute(); 22 | } 23 | 24 | #define b3GetRow(m, row) m.getRow(row) 25 | 26 | __inline b3Float4 mtMul3(b3Float4ConstArg a, b3Mat3x3ConstArg b) 27 | { 28 | return b * a; 29 | } 30 | 31 | #else 32 | 33 | typedef struct 34 | { 35 | b3Float4 m_row[3]; 36 | } b3Mat3x3; 37 | 38 | #define b3Mat3x3ConstArg const b3Mat3x3 39 | #define b3GetRow(m, row) (m.m_row[row]) 40 | 41 | inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat) 42 | { 43 | b3Float4 quat2 = (b3Float4)(quat.x * quat.x, quat.y * quat.y, quat.z * quat.z, 0.f); 44 | b3Mat3x3 out; 45 | 46 | out.m_row[0].x = 1 - 2 * quat2.y - 2 * quat2.z; 47 | out.m_row[0].y = 2 * quat.x * quat.y - 2 * quat.w * quat.z; 48 | out.m_row[0].z = 2 * quat.x * quat.z + 2 * quat.w * quat.y; 49 | out.m_row[0].w = 0.f; 50 | 51 | out.m_row[1].x = 2 * quat.x * quat.y + 2 * quat.w * quat.z; 52 | out.m_row[1].y = 1 - 2 * quat2.x - 2 * quat2.z; 53 | out.m_row[1].z = 2 * quat.y * quat.z - 2 * quat.w * quat.x; 54 | out.m_row[1].w = 0.f; 55 | 56 | out.m_row[2].x = 2 * quat.x * quat.z - 2 * quat.w * quat.y; 57 | out.m_row[2].y = 2 * quat.y * quat.z + 2 * quat.w * quat.x; 58 | out.m_row[2].z = 1 - 2 * quat2.x - 2 * quat2.y; 59 | out.m_row[2].w = 0.f; 60 | 61 | return out; 62 | } 63 | 64 | inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn) 65 | { 66 | b3Mat3x3 out; 67 | out.m_row[0] = fabs(matIn.m_row[0]); 68 | out.m_row[1] = fabs(matIn.m_row[1]); 69 | out.m_row[2] = fabs(matIn.m_row[2]); 70 | return out; 71 | } 72 | 73 | __inline b3Mat3x3 mtZero(); 74 | 75 | __inline b3Mat3x3 mtIdentity(); 76 | 77 | __inline b3Mat3x3 mtTranspose(b3Mat3x3 m); 78 | 79 | __inline b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b); 80 | 81 | __inline b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b); 82 | 83 | __inline b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b); 84 | 85 | __inline b3Mat3x3 mtZero() 86 | { 87 | b3Mat3x3 m; 88 | m.m_row[0] = (b3Float4)(0.f); 89 | m.m_row[1] = (b3Float4)(0.f); 90 | m.m_row[2] = (b3Float4)(0.f); 91 | return m; 92 | } 93 | 94 | __inline b3Mat3x3 mtIdentity() 95 | { 96 | b3Mat3x3 m; 97 | m.m_row[0] = (b3Float4)(1, 0, 0, 0); 98 | m.m_row[1] = (b3Float4)(0, 1, 0, 0); 99 | m.m_row[2] = (b3Float4)(0, 0, 1, 0); 100 | return m; 101 | } 102 | 103 | __inline b3Mat3x3 mtTranspose(b3Mat3x3 m) 104 | { 105 | b3Mat3x3 out; 106 | out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f); 107 | out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f); 108 | out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f); 109 | return out; 110 | } 111 | 112 | __inline b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b) 113 | { 114 | b3Mat3x3 transB; 115 | transB = mtTranspose(b); 116 | b3Mat3x3 ans; 117 | // why this doesn't run when 0ing in the for{} 118 | a.m_row[0].w = 0.f; 119 | a.m_row[1].w = 0.f; 120 | a.m_row[2].w = 0.f; 121 | for (int i = 0; i < 3; i++) 122 | { 123 | // a.m_row[i].w = 0.f; 124 | ans.m_row[i].x = b3Dot3F4(a.m_row[i], transB.m_row[0]); 125 | ans.m_row[i].y = b3Dot3F4(a.m_row[i], transB.m_row[1]); 126 | ans.m_row[i].z = b3Dot3F4(a.m_row[i], transB.m_row[2]); 127 | ans.m_row[i].w = 0.f; 128 | } 129 | return ans; 130 | } 131 | 132 | __inline b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b) 133 | { 134 | b3Float4 ans; 135 | ans.x = b3Dot3F4(a.m_row[0], b); 136 | ans.y = b3Dot3F4(a.m_row[1], b); 137 | ans.z = b3Dot3F4(a.m_row[2], b); 138 | ans.w = 0.f; 139 | return ans; 140 | } 141 | 142 | __inline b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b) 143 | { 144 | b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0); 145 | b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0); 146 | b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0); 147 | 148 | b3Float4 ans; 149 | ans.x = b3Dot3F4(a, colx); 150 | ans.y = b3Dot3F4(a, coly); 151 | ans.z = b3Dot3F4(a, colz); 152 | return ans; 153 | } 154 | 155 | #endif 156 | 157 | #endif //B3_MAT3x3_H 158 | -------------------------------------------------------------------------------- /src/Bullet3Common/shared/b3PlatformDefinitions.h: -------------------------------------------------------------------------------- 1 | #ifndef B3_PLATFORM_DEFINITIONS_H 2 | #define B3_PLATFORM_DEFINITIONS_H 3 | 4 | struct MyTest 5 | { 6 | int bla; 7 | }; 8 | 9 | #ifdef __cplusplus 10 | //#define b3ConstArray(a) const b3AlignedObjectArray& 11 | #define b3ConstArray(a) const a * 12 | #define b3AtomicInc(a) ((*a)++) 13 | 14 | inline int b3AtomicAdd(volatile int *p, int val) 15 | { 16 | int oldValue = *p; 17 | int newValue = oldValue + val; 18 | *p = newValue; 19 | return oldValue; 20 | } 21 | 22 | #define __global 23 | 24 | #define B3_STATIC static 25 | #else 26 | //keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX 27 | #define B3_LARGE_FLOAT 1e18f 28 | #define B3_INFINITY 1e18f 29 | #define b3Assert(a) 30 | #define b3ConstArray(a) __global const a * 31 | #define b3AtomicInc atomic_inc 32 | #define b3AtomicAdd atomic_add 33 | #define b3Fabs fabs 34 | #define b3Sqrt native_sqrt 35 | #define b3Sin native_sin 36 | #define b3Cos native_cos 37 | 38 | #define B3_STATIC 39 | #endif 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/Bullet3Common/shared/b3Quat.h: -------------------------------------------------------------------------------- 1 | #ifndef B3_QUAT_H 2 | #define B3_QUAT_H 3 | 4 | #include "Bullet3Common/shared/b3PlatformDefinitions.h" 5 | #include "Bullet3Common/shared/b3Float4.h" 6 | 7 | #ifdef __cplusplus 8 | #include "Bullet3Common/b3Quaternion.h" 9 | #include "Bullet3Common/b3Transform.h" 10 | 11 | #define b3Quat b3Quaternion 12 | #define b3QuatConstArg const b3Quaternion& 13 | inline b3Quat b3QuatInverse(b3QuatConstArg orn) 14 | { 15 | return orn.inverse(); 16 | } 17 | 18 | inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation) 19 | { 20 | b3Transform tr; 21 | tr.setOrigin(translation); 22 | tr.setRotation(orientation); 23 | return tr(point); 24 | } 25 | 26 | #else 27 | typedef float4 b3Quat; 28 | #define b3QuatConstArg const b3Quat 29 | 30 | inline float4 b3FastNormalize4(float4 v) 31 | { 32 | v = (float4)(v.xyz, 0.f); 33 | return fast_normalize(v); 34 | } 35 | 36 | inline b3Quat b3QuatMul(b3Quat a, b3Quat b); 37 | inline b3Quat b3QuatNormalized(b3QuatConstArg in); 38 | inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec); 39 | inline b3Quat b3QuatInvert(b3QuatConstArg q); 40 | inline b3Quat b3QuatInverse(b3QuatConstArg q); 41 | 42 | inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b) 43 | { 44 | b3Quat ans; 45 | ans = b3Cross3(a, b); 46 | ans += a.w * b + b.w * a; 47 | // ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z); 48 | ans.w = a.w * b.w - b3Dot3F4(a, b); 49 | return ans; 50 | } 51 | 52 | inline b3Quat b3QuatNormalized(b3QuatConstArg in) 53 | { 54 | b3Quat q; 55 | q = in; 56 | //return b3FastNormalize4(in); 57 | float len = native_sqrt(dot(q, q)); 58 | if (len > 0.f) 59 | { 60 | q *= 1.f / len; 61 | } 62 | else 63 | { 64 | q.x = q.y = q.z = 0.f; 65 | q.w = 1.f; 66 | } 67 | return q; 68 | } 69 | inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec) 70 | { 71 | b3Quat qInv = b3QuatInvert(q); 72 | float4 vcpy = vec; 73 | vcpy.w = 0.f; 74 | float4 out = b3QuatMul(b3QuatMul(q, vcpy), qInv); 75 | return out; 76 | } 77 | 78 | inline b3Quat b3QuatInverse(b3QuatConstArg q) 79 | { 80 | return (b3Quat)(-q.xyz, q.w); 81 | } 82 | 83 | inline b3Quat b3QuatInvert(b3QuatConstArg q) 84 | { 85 | return (b3Quat)(-q.xyz, q.w); 86 | } 87 | 88 | inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec) 89 | { 90 | return b3QuatRotate(b3QuatInvert(q), vec); 91 | } 92 | 93 | inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation) 94 | { 95 | return b3QuatRotate(orientation, point) + (translation); 96 | } 97 | 98 | #endif 99 | 100 | #endif //B3_QUAT_H 101 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE pybullet_cpp_SRC CONFIGURE_DEPENDS "*.h" "*.cpp") 2 | 3 | MESSAGE(${pybullet_cpp_SRC}) 4 | 5 | add_library(pybullet_cpp ${pybullet_cpp_SRC}) 6 | target_include_directories(pybullet_cpp PUBLIC .) 7 | target_compile_definitions(pybullet_cpp PUBLIC -DBT_USE_DOUBLE_PRECISION) 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/LinearMath/TaskScheduler/btThreadSupportInterface.h: -------------------------------------------------------------------------------- 1 | /* 2 | Bullet Continuous Collision Detection and Physics Library 3 | Copyright (c) 2003-2018 Erwin Coumans http://bulletphysics.com 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #ifndef BT_THREAD_SUPPORT_INTERFACE_H 17 | #define BT_THREAD_SUPPORT_INTERFACE_H 18 | 19 | class btCriticalSection 20 | { 21 | public: 22 | btCriticalSection() {} 23 | virtual ~btCriticalSection() {} 24 | 25 | virtual void lock() = 0; 26 | virtual void unlock() = 0; 27 | }; 28 | 29 | class btThreadSupportInterface 30 | { 31 | public: 32 | virtual ~btThreadSupportInterface() {} 33 | 34 | virtual int getNumWorkerThreads() const = 0; // number of worker threads (total number of logical processors - 1) 35 | virtual int getCacheFriendlyNumThreads() const = 0; // the number of logical processors sharing a single L3 cache 36 | virtual int getLogicalToPhysicalCoreRatio() const = 0; // the number of logical processors per physical processor (usually 1 or 2) 37 | virtual void runTask(int threadIndex, void* userData) = 0; 38 | virtual void waitForAllTasks() = 0; 39 | 40 | virtual btCriticalSection* createCriticalSection() = 0; 41 | virtual void deleteCriticalSection(btCriticalSection* criticalSection) = 0; 42 | 43 | typedef void (*ThreadFunc)(void* userPtr); 44 | 45 | struct ConstructionInfo 46 | { 47 | ConstructionInfo(const char* uniqueName, 48 | ThreadFunc userThreadFunc, 49 | int threadStackSize = 65535) 50 | : m_uniqueName(uniqueName), 51 | m_userThreadFunc(userThreadFunc), 52 | m_threadStackSize(threadStackSize) 53 | { 54 | } 55 | 56 | const char* m_uniqueName; 57 | ThreadFunc m_userThreadFunc; 58 | int m_threadStackSize; 59 | }; 60 | 61 | static btThreadSupportInterface* create(const ConstructionInfo& info); 62 | }; 63 | 64 | #endif //BT_THREAD_SUPPORT_INTERFACE_H 65 | -------------------------------------------------------------------------------- /src/LinearMath/btAlignedAllocator.h: -------------------------------------------------------------------------------- 1 | /* 2 | Bullet Continuous Collision Detection and Physics Library 3 | Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #ifndef BT_ALIGNED_ALLOCATOR 17 | #define BT_ALIGNED_ALLOCATOR 18 | 19 | ///we probably replace this with our own aligned memory allocator 20 | ///so we replace _aligned_malloc and _aligned_free with our own 21 | ///that is better portable and more predictable 22 | 23 | #include "btScalar.h" 24 | 25 | ///BT_DEBUG_MEMORY_ALLOCATIONS preprocessor can be set in build system 26 | ///for regression tests to detect memory leaks 27 | ///#define BT_DEBUG_MEMORY_ALLOCATIONS 1 28 | #ifdef BT_DEBUG_MEMORY_ALLOCATIONS 29 | 30 | int btDumpMemoryLeaks(); 31 | 32 | #define btAlignedAlloc(a, b) \ 33 | btAlignedAllocInternal(a, b, __LINE__, __FILE__) 34 | 35 | #define btAlignedFree(ptr) \ 36 | btAlignedFreeInternal(ptr, __LINE__, __FILE__) 37 | 38 | void* btAlignedAllocInternal(size_t size, int alignment, int line, const char* filename); 39 | 40 | void btAlignedFreeInternal(void* ptr, int line, const char* filename); 41 | 42 | #else 43 | void* btAlignedAllocInternal(size_t size, int alignment); 44 | void btAlignedFreeInternal(void* ptr); 45 | 46 | #define btAlignedAlloc(size, alignment) btAlignedAllocInternal(size, alignment) 47 | #define btAlignedFree(ptr) btAlignedFreeInternal(ptr) 48 | 49 | #endif 50 | typedef int size_type; 51 | 52 | typedef void*(btAlignedAllocFunc)(size_t size, int alignment); 53 | typedef void(btAlignedFreeFunc)(void* memblock); 54 | typedef void*(btAllocFunc)(size_t size); 55 | typedef void(btFreeFunc)(void* memblock); 56 | 57 | ///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom 58 | void btAlignedAllocSetCustom(btAllocFunc* allocFunc, btFreeFunc* freeFunc); 59 | ///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it. 60 | void btAlignedAllocSetCustomAligned(btAlignedAllocFunc* allocFunc, btAlignedFreeFunc* freeFunc); 61 | 62 | ///The btAlignedAllocator is a portable class for aligned memory allocations. 63 | ///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned. 64 | template 65 | class btAlignedAllocator 66 | { 67 | typedef btAlignedAllocator self_type; 68 | 69 | public: 70 | //just going down a list: 71 | btAlignedAllocator() {} 72 | /* 73 | btAlignedAllocator( const self_type & ) {} 74 | */ 75 | 76 | template 77 | btAlignedAllocator(const btAlignedAllocator&) 78 | { 79 | } 80 | 81 | typedef const T* const_pointer; 82 | typedef const T& const_reference; 83 | typedef T* pointer; 84 | typedef T& reference; 85 | typedef T value_type; 86 | 87 | pointer address(reference ref) const { return &ref; } 88 | const_pointer address(const_reference ref) const { return &ref; } 89 | pointer allocate(size_type n, const_pointer* hint = 0) 90 | { 91 | (void)hint; 92 | return reinterpret_cast(btAlignedAlloc(sizeof(value_type) * n, Alignment)); 93 | } 94 | void construct(pointer ptr, const value_type& value) { new (ptr) value_type(value); } 95 | void deallocate(pointer ptr) 96 | { 97 | btAlignedFree(reinterpret_cast(ptr)); 98 | } 99 | void destroy(pointer ptr) { ptr->~value_type(); } 100 | 101 | template 102 | struct rebind 103 | { 104 | typedef btAlignedAllocator other; 105 | }; 106 | template 107 | self_type& operator=(const btAlignedAllocator&) 108 | { 109 | return *this; 110 | } 111 | 112 | friend bool operator==(const self_type&, const self_type&) { return true; } 113 | }; 114 | 115 | #endif //BT_ALIGNED_ALLOCATOR 116 | -------------------------------------------------------------------------------- /src/LinearMath/btConvexHullComputer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | #ifndef BT_CONVEX_HULL_COMPUTER_H 16 | #define BT_CONVEX_HULL_COMPUTER_H 17 | 18 | #include "btVector3.h" 19 | #include "btAlignedObjectArray.h" 20 | 21 | /// Convex hull implementation based on Preparata and Hong 22 | /// See http://code.google.com/p/bullet/issues/detail?id=275 23 | /// Ole Kniemeyer, MAXON Computer GmbH 24 | class btConvexHullComputer 25 | { 26 | private: 27 | btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp); 28 | 29 | public: 30 | class Edge 31 | { 32 | private: 33 | int next; 34 | int reverse; 35 | int targetVertex; 36 | 37 | friend class btConvexHullComputer; 38 | 39 | public: 40 | int getSourceVertex() const 41 | { 42 | return (this + reverse)->targetVertex; 43 | } 44 | 45 | int getTargetVertex() const 46 | { 47 | return targetVertex; 48 | } 49 | 50 | const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex 51 | { 52 | return this + next; 53 | } 54 | 55 | const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face 56 | { 57 | return (this + reverse)->getNextEdgeOfVertex(); 58 | } 59 | 60 | const Edge* getReverseEdge() const 61 | { 62 | return this + reverse; 63 | } 64 | }; 65 | 66 | // Vertices of the output hull 67 | btAlignedObjectArray vertices; 68 | 69 | // The original vertex index in the input coords array 70 | btAlignedObjectArray original_vertex_index; 71 | 72 | // Edges of the output hull 73 | btAlignedObjectArray edges; 74 | 75 | // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons 76 | btAlignedObjectArray faces; 77 | 78 | /* 79 | Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes 80 | between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken 81 | by that amount (each face is moved by "shrink" length units towards the center along its normal). 82 | If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius" 83 | is the minimum distance of a face to the center of the convex hull. 84 | 85 | The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large 86 | that the resulting convex hull is empty. 87 | 88 | The output convex hull can be found in the member variables "vertices", "edges", "faces". 89 | */ 90 | btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp) 91 | { 92 | return compute(coords, false, stride, count, shrink, shrinkClamp); 93 | } 94 | 95 | // same as above, but double precision 96 | btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp) 97 | { 98 | return compute(coords, true, stride, count, shrink, shrinkClamp); 99 | } 100 | }; 101 | 102 | #endif //BT_CONVEX_HULL_COMPUTER_H 103 | -------------------------------------------------------------------------------- /src/LinearMath/btCpuFeatureUtility.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BT_CPU_UTILITY_H 3 | #define BT_CPU_UTILITY_H 4 | 5 | #include "LinearMath/btScalar.h" 6 | 7 | #include //memset 8 | #ifdef USE_SIMD 9 | #include 10 | #ifdef BT_ALLOW_SSE4 11 | #include 12 | #endif //BT_ALLOW_SSE4 13 | #endif //USE_SIMD 14 | 15 | #if defined BT_USE_NEON 16 | #define ARM_NEON_GCC_COMPATIBILITY 1 17 | #include 18 | #include 19 | #include //for sysctlbyname 20 | #endif //BT_USE_NEON 21 | 22 | ///Rudimentary btCpuFeatureUtility for CPU features: only report the features that Bullet actually uses (SSE4/FMA3, NEON_HPFP) 23 | ///We assume SSE2 in case BT_USE_SSE2 is defined in LinearMath/btScalar.h 24 | class btCpuFeatureUtility 25 | { 26 | public: 27 | enum btCpuFeature 28 | { 29 | CPU_FEATURE_FMA3 = 1, 30 | CPU_FEATURE_SSE4_1 = 2, 31 | CPU_FEATURE_NEON_HPFP = 4 32 | }; 33 | 34 | static int getCpuFeatures() 35 | { 36 | static int capabilities = 0; 37 | static bool testedCapabilities = false; 38 | if (0 != testedCapabilities) 39 | { 40 | return capabilities; 41 | } 42 | 43 | #ifdef BT_USE_NEON 44 | { 45 | uint32_t hasFeature = 0; 46 | size_t featureSize = sizeof(hasFeature); 47 | int err = sysctlbyname("hw.optional.neon_hpfp", &hasFeature, &featureSize, NULL, 0); 48 | if (0 == err && hasFeature) 49 | capabilities |= CPU_FEATURE_NEON_HPFP; 50 | } 51 | #endif //BT_USE_NEON 52 | 53 | #ifdef BT_ALLOW_SSE4 54 | { 55 | int cpuInfo[4]; 56 | memset(cpuInfo, 0, sizeof(cpuInfo)); 57 | unsigned long long sseExt = 0; 58 | __cpuid(cpuInfo, 1); 59 | 60 | bool osUsesXSAVE_XRSTORE = cpuInfo[2] & (1 << 27) || false; 61 | bool cpuAVXSuport = cpuInfo[2] & (1 << 28) || false; 62 | 63 | if (osUsesXSAVE_XRSTORE && cpuAVXSuport) 64 | { 65 | sseExt = _xgetbv(0); 66 | } 67 | const int OSXSAVEFlag = (1UL << 27); 68 | const int AVXFlag = ((1UL << 28) | OSXSAVEFlag); 69 | const int FMAFlag = ((1UL << 12) | AVXFlag | OSXSAVEFlag); 70 | if ((cpuInfo[2] & FMAFlag) == FMAFlag && (sseExt & 6) == 6) 71 | { 72 | capabilities |= btCpuFeatureUtility::CPU_FEATURE_FMA3; 73 | } 74 | 75 | const int SSE41Flag = (1 << 19); 76 | if (cpuInfo[2] & SSE41Flag) 77 | { 78 | capabilities |= btCpuFeatureUtility::CPU_FEATURE_SSE4_1; 79 | } 80 | } 81 | #endif //BT_ALLOW_SSE4 82 | 83 | testedCapabilities = true; 84 | return capabilities; 85 | } 86 | }; 87 | 88 | #endif //BT_CPU_UTILITY_H 89 | -------------------------------------------------------------------------------- /src/LinearMath/btDefaultMotionState.h: -------------------------------------------------------------------------------- 1 | #ifndef BT_DEFAULT_MOTION_STATE_H 2 | #define BT_DEFAULT_MOTION_STATE_H 3 | 4 | #include "btMotionState.h" 5 | 6 | ///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets. 7 | ATTRIBUTE_ALIGNED16(struct) 8 | btDefaultMotionState : public btMotionState 9 | { 10 | btTransform m_graphicsWorldTrans; 11 | btTransform m_centerOfMassOffset; 12 | btTransform m_startWorldTrans; 13 | void* m_userPointer; 14 | 15 | BT_DECLARE_ALIGNED_ALLOCATOR(); 16 | 17 | btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(), const btTransform& centerOfMassOffset = btTransform::getIdentity()) 18 | : m_graphicsWorldTrans(startTrans), 19 | m_centerOfMassOffset(centerOfMassOffset), 20 | m_startWorldTrans(startTrans), 21 | m_userPointer(0) 22 | 23 | { 24 | } 25 | 26 | ///synchronizes world transform from user to physics 27 | virtual void getWorldTransform(btTransform & centerOfMassWorldTrans) const 28 | { 29 | centerOfMassWorldTrans = m_graphicsWorldTrans * m_centerOfMassOffset.inverse(); 30 | } 31 | 32 | ///synchronizes world transform from physics to user 33 | ///Bullet only calls the update of worldtransform for active objects 34 | virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans) 35 | { 36 | m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset; 37 | } 38 | }; 39 | 40 | #endif //BT_DEFAULT_MOTION_STATE_H 41 | -------------------------------------------------------------------------------- /src/LinearMath/btGeometryUtil.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | #include "btGeometryUtil.h" 16 | 17 | /* 18 | Make sure this dummy function never changes so that it 19 | can be used by probes that are checking whether the 20 | library is actually installed. 21 | */ 22 | extern "C" 23 | { 24 | void btBulletMathProbe(); 25 | 26 | void btBulletMathProbe() {} 27 | } 28 | 29 | bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray& planeEquations, const btVector3& point, btScalar margin) 30 | { 31 | int numbrushes = planeEquations.size(); 32 | for (int i = 0; i < numbrushes; i++) 33 | { 34 | const btVector3& N1 = planeEquations[i]; 35 | btScalar dist = btScalar(N1.dot(point)) + btScalar(N1[3]) - margin; 36 | if (dist > btScalar(0.)) 37 | { 38 | return false; 39 | } 40 | } 41 | return true; 42 | } 43 | 44 | bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray& vertices, btScalar margin) 45 | { 46 | int numvertices = vertices.size(); 47 | for (int i = 0; i < numvertices; i++) 48 | { 49 | const btVector3& N1 = vertices[i]; 50 | btScalar dist = btScalar(planeNormal.dot(N1)) + btScalar(planeNormal[3]) - margin; 51 | if (dist > btScalar(0.)) 52 | { 53 | return false; 54 | } 55 | } 56 | return true; 57 | } 58 | 59 | bool notExist(const btVector3& planeEquation, const btAlignedObjectArray& planeEquations); 60 | 61 | bool notExist(const btVector3& planeEquation, const btAlignedObjectArray& planeEquations) 62 | { 63 | int numbrushes = planeEquations.size(); 64 | for (int i = 0; i < numbrushes; i++) 65 | { 66 | const btVector3& N1 = planeEquations[i]; 67 | if (planeEquation.dot(N1) > btScalar(0.999)) 68 | { 69 | return false; 70 | } 71 | } 72 | return true; 73 | } 74 | 75 | void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray& vertices, btAlignedObjectArray& planeEquationsOut) 76 | { 77 | const int numvertices = vertices.size(); 78 | // brute force: 79 | for (int i = 0; i < numvertices; i++) 80 | { 81 | const btVector3& N1 = vertices[i]; 82 | 83 | for (int j = i + 1; j < numvertices; j++) 84 | { 85 | const btVector3& N2 = vertices[j]; 86 | 87 | for (int k = j + 1; k < numvertices; k++) 88 | { 89 | const btVector3& N3 = vertices[k]; 90 | 91 | btVector3 planeEquation, edge0, edge1; 92 | edge0 = N2 - N1; 93 | edge1 = N3 - N1; 94 | btScalar normalSign = btScalar(1.); 95 | for (int ww = 0; ww < 2; ww++) 96 | { 97 | planeEquation = normalSign * edge0.cross(edge1); 98 | if (planeEquation.length2() > btScalar(0.0001)) 99 | { 100 | planeEquation.normalize(); 101 | if (notExist(planeEquation, planeEquationsOut)) 102 | { 103 | planeEquation[3] = -planeEquation.dot(N1); 104 | 105 | //check if inside, and replace supportingVertexOut if needed 106 | if (areVerticesBehindPlane(planeEquation, vertices, btScalar(0.01))) 107 | { 108 | planeEquationsOut.push_back(planeEquation); 109 | } 110 | } 111 | } 112 | normalSign = btScalar(-1.); 113 | } 114 | } 115 | } 116 | } 117 | } 118 | 119 | void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray& planeEquations, btAlignedObjectArray& verticesOut) 120 | { 121 | const int numbrushes = planeEquations.size(); 122 | // brute force: 123 | for (int i = 0; i < numbrushes; i++) 124 | { 125 | const btVector3& N1 = planeEquations[i]; 126 | 127 | for (int j = i + 1; j < numbrushes; j++) 128 | { 129 | const btVector3& N2 = planeEquations[j]; 130 | 131 | for (int k = j + 1; k < numbrushes; k++) 132 | { 133 | const btVector3& N3 = planeEquations[k]; 134 | 135 | btVector3 n2n3; 136 | n2n3 = N2.cross(N3); 137 | btVector3 n3n1; 138 | n3n1 = N3.cross(N1); 139 | btVector3 n1n2; 140 | n1n2 = N1.cross(N2); 141 | 142 | if ((n2n3.length2() > btScalar(0.0001)) && 143 | (n3n1.length2() > btScalar(0.0001)) && 144 | (n1n2.length2() > btScalar(0.0001))) 145 | { 146 | //point P out of 3 plane equations: 147 | 148 | // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 ) 149 | //P = ------------------------------------------------------------------------- 150 | // N1 . ( N2 * N3 ) 151 | 152 | btScalar quotient = (N1.dot(n2n3)); 153 | if (btFabs(quotient) > btScalar(0.000001)) 154 | { 155 | quotient = btScalar(-1.) / quotient; 156 | n2n3 *= N1[3]; 157 | n3n1 *= N2[3]; 158 | n1n2 *= N3[3]; 159 | btVector3 potentialVertex = n2n3; 160 | potentialVertex += n3n1; 161 | potentialVertex += n1n2; 162 | potentialVertex *= quotient; 163 | 164 | //check if inside, and replace supportingVertexOut if needed 165 | if (isPointInsidePlanes(planeEquations, potentialVertex, btScalar(0.01))) 166 | { 167 | verticesOut.push_back(potentialVertex); 168 | } 169 | } 170 | } 171 | } 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/LinearMath/btGeometryUtil.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | #ifndef BT_GEOMETRY_UTIL_H 16 | #define BT_GEOMETRY_UTIL_H 17 | 18 | #include "btVector3.h" 19 | #include "btAlignedObjectArray.h" 20 | 21 | ///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices. 22 | class btGeometryUtil 23 | { 24 | public: 25 | static void getPlaneEquationsFromVertices(btAlignedObjectArray& vertices, btAlignedObjectArray& planeEquationsOut); 26 | 27 | static void getVerticesFromPlaneEquations(const btAlignedObjectArray& planeEquations, btAlignedObjectArray& verticesOut); 28 | 29 | static bool isInside(const btAlignedObjectArray& vertices, const btVector3& planeNormal, btScalar margin); 30 | 31 | static bool isPointInsidePlanes(const btAlignedObjectArray& planeEquations, const btVector3& point, btScalar margin); 32 | 33 | static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray& vertices, btScalar margin); 34 | }; 35 | 36 | #endif //BT_GEOMETRY_UTIL_H 37 | -------------------------------------------------------------------------------- /src/LinearMath/btGrahamScan2dConvexHull.h: -------------------------------------------------------------------------------- 1 | /* 2 | Bullet Continuous Collision Detection and Physics Library 3 | Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #ifndef GRAHAM_SCAN_2D_CONVEX_HULL_H 17 | #define GRAHAM_SCAN_2D_CONVEX_HULL_H 18 | 19 | #include "btVector3.h" 20 | #include "btAlignedObjectArray.h" 21 | 22 | struct GrahamVector3 : public btVector3 23 | { 24 | GrahamVector3(const btVector3& org, int orgIndex) 25 | : btVector3(org), 26 | m_orgIndex(orgIndex) 27 | { 28 | } 29 | btScalar m_angle; 30 | int m_orgIndex; 31 | }; 32 | 33 | struct btAngleCompareFunc 34 | { 35 | btVector3 m_anchor; 36 | btAngleCompareFunc(const btVector3& anchor) 37 | : m_anchor(anchor) 38 | { 39 | } 40 | bool operator()(const GrahamVector3& a, const GrahamVector3& b) const 41 | { 42 | if (a.m_angle != b.m_angle) 43 | return a.m_angle < b.m_angle; 44 | else 45 | { 46 | btScalar al = (a - m_anchor).length2(); 47 | btScalar bl = (b - m_anchor).length2(); 48 | if (al != bl) 49 | return al < bl; 50 | else 51 | { 52 | return a.m_orgIndex < b.m_orgIndex; 53 | } 54 | } 55 | } 56 | }; 57 | 58 | inline void GrahamScanConvexHull2D(btAlignedObjectArray& originalPoints, btAlignedObjectArray& hull, const btVector3& normalAxis) 59 | { 60 | btVector3 axis0, axis1; 61 | btPlaneSpace1(normalAxis, axis0, axis1); 62 | 63 | if (originalPoints.size() <= 1) 64 | { 65 | for (int i = 0; i < originalPoints.size(); i++) 66 | hull.push_back(originalPoints[0]); 67 | return; 68 | } 69 | //step1 : find anchor point with smallest projection on axis0 and move it to first location 70 | for (int i = 0; i < originalPoints.size(); i++) 71 | { 72 | // const btVector3& left = originalPoints[i]; 73 | // const btVector3& right = originalPoints[0]; 74 | btScalar projL = originalPoints[i].dot(axis0); 75 | btScalar projR = originalPoints[0].dot(axis0); 76 | if (projL < projR) 77 | { 78 | originalPoints.swap(0, i); 79 | } 80 | } 81 | 82 | //also precompute angles 83 | originalPoints[0].m_angle = -1e30f; 84 | for (int i = 1; i < originalPoints.size(); i++) 85 | { 86 | btVector3 ar = originalPoints[i] - originalPoints[0]; 87 | btScalar ar1 = axis1.dot(ar); 88 | btScalar ar0 = axis0.dot(ar); 89 | if (ar1 * ar1 + ar0 * ar0 < FLT_EPSILON) 90 | { 91 | originalPoints[i].m_angle = 0.0f; 92 | } 93 | else 94 | { 95 | originalPoints[i].m_angle = btAtan2Fast(ar1, ar0); 96 | } 97 | } 98 | 99 | //step 2: sort all points, based on 'angle' with this anchor 100 | btAngleCompareFunc comp(originalPoints[0]); 101 | originalPoints.quickSortInternal(comp, 1, originalPoints.size() - 1); 102 | 103 | int i; 104 | for (i = 0; i < 2; i++) 105 | hull.push_back(originalPoints[i]); 106 | 107 | //step 3: keep all 'convex' points and discard concave points (using back tracking) 108 | for (; i != originalPoints.size(); i++) 109 | { 110 | bool isConvex = false; 111 | while (!isConvex && hull.size() > 1) 112 | { 113 | btVector3& a = hull[hull.size() - 2]; 114 | btVector3& b = hull[hull.size() - 1]; 115 | isConvex = btCross(a - b, a - originalPoints[i]).dot(normalAxis) > 0; 116 | if (!isConvex) 117 | hull.pop_back(); 118 | else 119 | hull.push_back(originalPoints[i]); 120 | } 121 | 122 | if (hull.size() == 1) 123 | { 124 | hull.push_back(originalPoints[i]); 125 | } 126 | } 127 | } 128 | 129 | #endif //GRAHAM_SCAN_2D_CONVEX_HULL_H 130 | -------------------------------------------------------------------------------- /src/LinearMath/btList.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | #ifndef BT_GEN_LIST_H 16 | #define BT_GEN_LIST_H 17 | 18 | class btGEN_Link 19 | { 20 | public: 21 | btGEN_Link() : m_next(0), m_prev(0) {} 22 | btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {} 23 | 24 | btGEN_Link *getNext() const { return m_next; } 25 | btGEN_Link *getPrev() const { return m_prev; } 26 | 27 | bool isHead() const { return m_prev == 0; } 28 | bool isTail() const { return m_next == 0; } 29 | 30 | void insertBefore(btGEN_Link *link) 31 | { 32 | m_next = link; 33 | m_prev = link->m_prev; 34 | m_next->m_prev = this; 35 | m_prev->m_next = this; 36 | } 37 | 38 | void insertAfter(btGEN_Link *link) 39 | { 40 | m_next = link->m_next; 41 | m_prev = link; 42 | m_next->m_prev = this; 43 | m_prev->m_next = this; 44 | } 45 | 46 | void remove() 47 | { 48 | m_next->m_prev = m_prev; 49 | m_prev->m_next = m_next; 50 | } 51 | 52 | private: 53 | btGEN_Link *m_next; 54 | btGEN_Link *m_prev; 55 | }; 56 | 57 | class btGEN_List 58 | { 59 | public: 60 | btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {} 61 | 62 | btGEN_Link *getHead() const { return m_head.getNext(); } 63 | btGEN_Link *getTail() const { return m_tail.getPrev(); } 64 | 65 | void addHead(btGEN_Link *link) { link->insertAfter(&m_head); } 66 | void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); } 67 | 68 | private: 69 | btGEN_Link m_head; 70 | btGEN_Link m_tail; 71 | }; 72 | 73 | #endif //BT_GEN_LIST_H 74 | -------------------------------------------------------------------------------- /src/LinearMath/btMinMax.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | #ifndef BT_GEN_MINMAX_H 16 | #define BT_GEN_MINMAX_H 17 | 18 | #include "btScalar.h" 19 | 20 | template 21 | SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) 22 | { 23 | return a < b ? a : b; 24 | } 25 | 26 | template 27 | SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) 28 | { 29 | return a > b ? a : b; 30 | } 31 | 32 | template 33 | SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub) 34 | { 35 | return a < lb ? lb : (ub < a ? ub : a); 36 | } 37 | 38 | template 39 | SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) 40 | { 41 | if (b < a) 42 | { 43 | a = b; 44 | } 45 | } 46 | 47 | template 48 | SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) 49 | { 50 | if (a < b) 51 | { 52 | a = b; 53 | } 54 | } 55 | 56 | template 57 | SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub) 58 | { 59 | if (a < lb) 60 | { 61 | a = lb; 62 | } 63 | else if (ub < a) 64 | { 65 | a = ub; 66 | } 67 | } 68 | 69 | #endif //BT_GEN_MINMAX_H 70 | -------------------------------------------------------------------------------- /src/LinearMath/btModifiedGramSchmidt.h: -------------------------------------------------------------------------------- 1 | // 2 | // btModifiedGramSchmidt.h 3 | // LinearMath 4 | // 5 | // Created by Xuchen Han on 4/4/20. 6 | // 7 | 8 | #ifndef btModifiedGramSchmidt_h 9 | #define btModifiedGramSchmidt_h 10 | 11 | #include "btReducedVector.h" 12 | #include "btAlignedObjectArray.h" 13 | #include 14 | #include 15 | template 16 | class btModifiedGramSchmidt 17 | { 18 | public: 19 | btAlignedObjectArray m_in; 20 | btAlignedObjectArray m_out; 21 | 22 | btModifiedGramSchmidt(const btAlignedObjectArray& vecs): m_in(vecs) 23 | { 24 | m_out.resize(0); 25 | } 26 | 27 | void solve() 28 | { 29 | m_out.resize(m_in.size()); 30 | for (int i = 0; i < m_in.size(); ++i) 31 | { 32 | // printf("========= starting %d ==========\n", i); 33 | TV v(m_in[i]); 34 | // v.print(); 35 | for (int j = 0; j < i; ++j) 36 | { 37 | v = v - v.proj(m_out[j]); 38 | // v.print(); 39 | } 40 | v.normalize(); 41 | m_out[i] = v; 42 | // v.print(); 43 | } 44 | } 45 | 46 | void test() 47 | { 48 | std::cout << SIMD_EPSILON << std::endl; 49 | printf("=======inputs=========\n"); 50 | for (int i = 0; i < m_out.size(); ++i) 51 | { 52 | m_in[i].print(); 53 | } 54 | printf("=======output=========\n"); 55 | for (int i = 0; i < m_out.size(); ++i) 56 | { 57 | m_out[i].print(); 58 | } 59 | btScalar eps = SIMD_EPSILON; 60 | for (int i = 0; i < m_out.size(); ++i) 61 | { 62 | for (int j = 0; j < m_out.size(); ++j) 63 | { 64 | if (i == j) 65 | { 66 | if (std::abs(1.0-m_out[i].dot(m_out[j])) > eps)// && std::abs(m_out[i].dot(m_out[j])) > eps) 67 | { 68 | printf("vec[%d] is not unit, norm squared = %f\n", i,m_out[i].dot(m_out[j])); 69 | } 70 | } 71 | else 72 | { 73 | if (std::abs(m_out[i].dot(m_out[j])) > eps) 74 | { 75 | printf("vec[%d] and vec[%d] is not orthogonal, dot product = %f\n", i, j, m_out[i].dot(m_out[j])); 76 | } 77 | } 78 | } 79 | } 80 | } 81 | }; 82 | template class btModifiedGramSchmidt; 83 | #endif /* btModifiedGramSchmidt_h */ 84 | -------------------------------------------------------------------------------- /src/LinearMath/btMotionState.h: -------------------------------------------------------------------------------- 1 | /* 2 | Bullet Continuous Collision Detection and Physics Library 3 | Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #ifndef BT_MOTIONSTATE_H 17 | #define BT_MOTIONSTATE_H 18 | 19 | #include "btTransform.h" 20 | 21 | ///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics 22 | ///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation) 23 | class btMotionState 24 | { 25 | public: 26 | virtual ~btMotionState() 27 | { 28 | } 29 | 30 | virtual void getWorldTransform(btTransform& worldTrans) const = 0; 31 | 32 | //Bullet only calls the update of worldtransform for active objects 33 | virtual void setWorldTransform(const btTransform& worldTrans) = 0; 34 | }; 35 | 36 | #endif //BT_MOTIONSTATE_H 37 | -------------------------------------------------------------------------------- /src/LinearMath/btPolarDecomposition.cpp: -------------------------------------------------------------------------------- 1 | #include "btPolarDecomposition.h" 2 | #include "btMinMax.h" 3 | 4 | namespace 5 | { 6 | btScalar abs_column_sum(const btMatrix3x3& a, int i) 7 | { 8 | return btFabs(a[0][i]) + btFabs(a[1][i]) + btFabs(a[2][i]); 9 | } 10 | 11 | btScalar abs_row_sum(const btMatrix3x3& a, int i) 12 | { 13 | return btFabs(a[i][0]) + btFabs(a[i][1]) + btFabs(a[i][2]); 14 | } 15 | 16 | btScalar p1_norm(const btMatrix3x3& a) 17 | { 18 | const btScalar sum0 = abs_column_sum(a, 0); 19 | const btScalar sum1 = abs_column_sum(a, 1); 20 | const btScalar sum2 = abs_column_sum(a, 2); 21 | return btMax(btMax(sum0, sum1), sum2); 22 | } 23 | 24 | btScalar pinf_norm(const btMatrix3x3& a) 25 | { 26 | const btScalar sum0 = abs_row_sum(a, 0); 27 | const btScalar sum1 = abs_row_sum(a, 1); 28 | const btScalar sum2 = abs_row_sum(a, 2); 29 | return btMax(btMax(sum0, sum1), sum2); 30 | } 31 | } // namespace 32 | 33 | btPolarDecomposition::btPolarDecomposition(btScalar tolerance, unsigned int maxIterations) 34 | : m_tolerance(tolerance), m_maxIterations(maxIterations) 35 | { 36 | } 37 | 38 | unsigned int btPolarDecomposition::decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const 39 | { 40 | // Use the 'u' and 'h' matrices for intermediate calculations 41 | u = a; 42 | h = a.inverse(); 43 | 44 | for (unsigned int i = 0; i < m_maxIterations; ++i) 45 | { 46 | const btScalar h_1 = p1_norm(h); 47 | const btScalar h_inf = pinf_norm(h); 48 | const btScalar u_1 = p1_norm(u); 49 | const btScalar u_inf = pinf_norm(u); 50 | 51 | const btScalar h_norm = h_1 * h_inf; 52 | const btScalar u_norm = u_1 * u_inf; 53 | 54 | // The matrix is effectively singular so we cannot invert it 55 | if (btFuzzyZero(h_norm) || btFuzzyZero(u_norm)) 56 | break; 57 | 58 | const btScalar gamma = btPow(h_norm / u_norm, 0.25f); 59 | const btScalar inv_gamma = btScalar(1.0) / gamma; 60 | 61 | // Determine the delta to 'u' 62 | const btMatrix3x3 delta = (u * (gamma - btScalar(2.0)) + h.transpose() * inv_gamma) * btScalar(0.5); 63 | 64 | // Update the matrices 65 | u += delta; 66 | h = u.inverse(); 67 | 68 | // Check for convergence 69 | if (p1_norm(delta) <= m_tolerance * u_1) 70 | { 71 | h = u.transpose() * a; 72 | h = (h + h.transpose()) * 0.5; 73 | return i; 74 | } 75 | } 76 | 77 | // The algorithm has failed to converge to the specified tolerance, but we 78 | // want to make sure that the matrices returned are in the right form. 79 | h = u.transpose() * a; 80 | h = (h + h.transpose()) * 0.5; 81 | 82 | return m_maxIterations; 83 | } 84 | 85 | unsigned int btPolarDecomposition::maxIterations() const 86 | { 87 | return m_maxIterations; 88 | } 89 | 90 | unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) 91 | { 92 | static btPolarDecomposition polar; 93 | return polar.decompose(a, u, h); 94 | } 95 | -------------------------------------------------------------------------------- /src/LinearMath/btPolarDecomposition.h: -------------------------------------------------------------------------------- 1 | #ifndef POLARDECOMPOSITION_H 2 | #define POLARDECOMPOSITION_H 3 | 4 | #include "btMatrix3x3.h" 5 | 6 | /** 7 | * This class is used to compute the polar decomposition of a matrix. In 8 | * general, the polar decomposition factorizes a matrix, A, into two parts: a 9 | * unitary matrix (U) and a positive, semi-definite Hermitian matrix (H). 10 | * However, in this particular implementation the original matrix, A, is 11 | * required to be a square 3x3 matrix with real elements. This means that U will 12 | * be an orthogonal matrix and H with be a positive-definite, symmetric matrix. 13 | */ 14 | class btPolarDecomposition 15 | { 16 | public: 17 | /** 18 | * Creates an instance with optional parameters. 19 | * 20 | * @param tolerance - the tolerance used to determine convergence of the 21 | * algorithm 22 | * @param maxIterations - the maximum number of iterations used to achieve 23 | * convergence 24 | */ 25 | btPolarDecomposition(btScalar tolerance = btScalar(0.0001), 26 | unsigned int maxIterations = 16); 27 | 28 | /** 29 | * Decomposes a matrix into orthogonal and symmetric, positive-definite 30 | * parts. If the number of iterations returned by this function is equal to 31 | * the maximum number of iterations, the algorithm has failed to converge. 32 | * 33 | * @param a - the original matrix 34 | * @param u - the resulting orthogonal matrix 35 | * @param h - the resulting symmetric matrix 36 | * 37 | * @return the number of iterations performed by the algorithm. 38 | */ 39 | unsigned int decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const; 40 | 41 | /** 42 | * Returns the maximum number of iterations that this algorithm will perform 43 | * to achieve convergence. 44 | * 45 | * @return maximum number of iterations 46 | */ 47 | unsigned int maxIterations() const; 48 | 49 | private: 50 | btScalar m_tolerance; 51 | unsigned int m_maxIterations; 52 | }; 53 | 54 | /** 55 | * This functions decomposes the matrix 'a' into two parts: an orthogonal matrix 56 | * 'u' and a symmetric, positive-definite matrix 'h'. If the number of 57 | * iterations returned by this function is equal to 58 | * btPolarDecomposition::DEFAULT_MAX_ITERATIONS, the algorithm has failed to 59 | * converge. 60 | * 61 | * @param a - the original matrix 62 | * @param u - the resulting orthogonal matrix 63 | * @param h - the resulting symmetric matrix 64 | * 65 | * @return the number of iterations performed by the algorithm. 66 | */ 67 | unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h); 68 | 69 | #endif // POLARDECOMPOSITION_H 70 | -------------------------------------------------------------------------------- /src/LinearMath/btPoolAllocator.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | #ifndef _BT_POOL_ALLOCATOR_H 16 | #define _BT_POOL_ALLOCATOR_H 17 | 18 | #include "btScalar.h" 19 | #include "btAlignedAllocator.h" 20 | #include "btThreads.h" 21 | 22 | ///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately. 23 | class btPoolAllocator 24 | { 25 | int m_elemSize; 26 | int m_maxElements; 27 | int m_freeCount; 28 | void* m_firstFree; 29 | unsigned char* m_pool; 30 | btSpinMutex m_mutex; // only used if BT_THREADSAFE 31 | 32 | public: 33 | btPoolAllocator(int elemSize, int maxElements) 34 | : m_elemSize(elemSize), 35 | m_maxElements(maxElements) 36 | { 37 | m_pool = (unsigned char*)btAlignedAlloc(static_cast(m_elemSize * m_maxElements), 16); 38 | 39 | unsigned char* p = m_pool; 40 | m_firstFree = p; 41 | m_freeCount = m_maxElements; 42 | int count = m_maxElements; 43 | while (--count) 44 | { 45 | *(void**)p = (p + m_elemSize); 46 | p += m_elemSize; 47 | } 48 | *(void**)p = 0; 49 | } 50 | 51 | ~btPoolAllocator() 52 | { 53 | btAlignedFree(m_pool); 54 | } 55 | 56 | int getFreeCount() const 57 | { 58 | return m_freeCount; 59 | } 60 | 61 | int getUsedCount() const 62 | { 63 | return m_maxElements - m_freeCount; 64 | } 65 | 66 | int getMaxCount() const 67 | { 68 | return m_maxElements; 69 | } 70 | 71 | void* allocate(int size) 72 | { 73 | // release mode fix 74 | (void)size; 75 | btMutexLock(&m_mutex); 76 | btAssert(!size || size <= m_elemSize); 77 | //btAssert(m_freeCount>0); // should return null if all full 78 | void* result = m_firstFree; 79 | if (NULL != m_firstFree) 80 | { 81 | m_firstFree = *(void**)m_firstFree; 82 | --m_freeCount; 83 | } 84 | btMutexUnlock(&m_mutex); 85 | return result; 86 | } 87 | 88 | bool validPtr(void* ptr) 89 | { 90 | if (ptr) 91 | { 92 | if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize)) 93 | { 94 | return true; 95 | } 96 | } 97 | return false; 98 | } 99 | 100 | void freeMemory(void* ptr) 101 | { 102 | if (ptr) 103 | { 104 | btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize); 105 | 106 | btMutexLock(&m_mutex); 107 | *(void**)ptr = m_firstFree; 108 | m_firstFree = ptr; 109 | ++m_freeCount; 110 | btMutexUnlock(&m_mutex); 111 | } 112 | } 113 | 114 | int getElementSize() const 115 | { 116 | return m_elemSize; 117 | } 118 | 119 | unsigned char* getPoolAddress() 120 | { 121 | return m_pool; 122 | } 123 | 124 | const unsigned char* getPoolAddress() const 125 | { 126 | return m_pool; 127 | } 128 | }; 129 | 130 | #endif //_BT_POOL_ALLOCATOR_H 131 | -------------------------------------------------------------------------------- /src/LinearMath/btQuickprof.h: -------------------------------------------------------------------------------- 1 | 2 | /*************************************************************************************************** 3 | ** 4 | ** Real-Time Hierarchical Profiling for Game Programming Gems 3 5 | ** 6 | ** by Greg Hjelstrom & Byon Garrabrant 7 | ** 8 | ***************************************************************************************************/ 9 | 10 | // Credits: The Clock class was inspired by the Timer classes in 11 | // Ogre (www.ogre3d.org). 12 | 13 | #ifndef BT_QUICK_PROF_H 14 | #define BT_QUICK_PROF_H 15 | 16 | #include "btScalar.h" 17 | #define USE_BT_CLOCK 1 18 | 19 | #ifdef USE_BT_CLOCK 20 | 21 | ///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling. 22 | class btClock 23 | { 24 | public: 25 | btClock(); 26 | 27 | btClock(const btClock& other); 28 | btClock& operator=(const btClock& other); 29 | 30 | ~btClock(); 31 | 32 | /// Resets the initial reference time. 33 | void reset(); 34 | 35 | /// Returns the time in ms since the last call to reset or since 36 | /// the btClock was created. 37 | unsigned long long int getTimeMilliseconds(); 38 | 39 | /// Returns the time in us since the last call to reset or since 40 | /// the Clock was created. 41 | unsigned long long int getTimeMicroseconds(); 42 | 43 | unsigned long long int getTimeNanoseconds(); 44 | 45 | /// Returns the time in s since the last call to reset or since 46 | /// the Clock was created. 47 | btScalar getTimeSeconds(); 48 | 49 | private: 50 | struct btClockData* m_data; 51 | }; 52 | 53 | #endif //USE_BT_CLOCK 54 | 55 | typedef void(btEnterProfileZoneFunc)(const char* msg); 56 | typedef void(btLeaveProfileZoneFunc)(); 57 | 58 | btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc(); 59 | btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc(); 60 | 61 | void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc); 62 | void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc); 63 | 64 | #ifndef BT_ENABLE_PROFILE 65 | #define BT_NO_PROFILE 1 66 | #endif //BT_NO_PROFILE 67 | 68 | const unsigned int BT_QUICKPROF_MAX_THREAD_COUNT = 64; 69 | 70 | //btQuickprofGetCurrentThreadIndex will return -1 if thread index cannot be determined, 71 | //otherwise returns thread index in range [0..maxThreads] 72 | unsigned int btQuickprofGetCurrentThreadIndex2(); 73 | 74 | #ifndef BT_NO_PROFILE 75 | 76 | 77 | #include //@todo remove this, backwards compatibility 78 | 79 | #include "btAlignedAllocator.h" 80 | #include 81 | 82 | ///A node in the Profile Hierarchy Tree 83 | class CProfileNode 84 | { 85 | public: 86 | CProfileNode(const char* name, CProfileNode* parent); 87 | ~CProfileNode(void); 88 | 89 | CProfileNode* Get_Sub_Node(const char* name); 90 | 91 | CProfileNode* Get_Parent(void) { return Parent; } 92 | CProfileNode* Get_Sibling(void) { return Sibling; } 93 | CProfileNode* Get_Child(void) { return Child; } 94 | 95 | void CleanupMemory(); 96 | void Reset(void); 97 | void Call(void); 98 | bool Return(void); 99 | 100 | const char* Get_Name(void) { return Name; } 101 | int Get_Total_Calls(void) { return TotalCalls; } 102 | float Get_Total_Time(void) { return TotalTime; } 103 | void* GetUserPointer() const { return m_userPtr; } 104 | void SetUserPointer(void* ptr) { m_userPtr = ptr; } 105 | 106 | protected: 107 | const char* Name; 108 | int TotalCalls; 109 | float TotalTime; 110 | unsigned long int StartTime; 111 | int RecursionCounter; 112 | 113 | CProfileNode* Parent; 114 | CProfileNode* Child; 115 | CProfileNode* Sibling; 116 | void* m_userPtr; 117 | }; 118 | 119 | ///An iterator to navigate through the tree 120 | class CProfileIterator 121 | { 122 | public: 123 | // Access all the children of the current parent 124 | void First(void); 125 | void Next(void); 126 | bool Is_Done(void); 127 | bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); } 128 | 129 | void Enter_Child(int index); // Make the given child the new parent 130 | void Enter_Largest_Child(void); // Make the largest child the new parent 131 | void Enter_Parent(void); // Make the current parent's parent the new parent 132 | 133 | // Access the current child 134 | const char* Get_Current_Name(void) { return CurrentChild->Get_Name(); } 135 | int Get_Current_Total_Calls(void) { return CurrentChild->Get_Total_Calls(); } 136 | float Get_Current_Total_Time(void) { return CurrentChild->Get_Total_Time(); } 137 | 138 | void* Get_Current_UserPointer(void) { return CurrentChild->GetUserPointer(); } 139 | void Set_Current_UserPointer(void* ptr) { CurrentChild->SetUserPointer(ptr); } 140 | // Access the current parent 141 | const char* Get_Current_Parent_Name(void) { return CurrentParent->Get_Name(); } 142 | int Get_Current_Parent_Total_Calls(void) { return CurrentParent->Get_Total_Calls(); } 143 | float Get_Current_Parent_Total_Time(void) { return CurrentParent->Get_Total_Time(); } 144 | 145 | protected: 146 | CProfileNode* CurrentParent; 147 | CProfileNode* CurrentChild; 148 | 149 | CProfileIterator(CProfileNode* start); 150 | friend class CProfileManager; 151 | }; 152 | 153 | ///The Manager for the Profile system 154 | class CProfileManager 155 | { 156 | public: 157 | static void Start_Profile(const char* name); 158 | static void Stop_Profile(void); 159 | 160 | static void CleanupMemory(void); 161 | // { 162 | // Root.CleanupMemory(); 163 | // } 164 | 165 | static void Reset(void); 166 | static void Increment_Frame_Counter(void); 167 | static int Get_Frame_Count_Since_Reset(void) { return FrameCounter; } 168 | static float Get_Time_Since_Reset(void); 169 | 170 | static CProfileIterator* Get_Iterator(void); 171 | // { 172 | // 173 | // return new CProfileIterator( &Root ); 174 | // } 175 | static void Release_Iterator(CProfileIterator* iterator) { delete (iterator); } 176 | 177 | static void dumpRecursive(CProfileIterator* profileIterator, int spacing); 178 | 179 | static void dumpAll(); 180 | 181 | private: 182 | static int FrameCounter; 183 | static unsigned long int ResetTime; 184 | }; 185 | 186 | #endif //#ifndef BT_NO_PROFILE 187 | 188 | ///ProfileSampleClass is a simple way to profile a function's scope 189 | ///Use the BT_PROFILE macro at the start of scope to time 190 | class CProfileSample 191 | { 192 | public: 193 | CProfileSample(const char* name); 194 | 195 | ~CProfileSample(void); 196 | }; 197 | 198 | #define BT_PROFILE(name) CProfileSample __profile(name) 199 | 200 | #endif //BT_QUICK_PROF_H 201 | -------------------------------------------------------------------------------- /src/LinearMath/btRandom.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | #ifndef BT_GEN_RANDOM_H 16 | #define BT_GEN_RANDOM_H 17 | 18 | #ifdef MT19937 19 | 20 | #include 21 | #include 22 | 23 | #define GEN_RAND_MAX UINT_MAX 24 | 25 | SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); } 26 | SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); } 27 | 28 | #else 29 | 30 | #include 31 | 32 | #define GEN_RAND_MAX RAND_MAX 33 | 34 | SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); } 35 | SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); } 36 | 37 | #endif 38 | 39 | #endif //BT_GEN_RANDOM_H 40 | -------------------------------------------------------------------------------- /src/LinearMath/btReducedVector.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // btReducedVector.cpp 3 | // LinearMath 4 | // 5 | // Created by Xuchen Han on 4/4/20. 6 | // 7 | #include 8 | #include "btReducedVector.h" 9 | #include 10 | 11 | // returns the projection of this onto other 12 | btReducedVector btReducedVector::proj(const btReducedVector& other) const 13 | { 14 | btReducedVector ret(m_sz); 15 | btScalar other_length2 = other.length2(); 16 | if (other_length2 < SIMD_EPSILON) 17 | { 18 | return ret; 19 | } 20 | return other*(this->dot(other))/other_length2; 21 | } 22 | 23 | void btReducedVector::normalize() 24 | { 25 | if (this->length2() < SIMD_EPSILON) 26 | { 27 | m_indices.clear(); 28 | m_vecs.clear(); 29 | return; 30 | } 31 | *this /= std::sqrt(this->length2()); 32 | } 33 | 34 | bool btReducedVector::testAdd() const 35 | { 36 | int sz = 5; 37 | btAlignedObjectArray id1; 38 | id1.push_back(1); 39 | id1.push_back(3); 40 | btAlignedObjectArray v1; 41 | v1.push_back(btVector3(1,0,1)); 42 | v1.push_back(btVector3(3,1,5)); 43 | btAlignedObjectArray id2; 44 | id2.push_back(2); 45 | id2.push_back(3); 46 | id2.push_back(5); 47 | btAlignedObjectArray v2; 48 | v2.push_back(btVector3(2,3,1)); 49 | v2.push_back(btVector3(3,4,9)); 50 | v2.push_back(btVector3(0,4,0)); 51 | btAlignedObjectArray id3; 52 | id3.push_back(1); 53 | id3.push_back(2); 54 | id3.push_back(3); 55 | id3.push_back(5); 56 | btAlignedObjectArray v3; 57 | v3.push_back(btVector3(1,0,1)); 58 | v3.push_back(btVector3(2,3,1)); 59 | v3.push_back(btVector3(6,5,14)); 60 | v3.push_back(btVector3(0,4,0)); 61 | btReducedVector rv1(sz, id1, v1); 62 | btReducedVector rv2(sz, id2, v2); 63 | btReducedVector ans(sz, id3, v3); 64 | bool ret = ((ans == rv1+rv2) && (ans == rv2+rv1)); 65 | if (!ret) 66 | printf("btReducedVector testAdd failed\n"); 67 | return ret; 68 | } 69 | 70 | bool btReducedVector::testMinus() const 71 | { 72 | int sz = 5; 73 | btAlignedObjectArray id1; 74 | id1.push_back(1); 75 | id1.push_back(3); 76 | btAlignedObjectArray v1; 77 | v1.push_back(btVector3(1,0,1)); 78 | v1.push_back(btVector3(3,1,5)); 79 | btAlignedObjectArray id2; 80 | id2.push_back(2); 81 | id2.push_back(3); 82 | id2.push_back(5); 83 | btAlignedObjectArray v2; 84 | v2.push_back(btVector3(2,3,1)); 85 | v2.push_back(btVector3(3,4,9)); 86 | v2.push_back(btVector3(0,4,0)); 87 | btAlignedObjectArray id3; 88 | id3.push_back(1); 89 | id3.push_back(2); 90 | id3.push_back(3); 91 | id3.push_back(5); 92 | btAlignedObjectArray v3; 93 | v3.push_back(btVector3(-1,-0,-1)); 94 | v3.push_back(btVector3(2,3,1)); 95 | v3.push_back(btVector3(0,3,4)); 96 | v3.push_back(btVector3(0,4,0)); 97 | btReducedVector rv1(sz, id1, v1); 98 | btReducedVector rv2(sz, id2, v2); 99 | btReducedVector ans(sz, id3, v3); 100 | bool ret = (ans == rv2-rv1); 101 | if (!ret) 102 | printf("btReducedVector testMinus failed\n"); 103 | return ret; 104 | } 105 | 106 | bool btReducedVector::testDot() const 107 | { 108 | int sz = 5; 109 | btAlignedObjectArray id1; 110 | id1.push_back(1); 111 | id1.push_back(3); 112 | btAlignedObjectArray v1; 113 | v1.push_back(btVector3(1,0,1)); 114 | v1.push_back(btVector3(3,1,5)); 115 | btAlignedObjectArray id2; 116 | id2.push_back(2); 117 | id2.push_back(3); 118 | id2.push_back(5); 119 | btAlignedObjectArray v2; 120 | v2.push_back(btVector3(2,3,1)); 121 | v2.push_back(btVector3(3,4,9)); 122 | v2.push_back(btVector3(0,4,0)); 123 | btReducedVector rv1(sz, id1, v1); 124 | btReducedVector rv2(sz, id2, v2); 125 | btScalar ans = 58; 126 | bool ret = (ans == rv2.dot(rv1) && ans == rv1.dot(rv2)); 127 | ans = 14+16+9+16+81; 128 | ret &= (ans==rv2.dot(rv2)); 129 | 130 | if (!ret) 131 | printf("btReducedVector testDot failed\n"); 132 | return ret; 133 | } 134 | 135 | bool btReducedVector::testMultiply() const 136 | { 137 | int sz = 5; 138 | btAlignedObjectArray id1; 139 | id1.push_back(1); 140 | id1.push_back(3); 141 | btAlignedObjectArray v1; 142 | v1.push_back(btVector3(1,0,1)); 143 | v1.push_back(btVector3(3,1,5)); 144 | btScalar s = 2; 145 | btReducedVector rv1(sz, id1, v1); 146 | btAlignedObjectArray id2; 147 | id2.push_back(1); 148 | id2.push_back(3); 149 | btAlignedObjectArray v2; 150 | v2.push_back(btVector3(2,0,2)); 151 | v2.push_back(btVector3(6,2,10)); 152 | btReducedVector ans(sz, id2, v2); 153 | bool ret = (ans == rv1*s); 154 | if (!ret) 155 | printf("btReducedVector testMultiply failed\n"); 156 | return ret; 157 | } 158 | 159 | void btReducedVector::test() const 160 | { 161 | bool ans = testAdd() && testMinus() && testDot() && testMultiply(); 162 | if (ans) 163 | { 164 | printf("All tests passed\n"); 165 | } 166 | else 167 | { 168 | printf("Tests failed\n"); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/LinearMath/btStackAlloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | /* 16 | StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson 17 | Nov.2006 18 | */ 19 | 20 | #ifndef BT_STACK_ALLOC 21 | #define BT_STACK_ALLOC 22 | 23 | #include "btScalar.h" //for btAssert 24 | #include "btAlignedAllocator.h" 25 | 26 | ///The btBlock class is an internal structure for the btStackAlloc memory allocator. 27 | struct btBlock 28 | { 29 | btBlock* previous; 30 | unsigned char* address; 31 | }; 32 | 33 | ///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out) 34 | class btStackAlloc 35 | { 36 | public: 37 | btStackAlloc(unsigned int size) 38 | { 39 | ctor(); 40 | create(size); 41 | } 42 | ~btStackAlloc() { destroy(); } 43 | 44 | inline void create(unsigned int size) 45 | { 46 | destroy(); 47 | data = (unsigned char*)btAlignedAlloc(size, 16); 48 | totalsize = size; 49 | } 50 | inline void destroy() 51 | { 52 | btAssert(usedsize == 0); 53 | //Raise(L"StackAlloc is still in use"); 54 | 55 | if (usedsize == 0) 56 | { 57 | if (!ischild && data) 58 | btAlignedFree(data); 59 | 60 | data = 0; 61 | usedsize = 0; 62 | } 63 | } 64 | 65 | int getAvailableMemory() const 66 | { 67 | return static_cast(totalsize - usedsize); 68 | } 69 | 70 | unsigned char* allocate(unsigned int size) 71 | { 72 | const unsigned int nus(usedsize + size); 73 | if (nus < totalsize) 74 | { 75 | usedsize = nus; 76 | return (data + (usedsize - size)); 77 | } 78 | btAssert(0); 79 | //&& (L"Not enough memory")); 80 | 81 | return (0); 82 | } 83 | SIMD_FORCE_INLINE btBlock* beginBlock() 84 | { 85 | btBlock* pb = (btBlock*)allocate(sizeof(btBlock)); 86 | pb->previous = current; 87 | pb->address = data + usedsize; 88 | current = pb; 89 | return (pb); 90 | } 91 | SIMD_FORCE_INLINE void endBlock(btBlock* block) 92 | { 93 | btAssert(block == current); 94 | //Raise(L"Unmatched blocks"); 95 | if (block == current) 96 | { 97 | current = block->previous; 98 | usedsize = (unsigned int)((block->address - data) - sizeof(btBlock)); 99 | } 100 | } 101 | 102 | private: 103 | void ctor() 104 | { 105 | data = 0; 106 | totalsize = 0; 107 | usedsize = 0; 108 | current = 0; 109 | ischild = false; 110 | } 111 | unsigned char* data; 112 | unsigned int totalsize; 113 | unsigned int usedsize; 114 | btBlock* current; 115 | bool ischild; 116 | }; 117 | 118 | #endif //BT_STACK_ALLOC 119 | -------------------------------------------------------------------------------- /src/LinearMath/btThreads.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2014 Erwin Coumans http://bullet.googlecode.com 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | #ifndef BT_THREADS_H 16 | #define BT_THREADS_H 17 | 18 | #include "btScalar.h" // has definitions like SIMD_FORCE_INLINE 19 | 20 | #if defined(_MSC_VER) && _MSC_VER >= 1600 21 | // give us a compile error if any signatures of overriden methods is changed 22 | #define BT_OVERRIDE override 23 | #endif 24 | 25 | #ifndef BT_OVERRIDE 26 | #define BT_OVERRIDE 27 | #endif 28 | 29 | // Don't set this to larger than 64, without modifying btThreadSupportPosix 30 | // and btThreadSupportWin32. They use UINT64 bit-masks. 31 | const unsigned int BT_MAX_THREAD_COUNT = 64; // only if BT_THREADSAFE is 1 32 | 33 | // for internal use only 34 | bool btIsMainThread(); 35 | bool btThreadsAreRunning(); 36 | unsigned int btGetCurrentThreadIndex(); 37 | void btResetThreadIndexCounter(); // notify that all worker threads have been destroyed 38 | 39 | /// 40 | /// btSpinMutex -- lightweight spin-mutex implemented with atomic ops, never puts 41 | /// a thread to sleep because it is designed to be used with a task scheduler 42 | /// which has one thread per core and the threads don't sleep until they 43 | /// run out of tasks. Not good for general purpose use. 44 | /// 45 | class btSpinMutex 46 | { 47 | int mLock; 48 | 49 | public: 50 | btSpinMutex() 51 | { 52 | mLock = 0; 53 | } 54 | void lock(); 55 | void unlock(); 56 | bool tryLock(); 57 | }; 58 | 59 | // 60 | // NOTE: btMutex* is for internal Bullet use only 61 | // 62 | // If BT_THREADSAFE is undefined or 0, should optimize away to nothing. 63 | // This is good because for the single-threaded build of Bullet, any calls 64 | // to these functions will be optimized out. 65 | // 66 | // However, for users of the multi-threaded build of Bullet this is kind 67 | // of bad because if you call any of these functions from external code 68 | // (where BT_THREADSAFE is undefined) you will get unexpected race conditions. 69 | // 70 | SIMD_FORCE_INLINE void btMutexLock(btSpinMutex* mutex) 71 | { 72 | #if BT_THREADSAFE 73 | mutex->lock(); 74 | #else 75 | (void)mutex; 76 | #endif // #if BT_THREADSAFE 77 | } 78 | 79 | SIMD_FORCE_INLINE void btMutexUnlock(btSpinMutex* mutex) 80 | { 81 | #if BT_THREADSAFE 82 | mutex->unlock(); 83 | #else 84 | (void)mutex; 85 | #endif // #if BT_THREADSAFE 86 | } 87 | 88 | SIMD_FORCE_INLINE bool btMutexTryLock(btSpinMutex* mutex) 89 | { 90 | #if BT_THREADSAFE 91 | return mutex->tryLock(); 92 | #else 93 | (void)mutex; 94 | return true; 95 | #endif // #if BT_THREADSAFE 96 | } 97 | 98 | // 99 | // btIParallelForBody -- subclass this to express work that can be done in parallel 100 | // 101 | class btIParallelForBody 102 | { 103 | public: 104 | virtual ~btIParallelForBody() {} 105 | virtual void forLoop(int iBegin, int iEnd) const = 0; 106 | }; 107 | 108 | // 109 | // btIParallelSumBody -- subclass this to express work that can be done in parallel 110 | // and produces a sum over all loop elements 111 | // 112 | class btIParallelSumBody 113 | { 114 | public: 115 | virtual ~btIParallelSumBody() {} 116 | virtual btScalar sumLoop(int iBegin, int iEnd) const = 0; 117 | }; 118 | 119 | // 120 | // btITaskScheduler -- subclass this to implement a task scheduler that can dispatch work to 121 | // worker threads 122 | // 123 | class btITaskScheduler 124 | { 125 | public: 126 | btITaskScheduler(const char* name); 127 | virtual ~btITaskScheduler() {} 128 | const char* getName() const { return m_name; } 129 | 130 | virtual int getMaxNumThreads() const = 0; 131 | virtual int getNumThreads() const = 0; 132 | virtual void setNumThreads(int numThreads) = 0; 133 | virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) = 0; 134 | virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) = 0; 135 | virtual void sleepWorkerThreadsHint() {} // hint the task scheduler that we may not be using these threads for a little while 136 | 137 | // internal use only 138 | virtual void activate(); 139 | virtual void deactivate(); 140 | 141 | protected: 142 | const char* m_name; 143 | unsigned int m_savedThreadCounter; 144 | bool m_isActive; 145 | }; 146 | 147 | // set the task scheduler to use for all calls to btParallelFor() 148 | // NOTE: you must set this prior to using any of the multi-threaded "Mt" classes 149 | void btSetTaskScheduler(btITaskScheduler* ts); 150 | 151 | // get the current task scheduler 152 | btITaskScheduler* btGetTaskScheduler(); 153 | 154 | // get non-threaded task scheduler (always available) 155 | btITaskScheduler* btGetSequentialTaskScheduler(); 156 | 157 | // create a default task scheduler (Win32 or pthreads based) 158 | btITaskScheduler* btCreateDefaultTaskScheduler(); 159 | 160 | // get OpenMP task scheduler (if available, otherwise returns null) 161 | btITaskScheduler* btGetOpenMPTaskScheduler(); 162 | 163 | // get Intel TBB task scheduler (if available, otherwise returns null) 164 | btITaskScheduler* btGetTBBTaskScheduler(); 165 | 166 | // get PPL task scheduler (if available, otherwise returns null) 167 | btITaskScheduler* btGetPPLTaskScheduler(); 168 | 169 | // btParallelFor -- call this to dispatch work like a for-loop 170 | // (iterations may be done out of order, so no dependencies are allowed) 171 | void btParallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body); 172 | 173 | // btParallelSum -- call this to dispatch work like a for-loop, returns the sum of all iterations 174 | // (iterations may be done out of order, so no dependencies are allowed) 175 | btScalar btParallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body); 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /src/Serialize/BulletFileLoader/bChunk.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | bParse 3 | Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #include "bChunk.h" 17 | #include "bDefines.h" 18 | #include "bFile.h" 19 | 20 | #if !defined(__CELLOS_LV2__) && !defined(__MWERKS__) 21 | #include 22 | #endif 23 | #include 24 | 25 | using namespace bParse; 26 | 27 | // ----------------------------------------------------- // 28 | short ChunkUtils::swapShort(short sht) 29 | { 30 | SWITCH_SHORT(sht); 31 | return sht; 32 | } 33 | 34 | // ----------------------------------------------------- // 35 | int ChunkUtils::swapInt(int inte) 36 | { 37 | SWITCH_INT(inte); 38 | return inte; 39 | } 40 | 41 | // ----------------------------------------------------- // 42 | long64 ChunkUtils::swapLong64(long64 lng) 43 | { 44 | SWITCH_LONGINT(lng); 45 | return lng; 46 | } 47 | 48 | // ----------------------------------------------------- // 49 | int ChunkUtils::getOffset(int flags) 50 | { 51 | // if the file is saved in a 52 | // different format, get the 53 | // file's chunk size 54 | int res = CHUNK_HEADER_LEN; 55 | 56 | if (VOID_IS_8) 57 | { 58 | if (flags & FD_BITS_VARIES) 59 | res = sizeof(bChunkPtr4); 60 | } 61 | else 62 | { 63 | if (flags & FD_BITS_VARIES) 64 | res = sizeof(bChunkPtr8); 65 | } 66 | return res; 67 | } 68 | 69 | //eof 70 | -------------------------------------------------------------------------------- /src/Serialize/BulletFileLoader/bChunk.h: -------------------------------------------------------------------------------- 1 | /* 2 | bParse 3 | Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #ifndef __BCHUNK_H__ 17 | #define __BCHUNK_H__ 18 | 19 | #if defined(_WIN32) && !defined(__MINGW32__) 20 | #define long64 __int64 21 | #elif defined(__MINGW32__) 22 | #include 23 | #define long64 int64_t 24 | #else 25 | #define long64 long long 26 | #endif 27 | 28 | namespace bParse 29 | { 30 | // ----------------------------------------------------- // 31 | class bChunkPtr4 32 | { 33 | public: 34 | bChunkPtr4() {} 35 | int code; 36 | int len; 37 | union { 38 | int m_uniqueInt; 39 | }; 40 | int dna_nr; 41 | int nr; 42 | }; 43 | 44 | // ----------------------------------------------------- // 45 | class bChunkPtr8 46 | { 47 | public: 48 | bChunkPtr8() {} 49 | int code, len; 50 | union { 51 | long64 oldPrev; 52 | int m_uniqueInts[2]; 53 | }; 54 | int dna_nr, nr; 55 | }; 56 | 57 | // ----------------------------------------------------- // 58 | class bChunkInd 59 | { 60 | public: 61 | bChunkInd() {} 62 | int code, len; 63 | void *oldPtr; 64 | int dna_nr, nr; 65 | }; 66 | 67 | // ----------------------------------------------------- // 68 | class ChunkUtils 69 | { 70 | public: 71 | // file chunk offset 72 | static int getOffset(int flags); 73 | 74 | // endian utils 75 | static short swapShort(short sht); 76 | static int swapInt(int inte); 77 | static long64 swapLong64(long64 lng); 78 | }; 79 | 80 | const int CHUNK_HEADER_LEN = ((sizeof(bChunkInd))); 81 | const bool VOID_IS_8 = ((sizeof(void *) == 8)); 82 | } // namespace bParse 83 | 84 | #endif //__BCHUNK_H__ 85 | -------------------------------------------------------------------------------- /src/Serialize/BulletFileLoader/bCommon.h: -------------------------------------------------------------------------------- 1 | /* 2 | bParse 3 | Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #ifndef __BCOMMON_H__ 17 | #define __BCOMMON_H__ 18 | 19 | #include 20 | //#include "bLog.h" 21 | #include "LinearMath/btAlignedObjectArray.h" 22 | #include "LinearMath/btHashMap.h" 23 | 24 | namespace bParse 25 | { 26 | class bMain; 27 | class bFileData; 28 | class bFile; 29 | class bDNA; 30 | 31 | // delete void* undefined 32 | typedef struct bStructHandle 33 | { 34 | int unused; 35 | } bStructHandle; 36 | typedef btAlignedObjectArray bListBasePtr; 37 | typedef btHashMap bPtrMap; 38 | } // namespace bParse 39 | 40 | #endif //__BCOMMON_H__ 41 | -------------------------------------------------------------------------------- /src/Serialize/BulletFileLoader/bDNA.h: -------------------------------------------------------------------------------- 1 | /* 2 | bParse 3 | Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #ifndef __BDNA_H__ 17 | #define __BDNA_H__ 18 | 19 | #include "bCommon.h" 20 | 21 | namespace bParse 22 | { 23 | struct bNameInfo 24 | { 25 | char *m_name; 26 | bool m_isPointer; 27 | int m_dim0; 28 | int m_dim1; 29 | }; 30 | 31 | class bDNA 32 | { 33 | public: 34 | bDNA(); 35 | ~bDNA(); 36 | 37 | void init(char *data, int len, bool swap = false); 38 | 39 | int getArraySize(char *str); 40 | int getArraySizeNew(short name) 41 | { 42 | const bNameInfo &nameInfo = m_Names[name]; 43 | return nameInfo.m_dim0 * nameInfo.m_dim1; 44 | } 45 | int getElementSize(short type, short name) 46 | { 47 | const bNameInfo &nameInfo = m_Names[name]; 48 | int size = nameInfo.m_isPointer ? mPtrLen * nameInfo.m_dim0 * nameInfo.m_dim1 : mTlens[type] * nameInfo.m_dim0 * nameInfo.m_dim1; 49 | return size; 50 | } 51 | 52 | int getNumNames() const 53 | { 54 | return m_Names.size(); 55 | } 56 | 57 | char *getName(int ind); 58 | char *getType(int ind); 59 | short *getStruct(int ind); 60 | short getLength(int ind); 61 | int getReverseType(short type); 62 | int getReverseType(const char *type); 63 | 64 | int getNumStructs(); 65 | 66 | // 67 | bool lessThan(bDNA *other); 68 | 69 | void initCmpFlags(bDNA *memDNA); 70 | bool flagNotEqual(int dna_nr); 71 | bool flagEqual(int dna_nr); 72 | bool flagNone(int dna_nr); 73 | 74 | int getPointerSize(); 75 | 76 | void dumpTypeDefinitions(); 77 | 78 | private: 79 | enum FileDNAFlags 80 | { 81 | FDF_NONE = 0, 82 | FDF_STRUCT_NEQU, 83 | FDF_STRUCT_EQU 84 | }; 85 | 86 | void initRecurseCmpFlags(int i); 87 | 88 | btAlignedObjectArray mCMPFlags; 89 | 90 | btAlignedObjectArray m_Names; 91 | btAlignedObjectArray mTypes; 92 | btAlignedObjectArray mStructs; 93 | btAlignedObjectArray mTlens; 94 | btHashMap mStructReverse; 95 | btHashMap mTypeLookup; 96 | 97 | int mPtrLen; 98 | }; 99 | } // namespace bParse 100 | 101 | #endif //__BDNA_H__ 102 | -------------------------------------------------------------------------------- /src/Serialize/BulletFileLoader/bDefines.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com 2 | * 3 | * This software is provided 'as-is', without any express or implied 4 | * warranty. In no event will the authors be held liable for any damages 5 | * arising from the use of this software. 6 | * 7 | * Permission is granted to anyone to use this software for any purpose, 8 | * including commercial applications, and to alter it and redistribute it 9 | * freely, subject to the following restrictions: 10 | * 11 | * 1. The origin of this software must not be misrepresented; you must not 12 | * claim that you wrote the original software. If you use this software 13 | * in a product, an acknowledgment in the product documentation would be 14 | * appreciated but is not required. 15 | * 2. Altered source versions must be plainly marked as such, and must not be 16 | * misrepresented as being the original software. 17 | * 3. This notice may not be removed or altered from any source distribution. 18 | */ 19 | #ifndef __B_DEFINES_H__ 20 | #define __B_DEFINES_H__ 21 | 22 | // MISC defines, see BKE_global.h, BKE_utildefines.h 23 | #define SIZEOFBLENDERHEADER 12 24 | 25 | // ------------------------------------------------------------ 26 | #if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__) 27 | #define MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d)) 28 | #else 29 | #define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a)) 30 | #endif 31 | 32 | // ------------------------------------------------------------ 33 | #if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__) 34 | #define MAKE_ID2(c, d) ((c) << 8 | (d)) 35 | #define MOST_SIG_BYTE 0 36 | #define BBIG_ENDIAN 37 | #else 38 | #define MAKE_ID2(c, d) ((d) << 8 | (c)) 39 | #define MOST_SIG_BYTE 1 40 | #define BLITTLE_ENDIAN 41 | #endif 42 | 43 | // ------------------------------------------------------------ 44 | #define ID_SCE MAKE_ID2('S', 'C') 45 | #define ID_LI MAKE_ID2('L', 'I') 46 | #define ID_OB MAKE_ID2('O', 'B') 47 | #define ID_ME MAKE_ID2('M', 'E') 48 | #define ID_CU MAKE_ID2('C', 'U') 49 | #define ID_MB MAKE_ID2('M', 'B') 50 | #define ID_MA MAKE_ID2('M', 'A') 51 | #define ID_TE MAKE_ID2('T', 'E') 52 | #define ID_IM MAKE_ID2('I', 'M') 53 | #define ID_IK MAKE_ID2('I', 'K') 54 | #define ID_WV MAKE_ID2('W', 'V') 55 | #define ID_LT MAKE_ID2('L', 'T') 56 | #define ID_SE MAKE_ID2('S', 'E') 57 | #define ID_LF MAKE_ID2('L', 'F') 58 | #define ID_LA MAKE_ID2('L', 'A') 59 | #define ID_CA MAKE_ID2('C', 'A') 60 | #define ID_IP MAKE_ID2('I', 'P') 61 | #define ID_KE MAKE_ID2('K', 'E') 62 | #define ID_WO MAKE_ID2('W', 'O') 63 | #define ID_SCR MAKE_ID2('S', 'R') 64 | #define ID_VF MAKE_ID2('V', 'F') 65 | #define ID_TXT MAKE_ID2('T', 'X') 66 | #define ID_SO MAKE_ID2('S', 'O') 67 | #define ID_SAMPLE MAKE_ID2('S', 'A') 68 | #define ID_GR MAKE_ID2('G', 'R') 69 | #define ID_ID MAKE_ID2('I', 'D') 70 | #define ID_AR MAKE_ID2('A', 'R') 71 | #define ID_AC MAKE_ID2('A', 'C') 72 | #define ID_SCRIPT MAKE_ID2('P', 'Y') 73 | #define ID_FLUIDSIM MAKE_ID2('F', 'S') 74 | #define ID_NT MAKE_ID2('N', 'T') 75 | #define ID_BR MAKE_ID2('B', 'R') 76 | 77 | #define ID_SEQ MAKE_ID2('S', 'Q') 78 | #define ID_CO MAKE_ID2('C', 'O') 79 | #define ID_PO MAKE_ID2('A', 'C') 80 | #define ID_NLA MAKE_ID2('N', 'L') 81 | 82 | #define ID_VS MAKE_ID2('V', 'S') 83 | #define ID_VN MAKE_ID2('V', 'N') 84 | 85 | // ------------------------------------------------------------ 86 | #define FORM MAKE_ID('F', 'O', 'R', 'M') 87 | #define DDG1 MAKE_ID('3', 'D', 'G', '1') 88 | #define DDG2 MAKE_ID('3', 'D', 'G', '2') 89 | #define DDG3 MAKE_ID('3', 'D', 'G', '3') 90 | #define DDG4 MAKE_ID('3', 'D', 'G', '4') 91 | #define GOUR MAKE_ID('G', 'O', 'U', 'R') 92 | #define BLEN MAKE_ID('B', 'L', 'E', 'N') 93 | #define DER_ MAKE_ID('D', 'E', 'R', '_') 94 | #define V100 MAKE_ID('V', '1', '0', '0') 95 | #define DATA MAKE_ID('D', 'A', 'T', 'A') 96 | #define GLOB MAKE_ID('G', 'L', 'O', 'B') 97 | #define IMAG MAKE_ID('I', 'M', 'A', 'G') 98 | #define USER MAKE_ID('U', 'S', 'E', 'R') 99 | 100 | // ------------------------------------------------------------ 101 | #define DNA1 MAKE_ID('D', 'N', 'A', '1') 102 | #define REND MAKE_ID('R', 'E', 'N', 'D') 103 | #define ENDB MAKE_ID('E', 'N', 'D', 'B') 104 | #define NAME MAKE_ID('N', 'A', 'M', 'E') 105 | #define SDNA MAKE_ID('S', 'D', 'N', 'A') 106 | #define TYPE MAKE_ID('T', 'Y', 'P', 'E') 107 | #define TLEN MAKE_ID('T', 'L', 'E', 'N') 108 | #define STRC MAKE_ID('S', 'T', 'R', 'C') 109 | 110 | // ------------------------------------------------------------ 111 | #define SWITCH_INT(a) \ 112 | { \ 113 | char s_i, *p_i; \ 114 | p_i = (char *)&(a); \ 115 | s_i = p_i[0]; \ 116 | p_i[0] = p_i[3]; \ 117 | p_i[3] = s_i; \ 118 | s_i = p_i[1]; \ 119 | p_i[1] = p_i[2]; \ 120 | p_i[2] = s_i; \ 121 | } 122 | 123 | // ------------------------------------------------------------ 124 | #define SWITCH_SHORT(a) \ 125 | { \ 126 | char s_i, *p_i; \ 127 | p_i = (char *)&(a); \ 128 | s_i = p_i[0]; \ 129 | p_i[0] = p_i[1]; \ 130 | p_i[1] = s_i; \ 131 | } 132 | 133 | // ------------------------------------------------------------ 134 | #define SWITCH_LONGINT(a) \ 135 | { \ 136 | char s_i, *p_i; \ 137 | p_i = (char *)&(a); \ 138 | s_i = p_i[0]; \ 139 | p_i[0] = p_i[7]; \ 140 | p_i[7] = s_i; \ 141 | s_i = p_i[1]; \ 142 | p_i[1] = p_i[6]; \ 143 | p_i[6] = s_i; \ 144 | s_i = p_i[2]; \ 145 | p_i[2] = p_i[5]; \ 146 | p_i[5] = s_i; \ 147 | s_i = p_i[3]; \ 148 | p_i[3] = p_i[4]; \ 149 | p_i[4] = s_i; \ 150 | } 151 | 152 | #endif //__B_DEFINES_H__ 153 | -------------------------------------------------------------------------------- /src/Serialize/BulletFileLoader/bFile.h: -------------------------------------------------------------------------------- 1 | /* 2 | bParse 3 | Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #ifndef __BFILE_H__ 17 | #define __BFILE_H__ 18 | 19 | #include "bCommon.h" 20 | #include "bChunk.h" 21 | #include 22 | 23 | namespace bParse 24 | { 25 | // ----------------------------------------------------- // 26 | enum bFileFlags 27 | { 28 | FD_INVALID = 0, 29 | FD_OK = 1, 30 | FD_VOID_IS_8 = 2, 31 | FD_ENDIAN_SWAP = 4, 32 | FD_FILE_64 = 8, 33 | FD_BITS_VARIES = 16, 34 | FD_VERSION_VARIES = 32, 35 | FD_DOUBLE_PRECISION = 64, 36 | FD_BROKEN_DNA = 128, 37 | FD_FILEDNA_IS_MEMDNA = 256 38 | }; 39 | 40 | enum bFileVerboseMode 41 | { 42 | FD_VERBOSE_EXPORT_XML = 1, 43 | FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS = 2, 44 | FD_VERBOSE_DUMP_CHUNKS = 4, 45 | FD_VERBOSE_DUMP_FILE_INFO = 8, 46 | }; 47 | // ----------------------------------------------------- // 48 | class bFile 49 | { 50 | protected: 51 | char m_headerString[7]; 52 | 53 | bool mOwnsBuffer; 54 | char* mFileBuffer; 55 | int mFileLen; 56 | int mVersion; 57 | 58 | bPtrMap mLibPointers; 59 | 60 | int mDataStart; 61 | bDNA* mFileDNA; 62 | bDNA* mMemoryDNA; 63 | 64 | btAlignedObjectArray m_pointerFixupArray; 65 | btAlignedObjectArray m_pointerPtrFixupArray; 66 | 67 | btAlignedObjectArray m_chunks; 68 | btHashMap m_chunkPtrPtrMap; 69 | 70 | // 71 | 72 | bPtrMap mDataPointers; 73 | 74 | int mFlags; 75 | 76 | // //////////////////////////////////////////////////////////////////////////// 77 | 78 | // buffer offset util 79 | int getNextBlock(bChunkInd* dataChunk, const char* dataPtr, const int flags); 80 | void safeSwapPtr(char* dst, const char* src); 81 | 82 | virtual void parseHeader(); 83 | 84 | virtual void parseData() = 0; 85 | 86 | void resolvePointersMismatch(); 87 | void resolvePointersChunk(const bChunkInd& dataChunk, int verboseMode); 88 | 89 | int resolvePointersStructRecursive(char* strcPtr, int old_dna, int verboseMode, int recursion); 90 | //void swapPtr(char *dst, char *src); 91 | 92 | void parseStruct(char* strcPtr, char* dtPtr, int old_dna, int new_dna, bool fixupPointers); 93 | void getMatchingFileDNA(short* old, const char* lookupName, const char* lookupType, char* strcData, char* data, bool fixupPointers); 94 | char* getFileElement(short* firstStruct, char* lookupName, char* lookupType, char* data, short** foundPos); 95 | 96 | void swap(char* head, class bChunkInd& ch, bool ignoreEndianFlag); 97 | void swapData(char* data, short type, int arraySize, bool ignoreEndianFlag); 98 | void swapStruct(int dna_nr, char* data, bool ignoreEndianFlag); 99 | void swapLen(char* dataPtr); 100 | void swapDNA(char* ptr); 101 | 102 | char* readStruct(char* head, class bChunkInd& chunk); 103 | char* getAsString(int code); 104 | 105 | virtual void parseInternal(int verboseMode, char* memDna, int memDnaLength); 106 | 107 | public: 108 | bFile(const char* filename, const char headerString[7]); 109 | 110 | //todo: make memoryBuffer const char 111 | //bFile( const char *memoryBuffer, int len); 112 | bFile(char* memoryBuffer, int len, const char headerString[7]); 113 | virtual ~bFile(); 114 | 115 | bDNA* getFileDNA() 116 | { 117 | return mFileDNA; 118 | } 119 | 120 | virtual void addDataBlock(char* dataBlock) = 0; 121 | 122 | int getFlags() const 123 | { 124 | return mFlags; 125 | } 126 | 127 | void setFileDNAisMemoryDNA() 128 | { 129 | mFlags |= FD_FILEDNA_IS_MEMDNA; 130 | } 131 | 132 | bPtrMap& getLibPointers() 133 | { 134 | return mLibPointers; 135 | } 136 | 137 | void* findLibPointer(void* ptr); 138 | 139 | bool ok(); 140 | 141 | virtual void parse(int verboseMode) = 0; 142 | 143 | virtual int write(const char* fileName, bool fixupPointers = false) = 0; 144 | 145 | virtual void writeChunks(FILE* fp, bool fixupPointers); 146 | 147 | virtual void writeDNA(FILE* fp) = 0; 148 | 149 | void updateOldPointers(); 150 | void resolvePointers(int verboseMode); 151 | 152 | void dumpChunks(bDNA* dna); 153 | 154 | virtual void setFileDNA(int verboseMode, char* buffer, int len); 155 | 156 | int getVersion() const 157 | { 158 | return mVersion; 159 | } 160 | //pre-swap the endianness, so that data loaded on a target with different endianness doesn't need to be swapped 161 | void preSwap(); 162 | void writeFile(const char* fileName); 163 | }; 164 | } // namespace bParse 165 | 166 | #endif //__BFILE_H__ 167 | -------------------------------------------------------------------------------- /src/Serialize/BulletFileLoader/btBulletFile.h: -------------------------------------------------------------------------------- 1 | /* 2 | bParse 3 | Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com 4 | 5 | This software is provided 'as-is', without any express or implied warranty. 6 | In no event will the authors be held liable for any damages arising from the use of this software. 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it freely, 9 | subject to the following restrictions: 10 | 11 | 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. 12 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 | 3. This notice may not be removed or altered from any source distribution. 14 | */ 15 | 16 | #ifndef BT_BULLET_FILE_H 17 | #define BT_BULLET_FILE_H 18 | 19 | #include "bFile.h" 20 | #include "LinearMath/btAlignedObjectArray.h" 21 | #include "bDefines.h" 22 | 23 | #include "LinearMath/btSerializer.h" 24 | 25 | namespace bParse 26 | { 27 | // ----------------------------------------------------- // 28 | class btBulletFile : public bFile 29 | { 30 | protected: 31 | char* m_DnaCopy; 32 | 33 | public: 34 | btAlignedObjectArray m_multiBodies; 35 | 36 | btAlignedObjectArray m_multiBodyLinkColliders; 37 | 38 | btAlignedObjectArray m_softBodies; 39 | 40 | btAlignedObjectArray m_rigidBodies; 41 | 42 | btAlignedObjectArray m_collisionObjects; 43 | 44 | btAlignedObjectArray m_collisionShapes; 45 | 46 | btAlignedObjectArray m_constraints; 47 | 48 | btAlignedObjectArray m_bvhs; 49 | 50 | btAlignedObjectArray m_triangleInfoMaps; 51 | 52 | btAlignedObjectArray m_dynamicsWorldInfo; 53 | 54 | btAlignedObjectArray m_contactManifolds; 55 | 56 | btAlignedObjectArray m_dataBlocks; 57 | btBulletFile(); 58 | 59 | btBulletFile(const char* fileName); 60 | 61 | btBulletFile(char* memoryBuffer, int len); 62 | 63 | virtual ~btBulletFile(); 64 | 65 | virtual void addDataBlock(char* dataBlock); 66 | 67 | // experimental 68 | virtual int write(const char* fileName, bool fixupPointers = false); 69 | 70 | virtual void parse(int verboseMode); 71 | 72 | virtual void parseData(); 73 | 74 | virtual void writeDNA(FILE* fp); 75 | 76 | void addStruct(const char* structType, void* data, int len, void* oldPtr, int code); 77 | }; 78 | }; // namespace bParse 79 | 80 | #endif //BT_BULLET_FILE_H 81 | -------------------------------------------------------------------------------- /src/SharedMemory/BodyJointInfoUtility.h: -------------------------------------------------------------------------------- 1 | #ifndef BODY_JOINT_INFO_UTILITY_H 2 | #define BODY_JOINT_INFO_UTILITY_H 3 | 4 | #include "Bullet3Common/b3Logging.h" 5 | 6 | namespace Bullet 7 | { 8 | class btMultiBodyDoubleData; 9 | class btMultiBodyFloatData; 10 | }; // namespace Bullet 11 | 12 | inline char* strDup(const char* const str) 13 | { 14 | #ifdef _WIN32 15 | return _strdup(str); 16 | #else 17 | return strdup(str); 18 | #endif 19 | } 20 | 21 | template 22 | void addJointInfoFromMultiBodyData(const T* mb, U* bodyJoints, bool verboseOutput) 23 | { 24 | int numDofs = 0; 25 | if (mb->m_baseMass>0) 26 | { 27 | numDofs = 6; 28 | } 29 | 30 | if (mb->m_baseName) 31 | { 32 | if (verboseOutput) 33 | { 34 | b3Printf("mb->m_baseName = %s\n", mb->m_baseName); 35 | } 36 | } 37 | int qOffset = 7; 38 | int uOffset = 6; 39 | 40 | for (int link = 0; link < mb->m_numLinks; link++) 41 | { 42 | { 43 | b3JointInfo info; 44 | info.m_jointName[0] = 0; 45 | info.m_linkName[0] = 0; 46 | info.m_flags = 0; 47 | info.m_jointIndex = link; 48 | info.m_qIndex = 49 | (0 < mb->m_links[link].m_posVarCount) ? qOffset : -1; 50 | info.m_uIndex = 51 | (0 < mb->m_links[link].m_dofCount) ? uOffset : -1; 52 | 53 | if (mb->m_links[link].m_linkName) 54 | { 55 | if (verboseOutput) 56 | { 57 | b3Printf("mb->m_links[%d].m_linkName = %s\n", link, 58 | mb->m_links[link].m_linkName); 59 | } 60 | strcpy(info.m_linkName, mb->m_links[link].m_linkName); 61 | } 62 | if (mb->m_links[link].m_jointName) 63 | { 64 | if (verboseOutput) 65 | { 66 | b3Printf("mb->m_links[%d].m_jointName = %s\n", link, 67 | mb->m_links[link].m_jointName); 68 | } 69 | strcpy(info.m_jointName, mb->m_links[link].m_jointName); 70 | //info.m_jointName = strDup(mb->m_links[link].m_jointName); 71 | } 72 | 73 | info.m_jointType = mb->m_links[link].m_jointType; 74 | info.m_jointDamping = mb->m_links[link].m_jointDamping; 75 | info.m_jointFriction = mb->m_links[link].m_jointFriction; 76 | info.m_jointLowerLimit = mb->m_links[link].m_jointLowerLimit; 77 | info.m_jointUpperLimit = mb->m_links[link].m_jointUpperLimit; 78 | info.m_jointMaxForce = mb->m_links[link].m_jointMaxForce; 79 | info.m_jointMaxVelocity = mb->m_links[link].m_jointMaxVelocity; 80 | 81 | info.m_parentFrame[0] = mb->m_links[link].m_parentComToThisPivotOffset.m_floats[0]; 82 | info.m_parentFrame[1] = mb->m_links[link].m_parentComToThisPivotOffset.m_floats[1]; 83 | info.m_parentFrame[2] = mb->m_links[link].m_parentComToThisPivotOffset.m_floats[2]; 84 | info.m_parentFrame[3] = mb->m_links[link].m_zeroRotParentToThis.m_floats[0]; 85 | info.m_parentFrame[4] = mb->m_links[link].m_zeroRotParentToThis.m_floats[1]; 86 | info.m_parentFrame[5] = mb->m_links[link].m_zeroRotParentToThis.m_floats[2]; 87 | info.m_parentFrame[6] = mb->m_links[link].m_zeroRotParentToThis.m_floats[3]; 88 | 89 | info.m_jointAxis[0] = 0; 90 | info.m_jointAxis[1] = 0; 91 | info.m_jointAxis[2] = 0; 92 | info.m_parentIndex = mb->m_links[link].m_parentIndex; 93 | 94 | if (info.m_jointType == eRevoluteType) 95 | { 96 | info.m_jointAxis[0] = mb->m_links[link].m_jointAxisTop[0].m_floats[0]; 97 | info.m_jointAxis[1] = mb->m_links[link].m_jointAxisTop[0].m_floats[1]; 98 | info.m_jointAxis[2] = mb->m_links[link].m_jointAxisTop[0].m_floats[2]; 99 | } 100 | if (info.m_jointType == ePrismaticType) 101 | { 102 | info.m_jointAxis[0] = mb->m_links[link].m_jointAxisBottom[0].m_floats[0]; 103 | info.m_jointAxis[1] = mb->m_links[link].m_jointAxisBottom[0].m_floats[1]; 104 | info.m_jointAxis[2] = mb->m_links[link].m_jointAxisBottom[0].m_floats[2]; 105 | } 106 | 107 | if ((mb->m_links[link].m_jointType == eRevoluteType) || 108 | (mb->m_links[link].m_jointType == ePrismaticType)) 109 | { 110 | info.m_flags |= JOINT_HAS_MOTORIZED_POWER; 111 | } 112 | bodyJoints->m_jointInfo.push_back(info); 113 | } 114 | qOffset += mb->m_links[link].m_posVarCount; 115 | uOffset += mb->m_links[link].m_dofCount; 116 | numDofs += mb->m_links[link].m_dofCount; 117 | } 118 | bodyJoints->m_numDofs = numDofs; 119 | } 120 | 121 | #endif //BODY_JOINT_INFO_UTILITY_H 122 | -------------------------------------------------------------------------------- /src/SharedMemory/InProcessMemory.cpp: -------------------------------------------------------------------------------- 1 | #include "InProcessMemory.h" 2 | 3 | #include "LinearMath/btHashMap.h" 4 | 5 | struct InProcessMemoryInternalData 6 | { 7 | btHashMap m_memoryPointers; 8 | }; 9 | 10 | InProcessMemory::InProcessMemory() 11 | { 12 | m_data = new InProcessMemoryInternalData; 13 | } 14 | 15 | InProcessMemory::~InProcessMemory() 16 | { 17 | for (int i = 0; i < m_data->m_memoryPointers.size(); i++) 18 | { 19 | void** ptrptr = m_data->m_memoryPointers.getAtIndex(i); 20 | if (ptrptr) 21 | { 22 | void* ptr = *ptrptr; 23 | free(ptr); 24 | } 25 | } 26 | delete m_data; 27 | } 28 | 29 | void* InProcessMemory::allocateSharedMemory(int key, int size, bool allowCreation) 30 | { 31 | void** ptrptr = m_data->m_memoryPointers[key]; 32 | if (ptrptr) 33 | { 34 | return *ptrptr; 35 | } 36 | 37 | void* ptr = malloc(size); 38 | m_data->m_memoryPointers.insert(key, ptr); 39 | return ptr; 40 | } 41 | 42 | void InProcessMemory::releaseSharedMemory(int /*key*/, int /*size*/) 43 | { 44 | //we don't release the memory here, but in the destructor instead, 45 | //so multiple users could 'share' the memory given some key 46 | } -------------------------------------------------------------------------------- /src/SharedMemory/InProcessMemory.h: -------------------------------------------------------------------------------- 1 | #ifndef IN_PROCESS_MEMORY_H 2 | #define IN_PROCESS_MEMORY_H 3 | 4 | #include "SharedMemoryInterface.h" 5 | 6 | class InProcessMemory : public SharedMemoryInterface 7 | { 8 | struct InProcessMemoryInternalData* m_data; 9 | 10 | public: 11 | InProcessMemory(); 12 | virtual ~InProcessMemory(); 13 | 14 | virtual void* allocateSharedMemory(int key, int size, bool allowCreation); 15 | virtual void releaseSharedMemory(int key, int size); 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/SharedMemory/PhysicsClient.cpp: -------------------------------------------------------------------------------- 1 | #include "PhysicsClient.h" 2 | 3 | PhysicsClient::~PhysicsClient() 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/SharedMemory/PhysicsClient.h: -------------------------------------------------------------------------------- 1 | #ifndef BT_PHYSICS_CLIENT_API_H 2 | #define BT_PHYSICS_CLIENT_API_H 3 | 4 | //#include "SharedMemoryCommands.h" 5 | #include "LinearMath/btVector3.h" 6 | 7 | class PhysicsClient 8 | { 9 | public: 10 | virtual ~PhysicsClient(); 11 | 12 | // return true if connection succesfull, can also check 'isConnected' 13 | virtual bool connect() = 0; 14 | 15 | virtual void disconnectSharedMemory() = 0; 16 | 17 | virtual bool isConnected() const = 0; 18 | 19 | // return non-null if there is a status, nullptr otherwise 20 | virtual const struct SharedMemoryStatus* processServerStatus() = 0; 21 | 22 | virtual struct SharedMemoryCommand* getAvailableSharedMemoryCommand() = 0; 23 | 24 | virtual bool canSubmitCommand() const = 0; 25 | 26 | virtual bool submitClientCommand(const struct SharedMemoryCommand& command) = 0; 27 | 28 | virtual int getNumBodies() const = 0; 29 | 30 | virtual int getBodyUniqueId(int serialIndex) const = 0; 31 | 32 | virtual bool getBodyInfo(int bodyUniqueId, struct b3BodyInfo& info) const = 0; 33 | 34 | virtual int getNumJoints(int bodyUniqueId) const = 0; 35 | 36 | virtual int getNumDofs(int bodyUniqueId) const = 0; 37 | 38 | virtual bool getJointInfo(int bodyUniqueId, int jointIndex, struct b3JointInfo& info) const = 0; 39 | 40 | virtual int getNumUserConstraints() const = 0; 41 | 42 | virtual int getUserConstraintInfo(int constraintUniqueId, struct b3UserConstraint& info) const = 0; 43 | 44 | virtual int getUserConstraintId(int serialIndex) const = 0; 45 | 46 | virtual void setSharedMemoryKey(int key) = 0; 47 | 48 | virtual void uploadBulletFileToSharedMemory(const char* data, int len) = 0; 49 | 50 | virtual void uploadRaysToSharedMemory(struct SharedMemoryCommand& command, const double* rayFromWorldArray, const double* rayToWorldArray, int numRays) = 0; 51 | 52 | virtual int getNumDebugLines() const = 0; 53 | 54 | virtual const float* getDebugLinesFrom() const = 0; 55 | virtual const float* getDebugLinesTo() const = 0; 56 | virtual const float* getDebugLinesColor() const = 0; 57 | 58 | virtual void getCachedCameraImage(struct b3CameraImageData* cameraData) = 0; 59 | 60 | virtual void getCachedContactPointInformation(struct b3ContactInformation* contactPointData) = 0; 61 | 62 | virtual void getCachedOverlappingObjects(struct b3AABBOverlapData* overlappingObjects) = 0; 63 | 64 | virtual void getCachedVisualShapeInformation(struct b3VisualShapeInformation* visualShapesInfo) = 0; 65 | 66 | virtual void getCachedCollisionShapeInformation(struct b3CollisionShapeInformation* collisionShapesInfo) = 0; 67 | 68 | virtual void getCachedMeshData(struct b3MeshData* meshData) = 0; 69 | 70 | virtual void getCachedVREvents(struct b3VREventsData* vrEventsData) = 0; 71 | 72 | virtual void getCachedKeyboardEvents(struct b3KeyboardEventsData* keyboardEventsData) = 0; 73 | 74 | virtual void getCachedMouseEvents(struct b3MouseEventsData* mouseEventsData) = 0; 75 | 76 | virtual void getCachedRaycastHits(struct b3RaycastInformation* raycastHits) = 0; 77 | 78 | virtual void getCachedMassMatrix(int dofCountCheck, double* massMatrix) = 0; 79 | 80 | virtual bool getCachedReturnData(struct b3UserDataValue* returnData) = 0; 81 | 82 | virtual void setTimeOut(double timeOutInSeconds) = 0; 83 | virtual double getTimeOut() const = 0; 84 | 85 | virtual bool getCachedUserData(int userDataId, struct b3UserDataValue& valueOut) const = 0; 86 | virtual int getCachedUserDataId(int bodyUniqueId, int linkIndex, int visualShapeIndex, const char* key) const = 0; 87 | virtual int getNumUserData(int bodyUniqueId) const = 0; 88 | virtual void getUserDataInfo(int bodyUniqueId, int userDataIndex, const char** keyOut, int* userDataIdOut, int* linkIndexOut, int* visualShapeIndexOut) const = 0; 89 | 90 | virtual void pushProfileTiming(const char* timingName) = 0; 91 | virtual void popProfileTiming() = 0; 92 | }; 93 | 94 | #endif // BT_PHYSICS_CLIENT_API_H 95 | -------------------------------------------------------------------------------- /src/SharedMemory/PhysicsClientSharedMemory.h: -------------------------------------------------------------------------------- 1 | #ifndef BT_PHYSICS_CLIENT_SHARED_MEMORY_API_H 2 | #define BT_PHYSICS_CLIENT_SHARED_MEMORY_API_H 3 | 4 | #include "PhysicsClient.h" 5 | 6 | //#include "SharedMemoryCommands.h" 7 | #include "LinearMath/btVector3.h" 8 | 9 | class PhysicsClientSharedMemory : public PhysicsClient 10 | { 11 | 12 | 13 | protected: 14 | struct PhysicsClientSharedMemoryInternalData* m_data; 15 | virtual void setSharedMemoryInterface(class SharedMemoryInterface* sharedMem); 16 | void processBodyJointInfo(int bodyUniqueId, const struct SharedMemoryStatus& serverCmd); 17 | void resetData(); 18 | void removeCachedBody(int bodyUniqueId); 19 | void clearCachedBodies(); 20 | virtual void renderSceneInternal(){}; 21 | 22 | public: 23 | PhysicsClientSharedMemory(); 24 | virtual ~PhysicsClientSharedMemory(); 25 | 26 | // return true if connection succesfull, can also check 'isConnected' 27 | virtual bool connect(); 28 | 29 | virtual void disconnectSharedMemory(); 30 | 31 | virtual bool isConnected() const; 32 | 33 | // return non-null if there is a status, nullptr otherwise 34 | virtual const struct SharedMemoryStatus* processServerStatus(); 35 | 36 | virtual struct SharedMemoryCommand* getAvailableSharedMemoryCommand(); 37 | 38 | virtual bool canSubmitCommand() const; 39 | 40 | virtual bool submitClientCommand(const struct SharedMemoryCommand& command); 41 | 42 | virtual int getNumBodies() const; 43 | 44 | virtual int getBodyUniqueId(int serialIndex) const; 45 | 46 | virtual bool getBodyInfo(int bodyUniqueId, struct b3BodyInfo& info) const; 47 | 48 | virtual int getNumJoints(int bodyUniqueId) const; 49 | 50 | virtual int getNumDofs(int bodyUniqueId) const; 51 | 52 | virtual bool getJointInfo(int bodyUniqueId, int jointIndex, struct b3JointInfo& info) const; 53 | 54 | virtual int getNumUserConstraints() const; 55 | 56 | virtual int getUserConstraintInfo(int constraintUniqueId, struct b3UserConstraint& info) const; 57 | 58 | virtual int getUserConstraintId(int serialIndex) const; 59 | 60 | virtual void setSharedMemoryKey(int key); 61 | 62 | virtual void uploadBulletFileToSharedMemory(const char* data, int len); 63 | 64 | virtual void uploadRaysToSharedMemory(struct SharedMemoryCommand& command, const double* rayFromWorldArray, const double* rayToWorldArray, int numRays); 65 | 66 | virtual int getNumDebugLines() const; 67 | 68 | virtual const float* getDebugLinesFrom() const; 69 | virtual const float* getDebugLinesTo() const; 70 | virtual const float* getDebugLinesColor() const; 71 | virtual void getCachedCameraImage(struct b3CameraImageData* cameraData); 72 | 73 | virtual void getCachedContactPointInformation(struct b3ContactInformation* contactPointData); 74 | 75 | virtual void getCachedOverlappingObjects(struct b3AABBOverlapData* overlappingObjects); 76 | 77 | virtual void getCachedVisualShapeInformation(struct b3VisualShapeInformation* visualShapesInfo); 78 | 79 | virtual void getCachedCollisionShapeInformation(struct b3CollisionShapeInformation* collisionShapesInfo); 80 | 81 | virtual void getCachedMeshData(struct b3MeshData* meshData); 82 | 83 | virtual void getCachedVREvents(struct b3VREventsData* vrEventsData); 84 | 85 | virtual void getCachedKeyboardEvents(struct b3KeyboardEventsData* keyboardEventsData); 86 | 87 | virtual void getCachedMouseEvents(struct b3MouseEventsData* mouseEventsData); 88 | 89 | virtual void getCachedRaycastHits(struct b3RaycastInformation* raycastHits); 90 | 91 | virtual void getCachedMassMatrix(int dofCountCheck, double* massMatrix); 92 | 93 | virtual bool getCachedReturnData(b3UserDataValue* returnData); 94 | 95 | virtual void setTimeOut(double timeOutInSeconds); 96 | virtual double getTimeOut() const; 97 | 98 | virtual bool getCachedUserData(int userDataId, struct b3UserDataValue& valueOut) const; 99 | virtual int getCachedUserDataId(int bodyUniqueId, int linkIndex, int visualShapeIndex, const char* key) const; 100 | virtual int getNumUserData(int bodyUniqueId) const; 101 | virtual void getUserDataInfo(int bodyUniqueId, int userDataIndex, const char** keyOut, int* userDataIdOut, int* linkIndexOut, int* visualShapeIndexOut) const; 102 | 103 | virtual void pushProfileTiming(const char* timingName); 104 | virtual void popProfileTiming(); 105 | }; 106 | 107 | #endif // BT_PHYSICS_CLIENT_API_H 108 | -------------------------------------------------------------------------------- /src/SharedMemory/PhysicsClientSharedMemory_C_API.cpp: -------------------------------------------------------------------------------- 1 | #include "PhysicsClientSharedMemory_C_API.h" 2 | 3 | #include "PhysicsClientSharedMemory.h" 4 | 5 | B3_SHARED_API b3PhysicsClientHandle b3ConnectSharedMemory(int key) 6 | { 7 | PhysicsClientSharedMemory* cl = new PhysicsClientSharedMemory(); 8 | cl->setSharedMemoryKey(key); 9 | cl->connect(); 10 | return (b3PhysicsClientHandle)cl; 11 | } 12 | -------------------------------------------------------------------------------- /src/SharedMemory/PhysicsClientSharedMemory_C_API.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICS_CLIENT_SHARED_MEMORY_H 2 | #define PHYSICS_CLIENT_SHARED_MEMORY_H 3 | 4 | #include "PhysicsClientC_API.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" 8 | { 9 | #endif 10 | 11 | B3_SHARED_API b3PhysicsClientHandle b3ConnectSharedMemory(int key); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif //PHYSICS_CLIENT_SHARED_MEMORY_H 18 | -------------------------------------------------------------------------------- /src/SharedMemory/PhysicsCommandProcessorInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYSICS_COMMAND_PROCESSOR_INTERFACE_H 2 | #define PHYSICS_COMMAND_PROCESSOR_INTERFACE_H 3 | 4 | enum PhysicsCommandRenderFlags 5 | { 6 | COV_DISABLE_SYNC_RENDERING = 1 7 | }; 8 | 9 | class PhysicsCommandProcessorInterface 10 | { 11 | public: 12 | virtual ~PhysicsCommandProcessorInterface() {} 13 | 14 | virtual bool connect() = 0; 15 | 16 | virtual void disconnect() = 0; 17 | 18 | virtual bool isConnected() const = 0; 19 | 20 | virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) = 0; 21 | 22 | virtual bool receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) = 0; 23 | 24 | virtual void renderScene(int renderFlags) = 0; 25 | virtual void physicsDebugDraw(int debugDrawFlags) = 0; 26 | virtual void setGuiHelper(struct GUIHelperInterface* guiHelper) = 0; 27 | virtual void setTimeOut(double timeOutInSeconds) = 0; 28 | 29 | virtual void reportNotifications() = 0; 30 | }; 31 | 32 | class btVector3; 33 | class btQuaternion; 34 | 35 | class CommandProcessorInterface : public PhysicsCommandProcessorInterface 36 | { 37 | public: 38 | virtual ~CommandProcessorInterface() {} 39 | 40 | virtual void syncPhysicsToGraphics() = 0; 41 | virtual void stepSimulationRealTime(double dtInSec, const struct b3VRControllerEvent* vrControllerEvents, int numVRControllerEvents, const struct b3KeyboardEvent* keyEvents, int numKeyEvents, const struct b3MouseEvent* mouseEvents, int numMouseEvents) = 0; 42 | virtual void enableRealTimeSimulation(bool enableRealTimeSim) = 0; 43 | virtual bool isRealTimeSimulationEnabled() const = 0; 44 | 45 | virtual void enableCommandLogging(bool enable, const char* fileName) = 0; 46 | virtual void replayFromLogFile(const char* fileName) = 0; 47 | virtual void replayLogCommand(char* bufferServerToClient, int bufferSizeInBytes) = 0; 48 | 49 | virtual bool pickBody(const btVector3& rayFromWorld, const btVector3& rayToWorld) = 0; 50 | virtual bool movePickedBody(const btVector3& rayFromWorld, const btVector3& rayToWorld) = 0; 51 | virtual void removePickingConstraint() = 0; 52 | 53 | virtual const btVector3& getVRTeleportPosition() const = 0; 54 | virtual void setVRTeleportPosition(const btVector3& vrReleportPos) = 0; 55 | 56 | virtual const btQuaternion& getVRTeleportOrientation() const = 0; 57 | virtual void setVRTeleportOrientation(const btQuaternion& vrReleportOrn) = 0; 58 | 59 | virtual void processClientCommands() = 0; 60 | }; 61 | 62 | #endif //PHYSICS_COMMAND_PROCESSOR_INTERFACE_H 63 | -------------------------------------------------------------------------------- /src/SharedMemory/PosixSharedMemory.cpp: -------------------------------------------------------------------------------- 1 | #include "PosixSharedMemory.h" 2 | #include "Bullet3Common/b3Logging.h" 3 | #include "LinearMath/btScalar.h" //for btAssert 4 | #include "LinearMath/btAlignedObjectArray.h" 5 | 6 | //Windows implementation is in Win32SharedMemory.cpp 7 | #ifndef _WIN32 8 | #define TEST_SHARED_MEMORY 9 | #endif //_WIN32 10 | 11 | #include 12 | 13 | #ifdef TEST_SHARED_MEMORY 14 | 15 | #include 16 | #include 17 | 18 | #endif 19 | 20 | struct btSharedMemorySegment 21 | { 22 | int m_key; 23 | int m_sharedMemoryId; 24 | void* m_sharedMemoryPtr; 25 | bool m_createdSharedMemory; 26 | 27 | btSharedMemorySegment() 28 | : m_sharedMemoryId(-1), 29 | m_sharedMemoryPtr(0), 30 | m_createdSharedMemory(true) 31 | { 32 | } 33 | }; 34 | 35 | struct PosixSharedMemoryInteralData 36 | { 37 | btAlignedObjectArray m_segments; 38 | 39 | PosixSharedMemoryInteralData() 40 | { 41 | } 42 | }; 43 | 44 | PosixSharedMemory::PosixSharedMemory() 45 | { 46 | m_internalData = new PosixSharedMemoryInteralData; 47 | } 48 | 49 | PosixSharedMemory::~PosixSharedMemory() 50 | { 51 | delete m_internalData; 52 | } 53 | 54 | struct btPointerCaster 55 | { 56 | union { 57 | void* ptr; 58 | ptrdiff_t integer; 59 | }; 60 | }; 61 | 62 | void* PosixSharedMemory::allocateSharedMemory(int key, int size, bool allowCreation) 63 | { 64 | #ifdef TEST_SHARED_MEMORY 65 | 66 | { 67 | btSharedMemorySegment* seg = 0; 68 | int i = 0; 69 | 70 | for (i = 0; i < m_internalData->m_segments.size(); i++) 71 | { 72 | if (m_internalData->m_segments[i].m_key == key) 73 | { 74 | seg = &m_internalData->m_segments[i]; 75 | break; 76 | } 77 | } 78 | if (seg) 79 | { 80 | b3Error("already created shared memory segment using same key"); 81 | return seg->m_sharedMemoryPtr; 82 | } 83 | } 84 | 85 | int flags = (allowCreation ? IPC_CREAT : 0) | 0666; 86 | int id = shmget((key_t)key, (size_t)size, flags); 87 | if (id < 0) 88 | { 89 | //b3Warning("shmget error1"); 90 | } 91 | else 92 | { 93 | btPointerCaster result; 94 | result.ptr = shmat(id, 0, 0); 95 | if (result.integer == -1) 96 | { 97 | b3Error("shmat returned -1"); 98 | } 99 | else 100 | { 101 | btSharedMemorySegment seg; 102 | seg.m_key = key; 103 | seg.m_createdSharedMemory = allowCreation; 104 | seg.m_sharedMemoryId = id; 105 | seg.m_sharedMemoryPtr = result.ptr; 106 | m_internalData->m_segments.push_back(seg); 107 | return result.ptr; 108 | } 109 | } 110 | #else 111 | //not implemented yet 112 | btAssert(0); 113 | #endif 114 | return 0; 115 | } 116 | void PosixSharedMemory::releaseSharedMemory(int key, int size) 117 | { 118 | #ifdef TEST_SHARED_MEMORY 119 | 120 | btSharedMemorySegment* seg = 0; 121 | int i = 0; 122 | 123 | for (i = 0; i < m_internalData->m_segments.size(); i++) 124 | { 125 | if (m_internalData->m_segments[i].m_key == key) 126 | { 127 | seg = &m_internalData->m_segments[i]; 128 | break; 129 | } 130 | } 131 | 132 | if (0 == seg) 133 | { 134 | b3Error("PosixSharedMemory::releaseSharedMemory: shared memory key not found"); 135 | return; 136 | } 137 | 138 | if (seg->m_sharedMemoryId < 0) 139 | { 140 | b3Error("PosixSharedMemory::releaseSharedMemory: shared memory id is not set"); 141 | } 142 | else 143 | { 144 | if (seg->m_createdSharedMemory) 145 | { 146 | int result = shmctl(seg->m_sharedMemoryId, IPC_RMID, 0); 147 | if (result == -1) 148 | { 149 | b3Error("PosixSharedMemory::releaseSharedMemory: shmat returned -1"); 150 | } 151 | else 152 | { 153 | b3Printf("PosixSharedMemory::releaseSharedMemory removed shared memory"); 154 | } 155 | seg->m_createdSharedMemory = false; 156 | seg->m_sharedMemoryId = -1; 157 | } 158 | if (seg->m_sharedMemoryPtr) 159 | { 160 | shmdt(seg->m_sharedMemoryPtr); 161 | seg->m_sharedMemoryPtr = 0; 162 | b3Printf("PosixSharedMemory::releaseSharedMemory detached shared memory\n"); 163 | } 164 | } 165 | 166 | m_internalData->m_segments.removeAtIndex(i); 167 | 168 | #endif 169 | } 170 | -------------------------------------------------------------------------------- /src/SharedMemory/PosixSharedMemory.h: -------------------------------------------------------------------------------- 1 | #ifndef POSIX_SHARED_MEMORY_H 2 | #define POSIX_SHARED_MEMORY_H 3 | 4 | #include "SharedMemoryInterface.h" 5 | 6 | class PosixSharedMemory : public SharedMemoryInterface 7 | { 8 | struct PosixSharedMemoryInteralData* m_internalData; 9 | 10 | public: 11 | PosixSharedMemory(); 12 | virtual ~PosixSharedMemory(); 13 | 14 | virtual void* allocateSharedMemory(int key, int size, bool allowCreation); 15 | virtual void releaseSharedMemory(int key, int size); 16 | }; 17 | 18 | #endif // 19 | -------------------------------------------------------------------------------- /src/SharedMemory/SharedMemoryBlock.h: -------------------------------------------------------------------------------- 1 | #ifndef SHARED_MEMORY_BLOCK_H 2 | #define SHARED_MEMORY_BLOCK_H 3 | 4 | #define SHARED_MEMORY_MAX_COMMANDS 1 5 | 6 | #include "SharedMemoryCommands.h" 7 | 8 | struct SharedMemoryBlock 9 | { 10 | int m_magicId; 11 | struct SharedMemoryCommand m_clientCommands[SHARED_MEMORY_MAX_COMMANDS]; 12 | struct SharedMemoryStatus m_serverCommands[SHARED_MEMORY_MAX_COMMANDS]; 13 | 14 | int m_numClientCommands; 15 | int m_numProcessedClientCommands; 16 | 17 | int m_numServerCommands; 18 | int m_numProcessedServerCommands; 19 | 20 | 21 | //m_bulletStreamDataServerToClient is used to send (debug) data from server to client, for 22 | //example to provide all details of a multibody including joint/link names, after loading a URDF file. 23 | char m_bulletStreamDataServerToClientRefactor[SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE]; 24 | }; 25 | 26 | //http://stackoverflow.com/questions/24736304/unable-to-use-inline-in-declaration-get-error-c2054 27 | #ifdef _WIN32 28 | __inline 29 | #else 30 | inline 31 | #endif 32 | void 33 | InitSharedMemoryBlock(struct SharedMemoryBlock* sharedMemoryBlock) 34 | { 35 | sharedMemoryBlock->m_numClientCommands = 0; 36 | sharedMemoryBlock->m_numServerCommands = 0; 37 | sharedMemoryBlock->m_numProcessedClientCommands = 0; 38 | sharedMemoryBlock->m_numProcessedServerCommands = 0; 39 | sharedMemoryBlock->m_magicId = SHARED_MEMORY_MAGIC_NUMBER; 40 | } 41 | 42 | #define SHARED_MEMORY_SIZE sizeof(SharedMemoryBlock) 43 | 44 | #endif //SHARED_MEMORY_BLOCK_H 45 | -------------------------------------------------------------------------------- /src/SharedMemory/SharedMemoryCommandProcessor.h: -------------------------------------------------------------------------------- 1 | #ifndef SHARED_MEMORY_COMMAND_PROCESSOR_H 2 | #define SHARED_MEMORY_COMMAND_PROCESSOR_H 3 | 4 | #include "PhysicsCommandProcessorInterface.h" 5 | 6 | class SharedMemoryCommandProcessor : public PhysicsCommandProcessorInterface 7 | { 8 | struct SharedMemoryCommandProcessorInternalData* m_data; 9 | 10 | public: 11 | SharedMemoryCommandProcessor(); 12 | 13 | virtual ~SharedMemoryCommandProcessor(); 14 | 15 | virtual bool connect(); 16 | 17 | virtual void disconnect(); 18 | 19 | virtual bool isConnected() const; 20 | 21 | virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes); 22 | 23 | virtual bool receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes); 24 | 25 | virtual void renderScene(int renderFlags); 26 | virtual void physicsDebugDraw(int debugDrawFlags); 27 | virtual void setGuiHelper(struct GUIHelperInterface* guiHelper); 28 | 29 | void setSharedMemoryInterface(class SharedMemoryInterface* sharedMem); 30 | void setSharedMemoryKey(int key); 31 | virtual void setTimeOut(double timeOutInSeconds); 32 | 33 | virtual void reportNotifications() {} 34 | }; 35 | 36 | #endif //SHARED_MEMORY_COMMAND_PROCESSOR_H 37 | -------------------------------------------------------------------------------- /src/SharedMemory/SharedMemoryCommon.h: -------------------------------------------------------------------------------- 1 | #ifndef SHARED_MEMORY_COMMON_H 2 | #define SHARED_MEMORY_COMMON_H 3 | 4 | #include "../CommonInterfaces/CommonMultiBodyBase.h" 5 | 6 | class SharedMemoryCommon : public CommonExampleInterface 7 | { 8 | protected: 9 | struct GUIHelperInterface* m_guiHelper; 10 | 11 | public: 12 | SharedMemoryCommon(GUIHelperInterface* helper) 13 | : m_guiHelper(helper) 14 | { 15 | } 16 | 17 | virtual void setSharedMemoryKey(int key) = 0; 18 | virtual bool wantsTermination() = 0; 19 | virtual bool isConnected() = 0; 20 | }; 21 | #endif // 22 | -------------------------------------------------------------------------------- /src/SharedMemory/SharedMemoryInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef SHARED_MEMORY_INTERFACE_H 2 | #define SHARED_MEMORY_INTERFACE_H 3 | 4 | class SharedMemoryInterface 5 | { 6 | public: 7 | virtual ~SharedMemoryInterface() 8 | { 9 | } 10 | 11 | virtual void* allocateSharedMemory(int key, int size, bool allowCreation) = 0; 12 | virtual void releaseSharedMemory(int key, int size) = 0; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/SharedMemory/SharedMemoryUserData.h: -------------------------------------------------------------------------------- 1 | #ifndef SHARED_MEMORY_USER_DATA_H 2 | #define SHARED_MEMORY_USER_DATA_H 3 | 4 | #include 5 | #include "LinearMath/btAlignedObjectArray.h" 6 | #include "LinearMath/btHashMap.h" 7 | #include "SharedMemoryPublic.h" 8 | 9 | struct SharedMemoryUserData 10 | { 11 | std::string m_key; 12 | int m_type; 13 | 14 | int m_bodyUniqueId; 15 | int m_linkIndex; 16 | int m_visualShapeIndex; 17 | 18 | btAlignedObjectArray m_bytes; 19 | 20 | SharedMemoryUserData() 21 | : m_type(-1), m_bodyUniqueId(-1), m_linkIndex(-1), m_visualShapeIndex(-1) 22 | { 23 | } 24 | 25 | SharedMemoryUserData(const char* key, int bodyUniqueId, int linkIndex, int visualShapeIndex) 26 | : m_key(key), m_type(-1), m_bodyUniqueId(bodyUniqueId), m_linkIndex(linkIndex), m_visualShapeIndex(visualShapeIndex) 27 | { 28 | } 29 | 30 | void replaceValue(const char* bytes, int len, int type) 31 | { 32 | m_type = type; 33 | m_bytes.resize(len); 34 | for (int i = 0; i < len; i++) 35 | { 36 | m_bytes[i] = bytes[i]; 37 | } 38 | } 39 | 40 | virtual ~SharedMemoryUserData() 41 | { 42 | } 43 | 44 | void clear() 45 | { 46 | m_bytes.clear(); 47 | m_type = -1; 48 | } 49 | }; 50 | 51 | struct SharedMemoryUserDataHashKey 52 | { 53 | unsigned int m_hash; 54 | 55 | btHashString m_key; 56 | btHashInt m_bodyUniqueId; 57 | btHashInt m_linkIndex; 58 | btHashInt m_visualShapeIndex; 59 | 60 | SIMD_FORCE_INLINE unsigned int getHash() const 61 | { 62 | return m_hash; 63 | } 64 | 65 | SharedMemoryUserDataHashKey() : m_hash(0) {} 66 | 67 | SharedMemoryUserDataHashKey(const struct SharedMemoryUserData* userData) 68 | : m_key(userData->m_key.c_str()), 69 | m_bodyUniqueId(userData->m_bodyUniqueId), 70 | m_linkIndex(userData->m_linkIndex), 71 | m_visualShapeIndex(userData->m_visualShapeIndex) 72 | { 73 | calculateHash(); 74 | } 75 | 76 | SharedMemoryUserDataHashKey(const char* key, int bodyUniqueId, int linkIndex, int visualShapeIndex) 77 | : m_key(key), m_bodyUniqueId(bodyUniqueId), m_linkIndex(linkIndex), m_visualShapeIndex(visualShapeIndex) 78 | { 79 | calculateHash(); 80 | } 81 | 82 | void calculateHash() 83 | { 84 | m_hash = m_key.getHash() ^ m_bodyUniqueId.getHash() ^ m_linkIndex.getHash() ^ m_visualShapeIndex.getHash(); 85 | } 86 | 87 | bool equals(const SharedMemoryUserDataHashKey& other) const 88 | { 89 | return m_bodyUniqueId.equals(other.m_bodyUniqueId) && 90 | m_linkIndex.equals(other.m_linkIndex) && 91 | m_visualShapeIndex.equals(other.m_visualShapeIndex) && 92 | m_key.equals(other.m_key); 93 | } 94 | }; 95 | 96 | #endif //SHARED_MEMORY_USER_DATA_H 97 | -------------------------------------------------------------------------------- /src/SharedMemory/Win32SharedMemory.cpp: -------------------------------------------------------------------------------- 1 | #ifdef _WIN32 2 | #include "Win32SharedMemory.h" 3 | #include "Bullet3Common/b3Logging.h" 4 | #include "Bullet3Common/b3Scalar.h" 5 | #include "Bullet3Common/b3AlignedObjectArray.h" 6 | 7 | #include 8 | #include 9 | //see also https://msdn.microsoft.com/en-us/library/windows/desktop/aa366551%28v=vs.85%29.aspx 10 | 11 | struct Win32SharedMemorySegment 12 | { 13 | int m_key; 14 | HANDLE m_hMapFile; 15 | void* m_buf; 16 | TCHAR m_szName[1024]; 17 | 18 | Win32SharedMemorySegment() 19 | : m_hMapFile(0), 20 | m_buf(0), 21 | m_key(-1) 22 | { 23 | m_szName[0] = 0; 24 | } 25 | }; 26 | 27 | struct Win32SharedMemoryInteralData 28 | { 29 | b3AlignedObjectArray m_segments; 30 | 31 | Win32SharedMemoryInteralData() 32 | { 33 | } 34 | }; 35 | 36 | Win32SharedMemory::Win32SharedMemory() 37 | { 38 | m_internalData = new Win32SharedMemoryInteralData; 39 | } 40 | Win32SharedMemory::~Win32SharedMemory() 41 | { 42 | delete m_internalData; 43 | } 44 | 45 | void* Win32SharedMemory::allocateSharedMemory(int key, int size, bool allowCreation) 46 | { 47 | { 48 | Win32SharedMemorySegment* seg = 0; 49 | int i = 0; 50 | 51 | for (i = 0; i < m_internalData->m_segments.size(); i++) 52 | { 53 | if (m_internalData->m_segments[i].m_key == key) 54 | { 55 | seg = &m_internalData->m_segments[i]; 56 | break; 57 | } 58 | } 59 | if (seg) 60 | { 61 | b3Error("already created shared memory segment using same key"); 62 | return seg->m_buf; 63 | } 64 | } 65 | 66 | Win32SharedMemorySegment seg; 67 | seg.m_key = key; 68 | #ifdef UNICODE 69 | swprintf_s(seg.m_szName, TEXT("MyFileMappingObject%d"), key); 70 | #else 71 | 72 | sprintf(seg.m_szName, "MyFileMappingObject%d", key); 73 | #endif 74 | 75 | seg.m_hMapFile = OpenFileMapping( 76 | FILE_MAP_ALL_ACCESS, // read/write access 77 | FALSE, // do not inherit the name 78 | seg.m_szName); // name of mapping object 79 | 80 | if (seg.m_hMapFile == NULL) 81 | { 82 | if (allowCreation) 83 | { 84 | seg.m_hMapFile = CreateFileMapping( 85 | INVALID_HANDLE_VALUE, // use paging file 86 | NULL, // default security 87 | PAGE_READWRITE, // read/write access 88 | 0, // maximum object size (high-order DWORD) 89 | size, // maximum object size (low-order DWORD) 90 | seg.m_szName); // name of mapping object 91 | } 92 | else 93 | { 94 | //b3Warning("Could not create file mapping object (%d).\n", GetLastError()); 95 | return 0; 96 | } 97 | } 98 | 99 | seg.m_buf = MapViewOfFile(seg.m_hMapFile, // handle to map object 100 | FILE_MAP_ALL_ACCESS, // read/write permission 101 | 0, 102 | 0, 103 | size); 104 | 105 | if (seg.m_buf == NULL) 106 | { 107 | b3Warning("Could not map view of file (%d).\n", GetLastError()); 108 | CloseHandle(seg.m_hMapFile); 109 | return 0; 110 | } 111 | 112 | m_internalData->m_segments.push_back(seg); 113 | return seg.m_buf; 114 | } 115 | void Win32SharedMemory::releaseSharedMemory(int key, int size) 116 | { 117 | Win32SharedMemorySegment* seg = 0; 118 | int i = 0; 119 | 120 | for (i = 0; i < m_internalData->m_segments.size(); i++) 121 | { 122 | if (m_internalData->m_segments[i].m_key == key) 123 | { 124 | seg = &m_internalData->m_segments[i]; 125 | break; 126 | } 127 | } 128 | 129 | if (seg == 0) 130 | { 131 | b3Error("Couldn't find shared memory segment"); 132 | return; 133 | } 134 | 135 | if (seg->m_buf) 136 | { 137 | UnmapViewOfFile(seg->m_buf); 138 | seg->m_buf = 0; 139 | } 140 | 141 | if (seg->m_hMapFile) 142 | { 143 | CloseHandle(seg->m_hMapFile); 144 | seg->m_hMapFile = 0; 145 | } 146 | 147 | m_internalData->m_segments.removeAtIndex(i); 148 | } 149 | 150 | Win32SharedMemoryServer::Win32SharedMemoryServer() 151 | { 152 | } 153 | Win32SharedMemoryServer::~Win32SharedMemoryServer() 154 | { 155 | } 156 | 157 | Win32SharedMemoryClient::Win32SharedMemoryClient() 158 | { 159 | } 160 | Win32SharedMemoryClient::~Win32SharedMemoryClient() 161 | { 162 | } 163 | 164 | #endif //_WIN32 165 | -------------------------------------------------------------------------------- /src/SharedMemory/Win32SharedMemory.h: -------------------------------------------------------------------------------- 1 | #ifndef WIN32_SHARED_MEMORY_H 2 | #define WIN32_SHARED_MEMORY_H 3 | 4 | #include "SharedMemoryInterface.h" 5 | 6 | class Win32SharedMemory : public SharedMemoryInterface 7 | { 8 | struct Win32SharedMemoryInteralData* m_internalData; 9 | 10 | public: 11 | Win32SharedMemory(); 12 | virtual ~Win32SharedMemory(); 13 | 14 | virtual void* allocateSharedMemory(int key, int size, bool allowCreation); 15 | virtual void releaseSharedMemory(int key, int size); 16 | }; 17 | 18 | class Win32SharedMemoryServer : public Win32SharedMemory 19 | { 20 | public: 21 | Win32SharedMemoryServer(); 22 | virtual ~Win32SharedMemoryServer(); 23 | }; 24 | 25 | class Win32SharedMemoryClient : public Win32SharedMemory 26 | { 27 | public: 28 | Win32SharedMemoryClient(); 29 | virtual ~Win32SharedMemoryClient(); 30 | }; 31 | 32 | #endif //WIN32_SHARED_MEMORY_H 33 | -------------------------------------------------------------------------------- /src/SharedMemory/b3RobotSimulatorClientAPI_InternalData.h: -------------------------------------------------------------------------------- 1 | #ifndef B3_ROBOT_SIMULATOR_CLIENT_API_INTERNAL_DATA_H 2 | #define B3_ROBOT_SIMULATOR_CLIENT_API_INTERNAL_DATA_H 3 | 4 | #include "../SharedMemory/PhysicsClientC_API.h" 5 | 6 | struct b3RobotSimulatorClientAPI_InternalData 7 | { 8 | b3PhysicsClientHandle m_physicsClientHandle; 9 | struct GUIHelperInterface* m_guiHelper; 10 | 11 | b3RobotSimulatorClientAPI_InternalData() 12 | : m_physicsClientHandle(0), 13 | m_guiHelper(0) 14 | { 15 | } 16 | }; 17 | 18 | #endif //B3_ROBOT_SIMULATOR_CLIENT_API_INTERNAL_DATA_H -------------------------------------------------------------------------------- /src/SharedMemory/urdfStringSplit.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | //#include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "urdfStringSplit.h" 10 | 11 | void urdfStringSplit(btAlignedObjectArray &pieces, const std::string &vector_str, const btAlignedObjectArray &separators) 12 | { 13 | assert(separators.size() == 1); 14 | if (separators.size() == 1) 15 | { 16 | char **strArray = urdfStrSplit(vector_str.c_str(), separators[0].c_str()); 17 | int numSubStr = urdfStrArrayLen(strArray); 18 | for (int i = 0; i < numSubStr; i++) 19 | pieces.push_back(std::string(strArray[i])); 20 | urdfStrArrayFree(strArray); 21 | } 22 | } 23 | void urdfIsAnyOf(const char *seps, btAlignedObjectArray &strArray) 24 | { 25 | int numSeps = strlen(seps); 26 | for (int i = 0; i < numSeps; i++) 27 | { 28 | char sep2[2] = {0, 0}; 29 | 30 | sep2[0] = seps[i]; 31 | strArray.push_back(sep2); 32 | } 33 | } 34 | 35 | /* Append an item to a dynamically allocated array of strings. On failure, 36 | return NULL, in which case the original array is intact. The item 37 | string is dynamically copied. If the array is NULL, allocate a new 38 | array. Otherwise, extend the array. Make sure the array is always 39 | NULL-terminated. Input string might not be '\0'-terminated. */ 40 | char **urdfStrArrayAppend(char **array, size_t nitems, const char *item, 41 | size_t itemlen) 42 | { 43 | /* Make a dynamic copy of the item. */ 44 | char *copy; 45 | if (item == NULL) 46 | copy = NULL; 47 | else 48 | { 49 | copy = (char *)malloc(itemlen + 1); 50 | if (copy == NULL) 51 | return NULL; 52 | memcpy(copy, item, itemlen); 53 | copy[itemlen] = '\0'; 54 | } 55 | 56 | /* Extend array with one element. Except extend it by two elements, 57 | in case it did not yet exist. This might mean it is a teeny bit 58 | too big, but we don't care. */ 59 | array = (char **)realloc(array, (nitems + 2) * sizeof(array[0])); 60 | if (array == NULL) 61 | { 62 | free(copy); 63 | return NULL; 64 | } 65 | 66 | /* Add copy of item to array, and return it. */ 67 | array[nitems] = copy; 68 | array[nitems + 1] = NULL; 69 | return array; 70 | } 71 | 72 | /* Free a dynamic array of dynamic strings. */ 73 | void urdfStrArrayFree(char **array) 74 | { 75 | if (array == NULL) 76 | return; 77 | for (size_t i = 0; array[i] != NULL; ++i) 78 | free(array[i]); 79 | free(array); 80 | } 81 | 82 | /* Split a string into substrings. Return dynamic array of dynamically 83 | allocated substrings, or NULL if there was an error. Caller is 84 | expected to free the memory, for example with str_array_free. */ 85 | char **urdfStrSplit(const char *input, const char *sep) 86 | { 87 | size_t nitems = 0; 88 | char **array = NULL; 89 | const char *start = input; 90 | const char *next = strstr(start, sep); 91 | size_t seplen = strlen(sep); 92 | const char *item; 93 | size_t itemlen; 94 | 95 | for (;;) 96 | { 97 | next = strstr(start, sep); 98 | if (next == NULL) 99 | { 100 | /* Add the remaining string (or empty string, if input ends with 101 | separator. */ 102 | char **newstr = urdfStrArrayAppend(array, nitems, start, strlen(start)); 103 | if (newstr == NULL) 104 | { 105 | urdfStrArrayFree(array); 106 | return NULL; 107 | } 108 | array = newstr; 109 | ++nitems; 110 | break; 111 | } 112 | else if (next == input) 113 | { 114 | /* Input starts with separator. */ 115 | item = ""; 116 | itemlen = 0; 117 | } 118 | else 119 | { 120 | item = start; 121 | itemlen = next - item; 122 | } 123 | char **newstr = urdfStrArrayAppend(array, nitems, item, itemlen); 124 | if (newstr == NULL) 125 | { 126 | urdfStrArrayFree(array); 127 | return NULL; 128 | } 129 | array = newstr; 130 | ++nitems; 131 | start = next + seplen; 132 | } 133 | 134 | if (nitems == 0) 135 | { 136 | /* Input does not contain separator at all. */ 137 | assert(array == NULL); 138 | array = urdfStrArrayAppend(array, nitems, input, strlen(input)); 139 | } 140 | 141 | return array; 142 | } 143 | 144 | /* Return length of a NULL-delimited array of strings. */ 145 | size_t urdfStrArrayLen(char **array) 146 | { 147 | size_t len; 148 | 149 | for (len = 0; array[len] != NULL; ++len) 150 | continue; 151 | return len; 152 | } 153 | 154 | #ifdef UNIT_TEST_STRING_SPLIT 155 | 156 | #define MAX_OUTPUT 20 157 | 158 | int main(void) 159 | { 160 | struct 161 | { 162 | const char *input; 163 | const char *sep; 164 | char *output[MAX_OUTPUT]; 165 | } tab[] = { 166 | /* Input is empty string. Output should be a list with an empty 167 | string. */ 168 | { 169 | "", 170 | "and", 171 | { 172 | "", 173 | NULL, 174 | }, 175 | }, 176 | /* Input is exactly the separator. Output should be two empty 177 | strings. */ 178 | { 179 | "and", 180 | "and", 181 | { 182 | "", 183 | "", 184 | NULL, 185 | }, 186 | }, 187 | /* Input is non-empty, but does not have separator. Output should 188 | be the same string. */ 189 | { 190 | "foo", 191 | "and", 192 | { 193 | "foo", 194 | NULL, 195 | }, 196 | }, 197 | /* Input is non-empty, and does have separator. */ 198 | { 199 | "foo bar 1 and foo bar 2", 200 | " and ", 201 | { 202 | "foo bar 1", 203 | "foo bar 2", 204 | NULL, 205 | }, 206 | }, 207 | }; 208 | const int tab_len = sizeof(tab) / sizeof(tab[0]); 209 | bool errors; 210 | 211 | errors = false; 212 | 213 | for (int i = 0; i < tab_len; ++i) 214 | { 215 | printf("test %d\n", i); 216 | 217 | char **output = str_split(tab[i].input, tab[i].sep); 218 | if (output == NULL) 219 | { 220 | fprintf(stderr, "output is NULL\n"); 221 | errors = true; 222 | break; 223 | } 224 | size_t num_output = str_array_len(output); 225 | printf("num_output %lu\n", (unsigned long)num_output); 226 | 227 | size_t num_correct = str_array_len(tab[i].output); 228 | if (num_output != num_correct) 229 | { 230 | fprintf(stderr, "wrong number of outputs (%lu, not %lu)\n", 231 | (unsigned long)num_output, (unsigned long)num_correct); 232 | errors = true; 233 | } 234 | else 235 | { 236 | for (size_t j = 0; j < num_output; ++j) 237 | { 238 | if (strcmp(tab[i].output[j], output[j]) != 0) 239 | { 240 | fprintf(stderr, "output[%lu] is '%s' not '%s'\n", 241 | (unsigned long)j, output[j], tab[i].output[j]); 242 | errors = true; 243 | break; 244 | } 245 | } 246 | } 247 | 248 | str_array_free(output); 249 | printf("\n"); 250 | } 251 | 252 | if (errors) 253 | return EXIT_FAILURE; 254 | return 0; 255 | } 256 | #endif //UNIT_TEST_STRING_SPLIT 257 | -------------------------------------------------------------------------------- /src/SharedMemory/urdfStringSplit.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef STRING_SPLIT_H 3 | #define STRING_SPLIT_H 4 | 5 | #ifdef __cplusplus 6 | 7 | #include 8 | #include 9 | #include "LinearMath/btAlignedObjectArray.h" 10 | 11 | void urdfStringSplit(btAlignedObjectArray& pieces, const std::string& vector_str, const btAlignedObjectArray& separators); 12 | 13 | void urdfIsAnyOf(const char* seps, btAlignedObjectArray& strArray); 14 | #endif 15 | 16 | #ifdef __cplusplus 17 | extern "C" 18 | { 19 | #endif 20 | 21 | ///The string split C code is by Lars Wirzenius 22 | ///See http://stackoverflow.com/questions/2531605/how-to-split-a-string-with-a-delimiter-larger-than-one-single-char 23 | 24 | /* Split a string into substrings. Return dynamic array of dynamically 25 | allocated substrings, or NULL if there was an error. Caller is 26 | expected to free the memory, for example with str_array_free. */ 27 | char** urdfStrSplit(const char* input, const char* sep); 28 | 29 | /* Free a dynamic array of dynamic strings. */ 30 | void urdfStrArrayFree(char** array); 31 | 32 | /* Return length of a NULL-delimited array of strings. */ 33 | size_t urdfStrArrayLen(char** array); 34 | 35 | #ifdef __cplusplus 36 | } 37 | #endif 38 | 39 | #endif //STRING_SPLIT_H 40 | -------------------------------------------------------------------------------- /src/Utils/ChromeTraceUtil.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef B3_CHROME_TRACE_UTIL_H 3 | #define B3_CHROME_TRACE_UTIL_H 4 | 5 | void b3ChromeUtilsStartTimings(); 6 | void b3ChromeUtilsStopTimingsAndWriteJsonFile(const char* fileNamePrefix); 7 | void b3ChromeUtilsEnableProfiling(); 8 | 9 | #endif //B3_CHROME_TRACE_UTIL_H -------------------------------------------------------------------------------- /src/Utils/RobotLoggingUtil.cpp: -------------------------------------------------------------------------------- 1 | #include "RobotLoggingUtil.h" 2 | #include 3 | #include "LinearMath/btAlignedObjectArray.h" 4 | 5 | #include "SharedMemory/urdfStringSplit.h" 6 | 7 | static bool readLine(FILE* file, btAlignedObjectArray& line) 8 | { 9 | int c = 0; 10 | for (c = fgetc(file); (c != EOF && c != '\n'); c = fgetc(file)) 11 | { 12 | line.push_back(c); 13 | } 14 | line.push_back(0); 15 | return (c == EOF); 16 | } 17 | 18 | int readMinitaurLogFile(const char* fileName, btAlignedObjectArray& structNames, std::string& structTypes, btAlignedObjectArray& logRecords, bool verbose) 19 | { 20 | int retVal = 0; 21 | 22 | FILE* f = fopen(fileName, "rb"); 23 | if (f) 24 | { 25 | if (verbose) 26 | { 27 | printf("Opened file %s\n", fileName); 28 | } 29 | btAlignedObjectArray line0Buf; 30 | bool eof = readLine(f, line0Buf); 31 | btAlignedObjectArray line1Buf; 32 | eof |= readLine(f, line1Buf); 33 | std::string line0 = &line0Buf[0]; 34 | structTypes = &line1Buf[0]; 35 | 36 | btAlignedObjectArray separators; 37 | separators.push_back(","); 38 | 39 | urdfStringSplit(structNames, line0, separators); 40 | if (verbose) 41 | { 42 | printf("Num Fields = %d\n", structNames.size()); 43 | } 44 | btAssert(structTypes.size() == structNames.size()); 45 | if (structTypes.size() != structNames.size()) 46 | { 47 | retVal = eCorruptHeader; 48 | } 49 | int numStructsRead = 0; 50 | 51 | if (structTypes.size() == structNames.size()) 52 | { 53 | while (!eof) 54 | { 55 | unsigned char blaat[1024]; 56 | size_t s = fread(blaat, 2, 1, f); 57 | if (s != 1) 58 | { 59 | eof = true; 60 | retVal = eInvalidAABBAlignCheck; 61 | break; 62 | } 63 | if ((blaat[0] != 0xaa) || (blaat[1] != 0xbb)) 64 | { 65 | if (verbose) 66 | { 67 | printf("Expected 0xaa0xbb, terminating\n"); 68 | } 69 | } 70 | 71 | if (verbose) 72 | { 73 | printf("Reading structure %d\n", numStructsRead); 74 | } 75 | MinitaurLogRecord record; 76 | 77 | for (int i = 0; i < structNames.size(); i++) 78 | { 79 | switch (structTypes[i]) 80 | { 81 | case 'I': 82 | { 83 | size_t s = fread(blaat, sizeof(int), 1, f); 84 | if (s != 1) 85 | { 86 | eof = true; 87 | retVal = eCorruptValue; 88 | break; 89 | } 90 | int v = (int)*(unsigned int*)blaat; 91 | if (s == 1) 92 | { 93 | if (verbose) 94 | { 95 | printf("%s = %d\n", structNames[i].c_str(), v); 96 | } 97 | record.m_values.push_back(v); 98 | } 99 | break; 100 | } 101 | case 'i': 102 | { 103 | size_t s = fread(blaat, sizeof(int), 1, f); 104 | if (s != 1) 105 | { 106 | eof = true; 107 | retVal = eCorruptValue; 108 | break; 109 | } 110 | int v = *(int*)blaat; 111 | if (s == 1) 112 | { 113 | if (verbose) 114 | { 115 | printf("%s = %d\n", structNames[i].c_str(), v); 116 | } 117 | record.m_values.push_back(v); 118 | } 119 | break; 120 | } 121 | case 'f': 122 | { 123 | float v; 124 | size_t s = fread(&v, sizeof(float), 1, f); 125 | if (s != 1) 126 | { 127 | eof = true; 128 | break; 129 | } 130 | 131 | if (s == 1) 132 | { 133 | if (verbose) 134 | { 135 | printf("%s = %f\n", structNames[i].c_str(), v); 136 | } 137 | record.m_values.push_back(v); 138 | } 139 | break; 140 | } 141 | case 'B': 142 | { 143 | char v; 144 | size_t s = fread(&v, sizeof(char), 1, f); 145 | if (s != 1) 146 | { 147 | eof = true; 148 | break; 149 | } 150 | if (s == 1) 151 | { 152 | if (verbose) 153 | { 154 | printf("%s = %d\n", structNames[i].c_str(), v); 155 | } 156 | record.m_values.push_back(v); 157 | } 158 | break; 159 | } 160 | default: 161 | { 162 | if (verbose) 163 | { 164 | printf("Unknown type\n"); 165 | } 166 | retVal = eUnknownType; 167 | btAssert(0); 168 | } 169 | } 170 | } 171 | logRecords.push_back(record); 172 | numStructsRead++; 173 | } 174 | if (verbose) 175 | { 176 | printf("numStructsRead = %d\n", numStructsRead); 177 | } 178 | if (retVal == 0) 179 | { 180 | retVal = numStructsRead; 181 | } 182 | } 183 | 184 | //read header and 185 | } 186 | else 187 | { 188 | if (verbose) 189 | { 190 | printf("Could not open file %s", fileName); 191 | } 192 | retVal = eMinitaurFileNotFound; 193 | } 194 | return retVal; 195 | } 196 | 197 | FILE* createMinitaurLogFile(const char* fileName, btAlignedObjectArray& structNames, std::string& structTypes) 198 | { 199 | FILE* f = fopen(fileName, "wb"); 200 | if (f) 201 | { 202 | for (int i = 0; i < structNames.size(); i++) 203 | { 204 | int len = strlen(structNames[i].c_str()); 205 | fwrite(structNames[i].c_str(), len, 1, f); 206 | if (i < structNames.size() - 1) 207 | { 208 | fwrite(",", 1, 1, f); 209 | } 210 | } 211 | int sz = sizeof("\n"); 212 | fwrite("\n", sz - 1, 1, f); 213 | fwrite(structTypes.c_str(), strlen(structTypes.c_str()), 1, f); 214 | fwrite("\n", sz - 1, 1, f); 215 | } 216 | 217 | return f; 218 | } 219 | 220 | void appendMinitaurLogData(FILE* f, std::string& structTypes, const MinitaurLogRecord& logData) 221 | { 222 | if (f) 223 | { 224 | unsigned char buf[2] = {0xaa, 0xbb}; 225 | fwrite(buf, 2, 1, f); 226 | if (structTypes.length() == logData.m_values.size()) 227 | { 228 | for (int i = 0; i < logData.m_values.size(); i++) 229 | { 230 | switch (structTypes[i]) 231 | { 232 | case 'i': 233 | case 'I': 234 | { 235 | fwrite(&logData.m_values[i].m_intVal, sizeof(int), 1, f); 236 | break; 237 | } 238 | case 'f': 239 | { 240 | fwrite(&logData.m_values[i].m_floatVal, sizeof(float), 1, f); 241 | break; 242 | } 243 | case 'B': 244 | { 245 | fwrite(&logData.m_values[i].m_charVal, sizeof(char), 1, f); 246 | break; 247 | } 248 | default: 249 | { 250 | } 251 | } 252 | } 253 | } 254 | } 255 | } 256 | 257 | void closeMinitaurLogFile(FILE* f) 258 | { 259 | if (f) 260 | { 261 | fclose(f); 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /src/Utils/RobotLoggingUtil.h: -------------------------------------------------------------------------------- 1 | #ifndef ROBOT_LOGGING_UTIL_H 2 | #define ROBOT_LOGGING_UTIL_H 3 | 4 | #include "LinearMath/btAlignedObjectArray.h" 5 | #include 6 | 7 | struct MinitaurLogValue 8 | { 9 | MinitaurLogValue() 10 | : m_intVal(0xcdcdcdcd) 11 | { 12 | } 13 | MinitaurLogValue(int iv) 14 | : m_intVal(iv) 15 | { 16 | } 17 | MinitaurLogValue(float fv) 18 | : m_floatVal(fv) 19 | { 20 | } 21 | MinitaurLogValue(char fv) 22 | : m_charVal(fv) 23 | { 24 | } 25 | 26 | union { 27 | char m_charVal; 28 | int m_intVal; 29 | float m_floatVal; 30 | }; 31 | }; 32 | 33 | struct MinitaurLogRecord 34 | { 35 | btAlignedObjectArray m_values; 36 | }; 37 | 38 | enum MINITAUR_LOG_ERROR 39 | { 40 | eMinitaurFileNotFound = -1, 41 | eCorruptHeader = -2, 42 | eUnknownType = -3, 43 | eCorruptValue = -4, 44 | eInvalidAABBAlignCheck = -5, 45 | }; 46 | 47 | int readMinitaurLogFile(const char* fileName, btAlignedObjectArray& structNames, std::string& structTypes, btAlignedObjectArray& logRecords, bool verbose); 48 | 49 | FILE* createMinitaurLogFile(const char* fileName, btAlignedObjectArray& structNames, std::string& structTypes); 50 | void appendMinitaurLogData(FILE* f, std::string& structTypes, const MinitaurLogRecord& logData); 51 | void closeMinitaurLogFile(FILE* f); 52 | 53 | #endif //ROBOT_LOGGING_UTIL_H 54 | -------------------------------------------------------------------------------- /src/Utils/b3BulletDefaultFileIO.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef B3_BULLET_DEFAULT_FILE_IO_H 3 | #define B3_BULLET_DEFAULT_FILE_IO_H 4 | 5 | #include "../CommonInterfaces/CommonFileIOInterface.h" 6 | #include "b3ResourcePath.h" 7 | 8 | #include 9 | #define B3_FILEIO_MAX_FILES 1024 10 | 11 | struct b3BulletDefaultFileIO : public CommonFileIOInterface 12 | { 13 | static bool FileIOPluginFindFile(void* userPtr, const char* orgFileName, char* relativeFileName, int maxRelativeFileNameMaxLen) 14 | { 15 | b3BulletDefaultFileIO* fileIo = (b3BulletDefaultFileIO*) userPtr; 16 | return fileIo->findFile(orgFileName, relativeFileName, maxRelativeFileNameMaxLen); 17 | } 18 | 19 | char m_prefix[1024]; 20 | FILE* m_fileHandles[B3_FILEIO_MAX_FILES]; 21 | int m_numFileHandles; 22 | 23 | b3BulletDefaultFileIO(int fileIOType=0, const char* pathPrefix=0) 24 | :CommonFileIOInterface(fileIOType, m_prefix), 25 | m_numFileHandles(0) 26 | { 27 | m_prefix[0] = 0; 28 | if (pathPrefix) 29 | { 30 | sprintf(m_prefix,"%s", pathPrefix); 31 | } 32 | for (int i=0;i=0) 54 | { 55 | FILE*f = ::fopen(fileName, mode); 56 | if (f) 57 | { 58 | m_fileHandles[slot]=f; 59 | } else 60 | { 61 | slot=-1; 62 | } 63 | } 64 | return slot; 65 | } 66 | virtual int fileRead(int fileHandle, char* destBuffer, int numBytes) 67 | { 68 | if (fileHandle>=0 && fileHandle < B3_FILEIO_MAX_FILES) 69 | { 70 | FILE* f = m_fileHandles[fileHandle]; 71 | if (f) 72 | { 73 | int readBytes = ::fread(destBuffer, 1, numBytes, f); 74 | return readBytes; 75 | } 76 | } 77 | return -1; 78 | 79 | } 80 | virtual int fileWrite(int fileHandle,const char* sourceBuffer, int numBytes) 81 | { 82 | if (fileHandle>=0 && fileHandle < B3_FILEIO_MAX_FILES) 83 | { 84 | FILE* f = m_fileHandles[fileHandle]; 85 | if (f) 86 | { 87 | return ::fwrite(sourceBuffer, 1, numBytes,m_fileHandles[fileHandle]); 88 | } 89 | } 90 | return -1; 91 | } 92 | virtual void fileClose(int fileHandle) 93 | { 94 | if (fileHandle>=0 && fileHandle < B3_FILEIO_MAX_FILES) 95 | { 96 | FILE* f = m_fileHandles[fileHandle]; 97 | if (f) 98 | { 99 | ::fclose(f); 100 | m_fileHandles[fileHandle]=0; 101 | } 102 | } 103 | } 104 | 105 | virtual bool findResourcePath(const char* fileName, char* relativeFileName, int relativeFileNameSizeInBytes) 106 | { 107 | return b3ResourcePath::findResourcePath(fileName, relativeFileName, relativeFileNameSizeInBytes, b3BulletDefaultFileIO::FileIOPluginFindFile, this)>0; 108 | } 109 | 110 | 111 | virtual bool findFile(const char* orgFileName, char* relativeFileName, int maxRelativeFileNameMaxLen) 112 | { 113 | FILE* f = 0; 114 | f = fopen(orgFileName, "rb"); 115 | if (f) 116 | { 117 | //printf("original file found: [%s]\n", orgFileName); 118 | sprintf(relativeFileName, "%s", orgFileName); 119 | fclose(f); 120 | return true; 121 | } 122 | 123 | //printf("Trying various directories, relative to current working directory\n"); 124 | const char* prefix[] = {m_prefix, "./", "./data/", "../data/", "../../data/", "../../../data/", "../../../../data/"}; 125 | int numPrefixes = sizeof(prefix) / sizeof(const char*); 126 | 127 | f = 0; 128 | bool fileFound = false; 129 | 130 | for (int i = 0; !f && i < numPrefixes; i++) 131 | { 132 | #ifdef _MSC_VER 133 | sprintf_s(relativeFileName, maxRelativeFileNameMaxLen, "%s%s", prefix[i], orgFileName); 134 | #else 135 | sprintf(relativeFileName, "%s%s", prefix[i], orgFileName); 136 | #endif 137 | f = fopen(relativeFileName, "rb"); 138 | if (f) 139 | { 140 | fileFound = true; 141 | break; 142 | } 143 | } 144 | if (f) 145 | { 146 | fclose(f); 147 | } 148 | 149 | return fileFound; 150 | } 151 | virtual char* readLine(int fileHandle, char* destBuffer, int numBytes) 152 | { 153 | if (fileHandle>=0 && fileHandle < B3_FILEIO_MAX_FILES) 154 | { 155 | FILE* f = m_fileHandles[fileHandle]; 156 | if (f) 157 | { 158 | char* txt = ::fgets(destBuffer, numBytes, m_fileHandles[fileHandle]); 159 | for (int i=0;i=0 && fileHandle < B3_FILEIO_MAX_FILES) 176 | { 177 | FILE* f = m_fileHandles[fileHandle]; 178 | if (f) 179 | { 180 | 181 | if (fseek(f, 0, SEEK_END) || (size = ftell(f)) == EOF || fseek(f, 0, SEEK_SET)) 182 | { 183 | printf("Error: Cannot access file to determine size\n"); 184 | } 185 | } 186 | } 187 | return size; 188 | } 189 | 190 | virtual void enableFileCaching(bool enable) 191 | { 192 | (void) enable; 193 | } 194 | }; 195 | 196 | #endif //B3_BULLET_DEFAULT_FILE_IO_H 197 | -------------------------------------------------------------------------------- /src/Utils/b3Clock.cpp: -------------------------------------------------------------------------------- 1 | #include "b3Clock.h" 2 | 3 | template 4 | const T& b3ClockMin(const T& a, const T& b) 5 | { 6 | return a < b ? a : b; 7 | } 8 | 9 | #ifdef __CELLOS_LV2__ 10 | #include 11 | #include 12 | #include 13 | #endif 14 | 15 | #if defined(SUNOS) || defined(__SUNOS__) 16 | #include 17 | #endif 18 | 19 | #if defined(WIN32) || defined(_WIN32) 20 | 21 | #define B3_USE_WINDOWS_TIMERS 22 | #define WIN32_LEAN_AND_MEAN 23 | #define NOWINRES 24 | #define NOMCX 25 | #define NOIME 26 | 27 | #ifdef _XBOX 28 | #include 29 | #else //_XBOX 30 | #include 31 | #endif //_XBOX 32 | 33 | #include 34 | 35 | #else //_WIN32 36 | #include 37 | #include 38 | #endif //_WIN32 39 | 40 | struct b3ClockData 41 | { 42 | #ifdef B3_USE_WINDOWS_TIMERS 43 | LARGE_INTEGER mClockFrequency; 44 | LARGE_INTEGER mStartTime; 45 | #else 46 | #ifdef __CELLOS_LV2__ 47 | uint64_t mStartTime; 48 | #else 49 | struct timeval mStartTime; 50 | #endif 51 | #endif //__CELLOS_LV2__ 52 | }; 53 | 54 | ///The b3Clock is a portable basic clock that measures accurate time in seconds, use for profiling. 55 | b3Clock::b3Clock() 56 | { 57 | m_data = new b3ClockData; 58 | #ifdef B3_USE_WINDOWS_TIMERS 59 | QueryPerformanceFrequency(&m_data->mClockFrequency); 60 | #endif 61 | reset(); 62 | } 63 | 64 | b3Clock::~b3Clock() 65 | { 66 | delete m_data; 67 | } 68 | 69 | b3Clock::b3Clock(const b3Clock& other) 70 | { 71 | m_data = new b3ClockData; 72 | *m_data = *other.m_data; 73 | } 74 | 75 | b3Clock& b3Clock::operator=(const b3Clock& other) 76 | { 77 | *m_data = *other.m_data; 78 | return *this; 79 | } 80 | 81 | /// Resets the initial reference time. 82 | void b3Clock::reset(bool zeroReference) 83 | { 84 | if (zeroReference) 85 | { 86 | #ifdef B3_USE_WINDOWS_TIMERS 87 | m_data->mStartTime.QuadPart = 0; 88 | #else 89 | #ifdef __CELLOS_LV2__ 90 | m_data->mStartTime = 0; 91 | #else 92 | m_data->mStartTime = (struct timeval){0}; 93 | #endif 94 | #endif 95 | } 96 | else 97 | { 98 | #ifdef B3_USE_WINDOWS_TIMERS 99 | QueryPerformanceCounter(&m_data->mStartTime); 100 | #else 101 | #ifdef __CELLOS_LV2__ 102 | 103 | typedef uint64_t ClockSize; 104 | ClockSize newTime; 105 | //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); 106 | SYS_TIMEBASE_GET(newTime); 107 | m_data->mStartTime = newTime; 108 | #else 109 | gettimeofday(&m_data->mStartTime, 0); 110 | #endif 111 | #endif 112 | } 113 | } 114 | 115 | /// Returns the time in ms since the last call to reset or since 116 | /// the b3Clock was created. 117 | unsigned long int b3Clock::getTimeMilliseconds() 118 | { 119 | #ifdef B3_USE_WINDOWS_TIMERS 120 | LARGE_INTEGER currentTime; 121 | QueryPerformanceCounter(¤tTime); 122 | LONGLONG elapsedTime = currentTime.QuadPart - 123 | m_data->mStartTime.QuadPart; 124 | // Compute the number of millisecond ticks elapsed. 125 | unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / 126 | m_data->mClockFrequency.QuadPart); 127 | 128 | return msecTicks; 129 | #else 130 | 131 | #ifdef __CELLOS_LV2__ 132 | uint64_t freq = sys_time_get_timebase_frequency(); 133 | double dFreq = ((double)freq) / 1000.0; 134 | typedef uint64_t ClockSize; 135 | ClockSize newTime; 136 | SYS_TIMEBASE_GET(newTime); 137 | //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); 138 | 139 | return (unsigned long int)((double(newTime - m_data->mStartTime)) / dFreq); 140 | #else 141 | 142 | struct timeval currentTime; 143 | gettimeofday(¤tTime, 0); 144 | return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 + 145 | (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000; 146 | #endif //__CELLOS_LV2__ 147 | #endif 148 | } 149 | 150 | /// Returns the time in us since the last call to reset or since 151 | /// the Clock was created. 152 | unsigned long long int b3Clock::getTimeMicroseconds() 153 | { 154 | #ifdef B3_USE_WINDOWS_TIMERS 155 | //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx 156 | LARGE_INTEGER currentTime, elapsedTime; 157 | 158 | QueryPerformanceCounter(¤tTime); 159 | elapsedTime.QuadPart = currentTime.QuadPart - 160 | m_data->mStartTime.QuadPart; 161 | elapsedTime.QuadPart *= 1000000; 162 | elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart; 163 | 164 | return (unsigned long long)elapsedTime.QuadPart; 165 | #else 166 | 167 | #ifdef __CELLOS_LV2__ 168 | uint64_t freq = sys_time_get_timebase_frequency(); 169 | double dFreq = ((double)freq) / 1000000.0; 170 | typedef uint64_t ClockSize; 171 | ClockSize newTime; 172 | //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); 173 | SYS_TIMEBASE_GET(newTime); 174 | 175 | return (unsigned long int)((double(newTime - m_data->mStartTime)) / dFreq); 176 | #else 177 | 178 | struct timeval currentTime; 179 | gettimeofday(¤tTime, 0); 180 | return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 + 181 | (currentTime.tv_usec - m_data->mStartTime.tv_usec); 182 | #endif //__CELLOS_LV2__ 183 | #endif 184 | } 185 | 186 | double b3Clock::getTimeInSeconds() 187 | { 188 | return double(getTimeMicroseconds() / 1.e6); 189 | } 190 | 191 | void b3Clock::usleep(int microSeconds) 192 | { 193 | #ifdef _WIN32 194 | if (microSeconds == 0) 195 | { 196 | Sleep(0); 197 | } 198 | else 199 | { 200 | int millis = microSeconds / 1000; 201 | if (millis < 1) 202 | millis = 1; 203 | Sleep(millis); 204 | } 205 | #else 206 | if (microSeconds > 0) 207 | { 208 | ::usleep(microSeconds); 209 | //struct timeval tv; 210 | //tv.tv_sec = microSeconds/1000000L; 211 | //tv.tv_usec = microSeconds%1000000L; 212 | //return select(0, 0, 0, 0, &tv); 213 | } 214 | #endif 215 | } 216 | -------------------------------------------------------------------------------- /src/Utils/b3Clock.h: -------------------------------------------------------------------------------- 1 | #ifndef B3_CLOCK_H 2 | #define B3_CLOCK_H 3 | 4 | ///The b3Clock is a portable basic clock that measures accurate time in seconds, use for profiling. 5 | class b3Clock 6 | { 7 | public: 8 | b3Clock(); 9 | 10 | b3Clock(const b3Clock& other); 11 | b3Clock& operator=(const b3Clock& other); 12 | 13 | ~b3Clock(); 14 | 15 | /// Resets the initial reference time. If zeroReference is true, will set reference to absolute 0. 16 | void reset(bool zeroReference = false); 17 | 18 | /// Returns the time in ms since the last call to reset or since 19 | /// the b3Clock was created. 20 | unsigned long int getTimeMilliseconds(); 21 | 22 | /// Returns the time in us since the last call to reset or since 23 | /// the Clock was created. 24 | unsigned long long int getTimeMicroseconds(); 25 | 26 | /// Returns the time in seconds since the last call to reset or since 27 | /// the Clock was created. 28 | double getTimeInSeconds(); 29 | 30 | ///Sleep for 'microSeconds', to yield to other threads and not waste 100% CPU cycles. 31 | ///Note that some operating systems may sleep a longer time. 32 | static void usleep(int microSeconds); 33 | 34 | private: 35 | struct b3ClockData* m_data; 36 | }; 37 | 38 | #endif //B3_CLOCK_H 39 | -------------------------------------------------------------------------------- /src/Utils/b3Quickprof.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org 3 | 4 | This software is provided 'as-is', without any express or implied warranty. 5 | In no event will the authors be held liable for any damages arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it freely, 8 | subject to the following restrictions: 9 | 10 | 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. 11 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 | 3. This notice may not be removed or altered from any source distribution. 13 | */ 14 | 15 | /*************************************************************************************************** 16 | ** 17 | ** Real-Time Hierarchical Profiling for Game Programming Gems 3 18 | ** 19 | ** by Greg Hjelstrom & Byon Garrabrant 20 | ** 21 | ***************************************************************************************************/ 22 | 23 | // Credits: The Clock class was inspired by the Timer classes in 24 | // Ogre (www.ogre3d.org). 25 | 26 | #ifndef B3_QUICK_PROF_H 27 | #define B3_QUICK_PROF_H 28 | 29 | //To disable built-in profiling, please comment out next line 30 | //#define B3_NO_PROFILE 1 31 | #ifndef B3_NO_PROFILE 32 | #include //@todo remove this, backwards compatibility 33 | #include "Bullet3Common/b3Scalar.h" 34 | #include "Bullet3Common/b3AlignedAllocator.h" 35 | #include 36 | 37 | #include "b3Clock.h" 38 | 39 | ///A node in the Profile Hierarchy Tree 40 | class b3ProfileNode 41 | { 42 | public: 43 | b3ProfileNode(const char* name, b3ProfileNode* parent); 44 | ~b3ProfileNode(void); 45 | 46 | b3ProfileNode* Get_Sub_Node(const char* name); 47 | 48 | b3ProfileNode* Get_Parent(void) { return Parent; } 49 | b3ProfileNode* Get_Sibling(void) { return Sibling; } 50 | b3ProfileNode* Get_Child(void) { return Child; } 51 | 52 | void CleanupMemory(); 53 | void Reset(void); 54 | void Call(void); 55 | bool Return(void); 56 | 57 | const char* Get_Name(void) { return Name; } 58 | int Get_Total_Calls(void) { return TotalCalls; } 59 | float Get_Total_Time(void) { return TotalTime; } 60 | void* GetUserPointer() const { return m_userPtr; } 61 | void SetUserPointer(void* ptr) { m_userPtr = ptr; } 62 | 63 | protected: 64 | const char* Name; 65 | int TotalCalls; 66 | float TotalTime; 67 | unsigned long int StartTime; 68 | int RecursionCounter; 69 | 70 | b3ProfileNode* Parent; 71 | b3ProfileNode* Child; 72 | b3ProfileNode* Sibling; 73 | void* m_userPtr; 74 | }; 75 | 76 | ///An iterator to navigate through the tree 77 | class b3ProfileIterator 78 | { 79 | public: 80 | // Access all the children of the current parent 81 | void First(void); 82 | void Next(void); 83 | bool Is_Done(void); 84 | bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); } 85 | 86 | void Enter_Child(int index); // Make the given child the new parent 87 | void Enter_Largest_Child(void); // Make the largest child the new parent 88 | void Enter_Parent(void); // Make the current parent's parent the new parent 89 | 90 | // Access the current child 91 | const char* Get_Current_Name(void) { return CurrentChild->Get_Name(); } 92 | int Get_Current_Total_Calls(void) { return CurrentChild->Get_Total_Calls(); } 93 | float Get_Current_Total_Time(void) { return CurrentChild->Get_Total_Time(); } 94 | 95 | void* Get_Current_UserPointer(void) { return CurrentChild->GetUserPointer(); } 96 | void Set_Current_UserPointer(void* ptr) { CurrentChild->SetUserPointer(ptr); } 97 | // Access the current parent 98 | const char* Get_Current_Parent_Name(void) { return CurrentParent->Get_Name(); } 99 | int Get_Current_Parent_Total_Calls(void) { return CurrentParent->Get_Total_Calls(); } 100 | float Get_Current_Parent_Total_Time(void) { return CurrentParent->Get_Total_Time(); } 101 | 102 | protected: 103 | b3ProfileNode* CurrentParent; 104 | b3ProfileNode* CurrentChild; 105 | 106 | b3ProfileIterator(b3ProfileNode* start); 107 | friend class b3ProfileManager; 108 | }; 109 | 110 | ///The Manager for the Profile system 111 | class b3ProfileManager 112 | { 113 | public: 114 | static void Start_Profile(const char* name); 115 | static void Stop_Profile(void); 116 | 117 | static void CleanupMemory(void) 118 | { 119 | Root.CleanupMemory(); 120 | } 121 | 122 | static void Reset(void); 123 | static void Increment_Frame_Counter(void); 124 | static int Get_Frame_Count_Since_Reset(void) { return FrameCounter; } 125 | static float Get_Time_Since_Reset(void); 126 | 127 | static b3ProfileIterator* Get_Iterator(void) 128 | { 129 | return new b3ProfileIterator(&Root); 130 | } 131 | static void Release_Iterator(b3ProfileIterator* iterator) { delete (iterator); } 132 | 133 | static void dumpRecursive(b3ProfileIterator* profileIterator, int spacing); 134 | static void dumpAll(); 135 | 136 | static void dumpRecursive(FILE* f, b3ProfileIterator* profileIterator, int spacing); 137 | static void dumpAll(FILE* f); 138 | 139 | private: 140 | static b3ProfileNode Root; 141 | static b3ProfileNode* CurrentNode; 142 | static int FrameCounter; 143 | static unsigned long int ResetTime; 144 | }; 145 | 146 | #else 147 | 148 | #endif //#ifndef B3_NO_PROFILE 149 | 150 | #endif //B3_QUICK_PROF_H 151 | -------------------------------------------------------------------------------- /src/Utils/b3ResourcePath.cpp: -------------------------------------------------------------------------------- 1 | #include "b3ResourcePath.h" 2 | #include "Bullet3Common/b3Logging.h" 3 | #ifdef __APPLE__ 4 | #include /* _NSGetExecutablePath */ 5 | #else 6 | #ifdef _WIN32 7 | #include 8 | #else 9 | //not Mac, not Windows, let's cross the fingers it is Linux :-) 10 | #include 11 | #endif 12 | #endif 13 | 14 | #include "Bullet3Common/b3FileUtils.h" 15 | #define B3_MAX_EXE_PATH_LEN 4096 16 | 17 | int b3ResourcePath::getExePath(char* path, int maxPathLenInBytes) 18 | { 19 | int numBytes = 0; 20 | 21 | #if __APPLE__ 22 | uint32_t bufsize = uint32_t(maxPathLenInBytes); 23 | 24 | if (_NSGetExecutablePath(path, &bufsize) != 0) 25 | { 26 | b3Warning("Cannot find executable path\n"); 27 | return false; 28 | } 29 | else 30 | { 31 | numBytes = strlen(path); 32 | } 33 | #else 34 | #ifdef _WIN32 35 | //https://msdn.microsoft.com/en-us/library/windows/desktop/ms683197(v=vs.85).aspx 36 | 37 | HMODULE hModule = GetModuleHandle(NULL); 38 | numBytes = GetModuleFileNameA(hModule, path, maxPathLenInBytes); 39 | 40 | #else 41 | ///http://stackoverflow.com/questions/933850/how-to-find-the-location-of-the-executable-in-c 42 | numBytes = (int)readlink("/proc/self/exe", path, maxPathLenInBytes - 1); 43 | if (numBytes > 0) 44 | { 45 | path[numBytes] = 0; 46 | } 47 | else 48 | { 49 | b3Warning("Cannot find executable path\n"); 50 | } 51 | #endif //_WIN32 52 | #endif //__APPLE__ 53 | 54 | return numBytes; 55 | } 56 | 57 | struct TempResourcePath 58 | { 59 | char* m_path; 60 | TempResourcePath(int len) 61 | { 62 | m_path = (char*)malloc(len); 63 | memset(m_path, 0, len); 64 | } 65 | virtual ~TempResourcePath() 66 | { 67 | free(m_path); 68 | } 69 | }; 70 | 71 | static char sAdditionalSearchPath[B3_MAX_EXE_PATH_LEN] = {0}; 72 | 73 | void b3ResourcePath::setAdditionalSearchPath(const char* path) 74 | { 75 | if (path) 76 | { 77 | int len = strlen(path); 78 | if (len < (B3_MAX_EXE_PATH_LEN - 1)) 79 | { 80 | strcpy(sAdditionalSearchPath, path); 81 | sAdditionalSearchPath[len] = 0; 82 | } 83 | } 84 | else 85 | { 86 | sAdditionalSearchPath[0] = 0; 87 | } 88 | } 89 | 90 | bool b3MyFindFile(void* userPointer, const char* orgFileName, char* relativeFileName, int maxRelativeFileNameMaxLen) 91 | { 92 | return b3FileUtils::findFile(orgFileName, relativeFileName, maxRelativeFileNameMaxLen); 93 | } 94 | 95 | int b3ResourcePath::findResourcePath(const char* resourceName, char* resourcePathOut, int resourcePathMaxNumBytes, PFN_FIND_FILE findFile, void* userPointer) 96 | { 97 | if (findFile==0) 98 | { 99 | findFile=b3MyFindFile; 100 | } 101 | //first find in a resource/ location, then in various folders within 'data' using b3FileUtils 102 | char exePath[B3_MAX_EXE_PATH_LEN]; 103 | 104 | bool res = findFile(userPointer, resourceName, resourcePathOut, resourcePathMaxNumBytes); 105 | if (res) 106 | { 107 | return strlen(resourcePathOut); 108 | } 109 | 110 | if (sAdditionalSearchPath[0]) 111 | { 112 | TempResourcePath tmpPath(resourcePathMaxNumBytes + 1024); 113 | char* resourcePathIn = tmpPath.m_path; 114 | sprintf(resourcePathIn, "%s/%s", sAdditionalSearchPath, resourceName); 115 | //printf("try resource at %s\n", resourcePath); 116 | if (findFile(userPointer, resourcePathIn, resourcePathOut, resourcePathMaxNumBytes)) 117 | { 118 | return strlen(resourcePathOut); 119 | } 120 | } 121 | 122 | int l = b3ResourcePath::getExePath(exePath, B3_MAX_EXE_PATH_LEN); 123 | if (l) 124 | { 125 | char pathToExe[B3_MAX_EXE_PATH_LEN]; 126 | 127 | int exeNamePos = b3FileUtils::extractPath(exePath, pathToExe, B3_MAX_EXE_PATH_LEN); 128 | if (exeNamePos) 129 | { 130 | TempResourcePath tmpPath(resourcePathMaxNumBytes + 1024); 131 | char* resourcePathIn = tmpPath.m_path; 132 | sprintf(resourcePathIn, "%s../data/%s", pathToExe, resourceName); 133 | //printf("try resource at %s\n", resourcePath); 134 | if (findFile(userPointer, resourcePathIn, resourcePathOut, resourcePathMaxNumBytes)) 135 | { 136 | return strlen(resourcePathOut); 137 | } 138 | 139 | sprintf(resourcePathIn, "%s../resources/%s/%s", pathToExe, &exePath[exeNamePos], resourceName); 140 | //printf("try resource at %s\n", resourcePath); 141 | if (findFile(userPointer, resourcePathIn, resourcePathOut, resourcePathMaxNumBytes)) 142 | { 143 | return strlen(resourcePathOut); 144 | } 145 | sprintf(resourcePathIn, "%s.runfiles/google3/third_party/bullet/data/%s", exePath, resourceName); 146 | //printf("try resource at %s\n", resourcePath); 147 | if (findFile(userPointer, resourcePathIn, resourcePathOut, resourcePathMaxNumBytes)) 148 | { 149 | return strlen(resourcePathOut); 150 | } 151 | } 152 | } 153 | 154 | return 0; 155 | } 156 | -------------------------------------------------------------------------------- /src/Utils/b3ResourcePath.h: -------------------------------------------------------------------------------- 1 | #ifndef _B3_RESOURCE_PATH_H 2 | #define _B3_RESOURCE_PATH_H 3 | 4 | #include 5 | 6 | typedef bool (* PFN_FIND_FILE)(void* userPointer, const char* orgFileName, char* relativeFileName, int maxRelativeFileNameMaxLen); 7 | 8 | class b3ResourcePath 9 | { 10 | public: 11 | static int getExePath(char* path, int maxPathLenInBytes); 12 | static int findResourcePath(const char* resourceName, char* resourcePathOut, int resourcePathMaxNumBytes, PFN_FIND_FILE findFile, void* userPointer=0); 13 | static void setAdditionalSearchPath(const char* path); 14 | }; 15 | #endif 16 | --------------------------------------------------------------------------------