├── lib ├── CMakeLists.txt └── VHACD_Lib │ ├── src │ ├── vhacdVolume.cpp │ ├── btAlignedAllocator.cpp │ ├── vhacdManifoldMesh.cpp │ └── vhacdMesh.cpp │ ├── CMakeLists.txt │ ├── inc │ ├── btMinMax.h │ ├── btConvexHullComputer.h │ ├── vhacdTimer.h │ ├── vhacdCircularList.inl │ ├── btAlignedAllocator.h │ ├── vhacdCircularList.h │ ├── vhacdMutex.h │ ├── vhacdVector.h │ ├── vhacdICHull.h │ ├── vhacdManifoldMesh.h │ ├── vhacdSArray.h │ ├── vhacdMesh.h │ ├── vhacdVector.inl │ ├── btAlignedObjectArray.h │ ├── btScalar.h │ ├── vhacdVHACD.h │ └── btVector3.h │ ├── cl │ └── vhacdKernels.cl │ └── public │ └── VHACD.h ├── CMakeLists.txt ├── README.md └── src ├── CMakeLists.txt └── HACD.cpp /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_SUBDIRECTORY( VHACD_Lib ) 2 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/src/vhacdVolume.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhoub/vhacd4h/HEAD/lib/VHACD_Lib/src/vhacdVolume.cpp -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED( VERSION 3.2 ) 2 | 3 | PROJECT( HACD4H ) 4 | 5 | # We use the libraries from Houdini as much as possible. 6 | FIND_PATH( HOUDINI_DIR REQUIRED ) 7 | IF ( MSVC ) 8 | SET( HOUDINI_INCLUDE_DIR "${HOUDINI_DIR}/toolkit/include" ) 9 | SET( HOUDINI_LIBRARY_DIR "${HOUDINI_DIR}/custom/houdini/dsolib" ) 10 | ELSEIF( APPLE ) 11 | SET( HOUDINI_INCLUDE_DIR "${HOUDINI_DIR}/Resources/toolkit/include" ) 12 | SET( HOUDINI_LIBRARY_DIR "${HOUDINI_DIR}/Libraries" ) 13 | ELSE() 14 | SET( HOUDINI_INCLUDE_DIR "${HOUDINI_DIR}/toolkit/include" ) 15 | SET( HOUDINI_LIBRARY_DIR "${HOUDINI_DIR}/dsolib" ) 16 | ENDIF() 17 | 18 | ADD_SUBDIRECTORY( lib ) 19 | ADD_SUBDIRECTORY( src ) 20 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set( HACD_INCLUDR_DIR ${CMAKE_CURRENT_SOURCE_DIR}/public ) 2 | 3 | option(USE_OPENCL "Using OpenCL" OFF) 4 | option(USE_OPENMP "Using OpenMP" OFF) 5 | 6 | if(USE_OPENCL) 7 | FIND_PACKAGE(OpenCL REQUIRED) 8 | SET(OpenCL_INCLUDE_DIR ${HOUDINI_INCLUDE_DIR}) 9 | SET(OpenCL_LIBRARY ${HOUDINI_LIBRARY_DIR}/OpenCL) 10 | if (OpenCL_FOUND) 11 | include_directories("${OpenCL_INCLUDE_DIRS}") 12 | add_definitions( -DOPENCL_FOUND=1 ) 13 | add_definitions( -DOPENCL_CL_FILES="${PROJECT_CL_FILES}" ) 14 | endif() 15 | endif() 16 | if(USE_OPENMP) 17 | if(NOT APPLE) 18 | include(FindOpenMP) 19 | if(OPENMP_FOUND) 20 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 21 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 22 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 23 | endif() 24 | endif() 25 | endif() 26 | 27 | set(LIB_TYPE "STATIC" CACHE STRING "STATIC, SHARED or MODULE?") 28 | message("[VHACD] \t LIB_TYPE " ${LIB_TYPE}) 29 | 30 | file(GLOB PROJECT_CL_FILES "cl/*") 31 | file(GLOB PROJECT_INC_FILES "inc/*") 32 | file(GLOB PROJECT_PUBLIC_FILES "public/*") 33 | file(GLOB PROJECT_SRC_FILES "src/*") 34 | 35 | include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/inc" ) 36 | add_library(VHACD_LIB ${LIB_TYPE} ${PROJECT_CL_FILES} ${PROJECT_INC_FILES} ${PROJECT_PUBLIC_FILES} ${PROJECT_SRC_FILES}) 37 | 38 | message("[VHACD] \t -> CMAKE_INSTALL_PREFIX " ${CMAKE_INSTALL_PREFIX}) 39 | install(TARGETS VHACD_LIB DESTINATION bin) 40 | install(FILES ${PROJECT_PUBLIC_FILES} DESTINATION include) 41 | install(FILES ${PROJECT_INC_FILES} DESTINATION include) 42 | 43 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/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 | 16 | 17 | #ifndef BT_GEN_MINMAX_H 18 | #define BT_GEN_MINMAX_H 19 | 20 | #include "btScalar.h" 21 | 22 | template 23 | SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) 24 | { 25 | return a < b ? a : b ; 26 | } 27 | 28 | template 29 | SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) 30 | { 31 | return a > b ? a : b; 32 | } 33 | 34 | template 35 | SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub) 36 | { 37 | return a < lb ? lb : (ub < a ? ub : a); 38 | } 39 | 40 | template 41 | SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) 42 | { 43 | if (b < a) 44 | { 45 | a = b; 46 | } 47 | } 48 | 49 | template 50 | SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) 51 | { 52 | if (a < b) 53 | { 54 | a = b; 55 | } 56 | } 57 | 58 | template 59 | SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub) 60 | { 61 | if (a < lb) 62 | { 63 | a = lb; 64 | } 65 | else if (ub < a) 66 | { 67 | a = ub; 68 | } 69 | } 70 | 71 | #endif //BT_GEN_MINMAX_H 72 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/cl/vhacdKernels.cl: -------------------------------------------------------------------------------- 1 | __kernel void ComputePartialVolumes(__global short4 * voxels, 2 | const int numVoxels, 3 | const float4 plane, 4 | const float4 minBB, 5 | const float4 scale, 6 | __local uint4 * localPartialVolumes, 7 | __global uint4 * partialVolumes) 8 | { 9 | int localId = get_local_id(0); 10 | int groupSize = get_local_size(0); 11 | int i0 = get_global_id(0) << 2; 12 | float4 voxel; 13 | uint4 v; 14 | 15 | voxel = convert_float4(voxels[i0]); 16 | v.s0 = (dot(plane, mad(scale, voxel, minBB)) >= 0.0f) * (i0 < numVoxels); 17 | voxel = convert_float4(voxels[i0 + 1]); 18 | v.s1 = (dot(plane, mad(scale, voxel, minBB)) >= 0.0f) * (i0 + 1 < numVoxels); 19 | voxel = convert_float4(voxels[i0 + 2]); 20 | v.s2 = (dot(plane, mad(scale, voxel, minBB)) >= 0.0f) * (i0 + 2 < numVoxels); 21 | voxel = convert_float4(voxels[i0 + 3]); 22 | v.s3 = (dot(plane, mad(scale, voxel, minBB)) >= 0.0f) * (i0 + 3 < numVoxels); 23 | 24 | localPartialVolumes[localId] = v; 25 | barrier(CLK_LOCAL_MEM_FENCE); 26 | 27 | for (int i = groupSize >> 1; i > 0; i >>= 1) 28 | { 29 | if (localId < i) 30 | { 31 | localPartialVolumes[localId] += localPartialVolumes[localId + i]; 32 | } 33 | barrier(CLK_LOCAL_MEM_FENCE); 34 | } 35 | if (localId == 0) 36 | { 37 | partialVolumes[get_group_id(0)] = localPartialVolumes[0]; 38 | } 39 | } 40 | __kernel void ComputePartialSums(__global uint4 * data, 41 | const int dataSize, 42 | __local uint4 * partialSums) 43 | { 44 | 45 | int globalId = get_global_id(0); 46 | int localId = get_local_id(0); 47 | int groupSize = get_local_size(0); 48 | int i; 49 | if (globalId < dataSize) 50 | { 51 | partialSums[localId] = data[globalId]; 52 | } 53 | else 54 | { 55 | partialSums[localId] = (0, 0, 0, 0); 56 | } 57 | barrier(CLK_LOCAL_MEM_FENCE); 58 | for (i = groupSize >> 1; i > 0; i >>= 1) 59 | { 60 | if (localId < i) 61 | { 62 | partialSums[localId] += partialSums[localId + i]; 63 | } 64 | barrier(CLK_LOCAL_MEM_FENCE); 65 | } 66 | if (localId == 0) 67 | { 68 | data[get_group_id(0)] = partialSums[0]; 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/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 | 31 | class Edge 32 | { 33 | private: 34 | int next; 35 | int reverse; 36 | int targetVertex; 37 | 38 | friend class btConvexHullComputer; 39 | 40 | public: 41 | int getSourceVertex() const 42 | { 43 | return (this + reverse)->targetVertex; 44 | } 45 | 46 | int getTargetVertex() const 47 | { 48 | return targetVertex; 49 | } 50 | 51 | const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex 52 | { 53 | return this + next; 54 | } 55 | 56 | const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face 57 | { 58 | return (this + reverse)->getNextEdgeOfVertex(); 59 | } 60 | 61 | const Edge* getReverseEdge() const 62 | { 63 | return this + reverse; 64 | } 65 | }; 66 | 67 | 68 | // Vertices of the output hull 69 | btAlignedObjectArray vertices; 70 | 71 | // Edges of the output hull 72 | btAlignedObjectArray edges; 73 | 74 | // 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 75 | btAlignedObjectArray faces; 76 | 77 | /* 78 | Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes 79 | between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken 80 | by that amount (each face is moved by "shrink" length units towards the center along its normal). 81 | If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius" 82 | is the minimum distance of a face to the center of the convex hull. 83 | 84 | The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large 85 | that the resulting convex hull is empty. 86 | 87 | The output convex hull can be found in the member variables "vertices", "edges", "faces". 88 | */ 89 | btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp) 90 | { 91 | return compute(coords, false, stride, count, shrink, shrinkClamp); 92 | } 93 | 94 | // same as above, but double precision 95 | btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp) 96 | { 97 | return compute(coords, true, stride, count, shrink, shrinkClamp); 98 | } 99 | }; 100 | 101 | 102 | #endif //BT_CONVEX_HULL_COMPUTER_H 103 | 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vhacd4h 2 | V-HACD for Houdini 3 | 4 | Refer to the implementation of [Volumetric Hierarchical Approximate Convex Decomposition](https://code.google.com/p/v-hacd) 5 | 6 | # Copyrights 7 | 8 | ## V-HACD for Houdini 9 | Copyright (c) 2016 Bo Zhou (bo.schwarzstein at gmail dot com) 10 | All rights reserved. 11 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 12 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 14 | 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 17 | 18 | ## V-HACD 19 | 20 | Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) 21 | All rights reserved. 22 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 23 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 24 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 25 | 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | ## Bullet 30 | 31 | Bullet Continuous Collision Detection and Physics Library 32 | Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ 33 | This software is provided 'as-is', without any express or implied warranty. 34 | In no event will the authors be held liable for any damages arising from the use of this software. 35 | Permission is granted to anyone to use this software for any purpose, 36 | including commercial applications, and to alter it and redistribute it freely, 37 | subject to the following restrictions: 38 | 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. 39 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 40 | 3. This notice may not be removed or altered from any source distribution. 41 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | IF ( USE_OPENCL ) 2 | ADD_DEFINITIONS( -DUSE_OPENCL ) 3 | ENDIF() 4 | 5 | IF( MSVC ) 6 | ADD_DEFINITIONS( -DMAKING_DSO -DI386 -DWIN32 -DSWAP_BITFIELDS -D_WIN32_WINNT=0x0502 -DNOMINMAX -DSTRICT -DWIN32_LEAN_AND_MEAN -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS -DBOOST_ALL_NO_LIB -DSESI_LITTLE_ENDIAN $(ARCHDEFS) -DFBX_ENABLED=1 -DOPENCL_ENABLED=1 -DOPENVDB_ENABLED=1 -DOPENEXR_DLL ) 7 | 8 | SET( HOUDINI_LIBRARIES 9 | "${HOUDINI_LIBRARY_DIR}/boost_system-vc110-mt-1_55.lib" 10 | "${HOUDINI_LIBRARY_DIR}/tbb.lib" 11 | "${HOUDINI_LIBRARY_DIR}/libCH.a" 12 | "${HOUDINI_LIBRARY_DIR}/libCMD.a" 13 | "${HOUDINI_LIBRARY_DIR}/libGA.a" 14 | "${HOUDINI_LIBRARY_DIR}/libGEO.a" 15 | "${HOUDINI_LIBRARY_DIR}/libGT.a" 16 | "${HOUDINI_LIBRARY_DIR}/libGU.a" 17 | "${HOUDINI_LIBRARY_DIR}/libGUI.a" 18 | "${HOUDINI_LIBRARY_DIR}/libGSTY.a" 19 | "${HOUDINI_LIBRARY_DIR}/libUT.a" 20 | "${HOUDINI_LIBRARY_DIR}/libFS.a" 21 | "${HOUDINI_LIBRARY_DIR}/libSYS.a" 22 | "${HOUDINI_LIBRARY_DIR}/libOP.a" 23 | "${HOUDINI_LIBRARY_DIR}/libOBJ.a" 24 | "${HOUDINI_LIBRARY_DIR}/libSOP.a" 25 | "${HOUDINI_LIBRARY_DIR}/libSTY.a" 26 | "${HOUDINI_LIBRARY_DIR}/libPRM.a" 27 | "${HOUDINI_LIBRARY_DIR}/libROP.a" 28 | "${HOUDINI_LIBRARY_DIR}/libPY.a" 29 | "${HOUDINI_LIBRARY_DIR}/libPYP.a" 30 | "${HOUDINI_LIBRARY_DIR}/libVRAY.a" ) 31 | ELSEIF( APPLE ) 32 | ADD_DEFINITIONS( -DMAKING_DSO 33 | -DVERSION=\"15.0.416\" 34 | -D_GNU_SOURCE -DMBSD 35 | -DMBSD_COCOA 36 | -DMBSD_INTEL 37 | -arch x86_64 38 | -DAMD64 39 | -fPIC 40 | -DSIZEOF_VOID_P=8 41 | -DFBX_ENABLED=1 42 | -DOPENCL_ENABLED=1 43 | -DOPENVDB_ENABLED=1 44 | -DSESI_LITTLE_ENDIAN 45 | -DENABLE_THREADS 46 | -DUSE_PTHREADS 47 | -D_REENTRANT 48 | -D_FILE_OFFSET_BITS=64 49 | -DGCC4 -DGCC3 50 | -Wno-deprecated 51 | -std=c++11 52 | -Wall -W -Wno-parentheses -Wno-sign-compare -Wno-reorder -Wno-uninitialized -Wunused -Wno-unused-parameter ) 53 | 54 | SET( HOUDINI_LIBRARIES 55 | "${HOUDINI_LIBRARY_DIR}/libHoudiniGEO.dylib" 56 | "${HOUDINI_LIBRARY_DIR}/libHoudiniOP1.dylib" 57 | "${HOUDINI_LIBRARY_DIR}/libHoudiniOP2.dylib" 58 | "${HOUDINI_LIBRARY_DIR}/libHoudiniOP3.dylib" 59 | "${HOUDINI_LIBRARY_DIR}/libHoudiniOPZ.dylib" 60 | "${HOUDINI_LIBRARY_DIR}/libHoudiniPRM.dylib" 61 | "${HOUDINI_LIBRARY_DIR}/libHoudiniUT.dylib" 62 | "${HOUDINI_LIBRARY_DIR}/libHoudiniRAY.dylib" 63 | "${HOUDINI_LIBRARY_DIR}/libboost_system.dylib" 64 | "${HOUDINI_LIBRARY_DIR}/libtbb.dylib" ) 65 | ELSE() 66 | ADD_DEFINITIONS( -DMAKING_DSO -DVERSION=\"15.0.416\" -D_GNU_SOURCE -DLINUX -DAMD64 -m64 -fPIC -DSIZEOF_VOID_P=8 -DFBX_ENABLED=1 -DOPENCL_ENABLED=1 -DOPENVDB_ENABLED=1 -DSESI_LITTLE_ENDIAN -DENABLE_THREADS -DUSE_PTHREADS -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DGCC4 -DGCC3 -Wno-deprecated -std=c++0x -Wall -W -Wno-parentheses -Wno-sign-compare -Wno-reorder -Wno-uninitialized -Wunused -Wno-unused-parameter -fno-strict-aliasing -DBOOST_ALL_NO_LIB ) 67 | 68 | SET( HOUDINI_LIBRARIES 69 | "${HOUDINI_LIBRARY_DIR}/libHoudiniGEO.so" 70 | "${HOUDINI_LIBRARY_DIR}/libHoudiniOPZ.so" 71 | "${HOUDINI_LIBRARY_DIR}/libHoudiniPRM.so" 72 | "${HOUDINI_LIBRARY_DIR}/libHoudiniUT.so" 73 | "${HOUDINI_LIBRARY_DIR}/libHoudiniRAY.so" 74 | "" ) 75 | ENDIF() 76 | 77 | IF (USE_OPENCL) 78 | SET( HOUDINI_LIBRARIES ${HOUDINI_LIBRARIES} ${OpenCL_LIBRARY}) 79 | ENDIF() 80 | 81 | INCLUDE_DIRECTORIES( ${HOUDINI_INCLUDE_DIR} ${CMAKE_INSTALL_PREFIX}/include ) 82 | LINK_DIRECTORIES( ${HOUDINI_LIBRARY_DIR} ) 83 | 84 | ADD_LIBRARY( HACD SHARED HACD.cpp ) 85 | TARGET_LINK_LIBRARIES( HACD ${HOUDINI_LIBRARIES} VHACD_LIB ) 86 | 87 | IF(MSVC) 88 | INSTALL( TARGETS HACD RUNTIME DESTINATION bin ) 89 | ELSE() 90 | SET_TARGET_PROPERTIES( HACD PROPERTIES PREFIX "" ) 91 | INSTALL( TARGETS HACD LIBRARY DESTINATION bin ) 92 | ENDIF() 93 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/vhacdTimer.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) 2 | All rights reserved. 3 | 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | */ 15 | #pragma once 16 | #ifndef VHACD_TIMER_H 17 | #define VHACD_TIMER_H 18 | 19 | #ifdef _WIN32 20 | #ifndef WIN32_LEAN_AND_MEAN 21 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 22 | #endif 23 | #include 24 | #elif __MACH__ 25 | #include 26 | #include 27 | #else 28 | #include 29 | #include 30 | #endif 31 | 32 | namespace VHACD 33 | { 34 | #ifdef _WIN32 35 | class Timer 36 | { 37 | public: 38 | Timer(void) 39 | { 40 | m_start.QuadPart = 0; 41 | m_stop.QuadPart = 0; 42 | QueryPerformanceFrequency( &m_freq ) ; 43 | }; 44 | ~Timer(void){}; 45 | void Tic() 46 | { 47 | QueryPerformanceCounter(&m_start) ; 48 | } 49 | void Toc() 50 | { 51 | QueryPerformanceCounter(&m_stop); 52 | } 53 | double GetElapsedTime() // in ms 54 | { 55 | LARGE_INTEGER delta; 56 | delta.QuadPart = m_stop.QuadPart - m_start.QuadPart; 57 | return (1000.0 * delta.QuadPart) / (double)m_freq.QuadPart; 58 | } 59 | private: 60 | LARGE_INTEGER m_start; 61 | LARGE_INTEGER m_stop; 62 | LARGE_INTEGER m_freq; 63 | 64 | }; 65 | 66 | #elif __MACH__ 67 | class Timer 68 | { 69 | public: 70 | Timer(void) 71 | { 72 | memset(this, 0, sizeof(Timer)); 73 | host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, & m_cclock); 74 | }; 75 | ~Timer(void) 76 | { 77 | mach_port_deallocate(mach_task_self(), m_cclock); 78 | }; 79 | void Tic() 80 | { 81 | clock_get_time( m_cclock, &m_start); 82 | } 83 | void Toc() 84 | { 85 | clock_get_time( m_cclock, &m_stop); 86 | } 87 | double GetElapsedTime() // in ms 88 | { 89 | return 1000.0 * (m_stop.tv_sec - m_start.tv_sec + (1.0E-9) * (m_stop.tv_nsec - m_start.tv_nsec)); 90 | } 91 | private: 92 | clock_serv_t m_cclock; 93 | mach_timespec_t m_start; 94 | mach_timespec_t m_stop; 95 | }; 96 | #else 97 | class Timer 98 | { 99 | public: 100 | Timer(void) 101 | { 102 | memset(this, 0, sizeof(Timer)); 103 | }; 104 | ~Timer(void){}; 105 | void Tic() 106 | { 107 | clock_gettime(CLOCK_REALTIME, &m_start); 108 | } 109 | void Toc() 110 | { 111 | clock_gettime(CLOCK_REALTIME, &m_stop); 112 | } 113 | double GetElapsedTime() // in ms 114 | { 115 | return 1000.0 * (m_stop.tv_sec - m_start.tv_sec + (1.0E-9) * (m_stop.tv_nsec - m_start.tv_nsec)); 116 | } 117 | private: 118 | struct timespec m_start; 119 | struct timespec m_stop; 120 | }; 121 | #endif 122 | } 123 | #endif // VHACD_TIMER_H 124 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/vhacdCircularList.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef HACD_CIRCULAR_LIST_INL 3 | #define HACD_CIRCULAR_LIST_INL 4 | namespace VHACD 5 | { 6 | template < typename T > 7 | inline bool CircularList::Delete(CircularListElement * element) 8 | { 9 | if (!element) 10 | { 11 | return false; 12 | } 13 | if (m_size > 1) 14 | { 15 | CircularListElement * next = element->GetNext(); 16 | CircularListElement * prev = element->GetPrev(); 17 | delete element; 18 | m_size--; 19 | if (element == m_head) 20 | { 21 | m_head = next; 22 | } 23 | next->GetPrev() = prev; 24 | prev->GetNext() = next; 25 | return true; 26 | } 27 | else if (m_size == 1) 28 | { 29 | delete m_head; 30 | m_size--; 31 | m_head = 0; 32 | return true; 33 | } 34 | else 35 | { 36 | return false; 37 | } 38 | } 39 | 40 | template < typename T > 41 | inline bool CircularList::Delete() 42 | { 43 | if (m_size > 1) 44 | { 45 | CircularListElement * next = m_head->GetNext(); 46 | CircularListElement * prev = m_head->GetPrev(); 47 | delete m_head; 48 | m_size--; 49 | m_head = next; 50 | next->GetPrev() = prev; 51 | prev->GetNext() = next; 52 | return true; 53 | } 54 | else if (m_size == 1) 55 | { 56 | delete m_head; 57 | m_size--; 58 | m_head = 0; 59 | return true; 60 | } 61 | else 62 | { 63 | return false; 64 | } 65 | } 66 | template < typename T > 67 | inline CircularListElement * CircularList::Add(const T * data) 68 | { 69 | if (m_size == 0) 70 | { 71 | if (data) 72 | { 73 | m_head = new CircularListElement(*data); 74 | } 75 | else 76 | { 77 | m_head = new CircularListElement(); 78 | } 79 | m_head->GetNext() = m_head->GetPrev() = m_head; 80 | } 81 | else 82 | { 83 | CircularListElement * next = m_head->GetNext(); 84 | CircularListElement * element = m_head; 85 | if (data) 86 | { 87 | m_head = new CircularListElement(*data); 88 | } 89 | else 90 | { 91 | m_head = new CircularListElement(); 92 | } 93 | m_head->GetNext() = next; 94 | m_head->GetPrev() = element; 95 | element->GetNext() = m_head; 96 | next->GetPrev() = m_head; 97 | } 98 | m_size++; 99 | return m_head; 100 | } 101 | template < typename T > 102 | inline CircularListElement * CircularList::Add(const T & data) 103 | { 104 | const T * pData = &data; 105 | return Add(pData); 106 | } 107 | template < typename T > 108 | inline bool CircularList::Next() 109 | { 110 | if (m_size == 0) 111 | { 112 | return false; 113 | } 114 | m_head = m_head->GetNext(); 115 | return true; 116 | } 117 | template < typename T > 118 | inline bool CircularList::Prev() 119 | { 120 | if (m_size == 0) 121 | { 122 | return false; 123 | } 124 | m_head = m_head->GetPrev(); 125 | return true; 126 | } 127 | template < typename T > 128 | inline CircularList::CircularList(const CircularList& rhs) 129 | { 130 | if (rhs.m_size > 0) 131 | { 132 | CircularListElement * current = rhs.m_head; 133 | do 134 | { 135 | current = current->GetNext(); 136 | Add(current->GetData()); 137 | } 138 | while ( current != rhs.m_head ); 139 | } 140 | } 141 | template < typename T > 142 | inline const CircularList& CircularList::operator=(const CircularList& rhs) 143 | { 144 | if (&rhs != this) 145 | { 146 | Clear(); 147 | if (rhs.m_size > 0) 148 | { 149 | CircularListElement * current = rhs.m_head; 150 | do 151 | { 152 | current = current->GetNext(); 153 | Add(current->GetData()); 154 | } 155 | while ( current != rhs.m_head ); 156 | } 157 | } 158 | return (*this); 159 | } 160 | } 161 | #endif -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/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 | //#define BT_DEBUG_MEMORY_ALLOCATIONS 1 25 | #ifdef BT_DEBUG_MEMORY_ALLOCATIONS 26 | 27 | #define btAlignedAlloc(a,b) \ 28 | btAlignedAllocInternal(a,b,__LINE__,__FILE__) 29 | 30 | #define btAlignedFree(ptr) \ 31 | btAlignedFreeInternal(ptr,__LINE__,__FILE__) 32 | 33 | void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename); 34 | 35 | void btAlignedFreeInternal (void* ptr,int line,char* filename); 36 | 37 | #else 38 | void* btAlignedAllocInternal (size_t size, int alignment); 39 | void btAlignedFreeInternal (void* ptr); 40 | 41 | #define btAlignedAlloc(size,alignment) btAlignedAllocInternal(size,alignment) 42 | #define btAlignedFree(ptr) btAlignedFreeInternal(ptr) 43 | 44 | #endif 45 | typedef int size_type; 46 | 47 | typedef void *(btAlignedAllocFunc)(size_t size, int alignment); 48 | typedef void (btAlignedFreeFunc)(void *memblock); 49 | typedef void *(btAllocFunc)(size_t size); 50 | typedef void (btFreeFunc)(void *memblock); 51 | 52 | ///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom 53 | void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc); 54 | ///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. 55 | void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc); 56 | 57 | 58 | ///The btAlignedAllocator is a portable class for aligned memory allocations. 59 | ///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned. 60 | template < typename T , unsigned Alignment > 61 | class btAlignedAllocator { 62 | 63 | typedef btAlignedAllocator< T , Alignment > self_type; 64 | 65 | public: 66 | 67 | //just going down a list: 68 | btAlignedAllocator() {} 69 | /* 70 | btAlignedAllocator( const self_type & ) {} 71 | */ 72 | 73 | template < typename Other > 74 | btAlignedAllocator( const btAlignedAllocator< Other , Alignment > & ) {} 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 ( size_type n , const_pointer * hint = 0 ) { 85 | (void)hint; 86 | return reinterpret_cast< pointer >(btAlignedAlloc( sizeof(value_type) * n , Alignment )); 87 | } 88 | void construct ( pointer ptr , const value_type & value ) { new (ptr) value_type( value ); } 89 | void deallocate( pointer ptr ) { 90 | btAlignedFree( reinterpret_cast< void * >( ptr ) ); 91 | } 92 | void destroy ( pointer ptr ) { ptr->~value_type(); } 93 | 94 | 95 | template < typename O > struct rebind { 96 | typedef btAlignedAllocator< O , Alignment > other; 97 | }; 98 | template < typename O > 99 | self_type & operator=( const btAlignedAllocator< O , Alignment > & ) { return *this; } 100 | 101 | friend bool operator==( const self_type & , const self_type & ) { return true; } 102 | }; 103 | 104 | 105 | 106 | #endif //BT_ALIGNED_ALLOCATOR 107 | 108 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/vhacdCircularList.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) 2 | All rights reserved. 3 | 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | */ 15 | #pragma once 16 | #ifndef VHACD_CIRCULAR_LIST_H 17 | #define VHACD_CIRCULAR_LIST_H 18 | #include 19 | namespace VHACD 20 | { 21 | //! CircularListElement class. 22 | template < typename T > class CircularListElement 23 | { 24 | public: 25 | T & GetData() { return m_data; } 26 | const T & GetData() const { return m_data; } 27 | CircularListElement * & GetNext() { return m_next; } 28 | CircularListElement * & GetPrev() { return m_prev; } 29 | const CircularListElement * & GetNext() const { return m_next; } 30 | const CircularListElement * & GetPrev() const { return m_prev; } 31 | //! Constructor 32 | CircularListElement(const T & data) {m_data = data;} 33 | CircularListElement(void){} 34 | //! Destructor 35 | ~CircularListElement(void){} 36 | private: 37 | T m_data; 38 | CircularListElement * m_next; 39 | CircularListElement * m_prev; 40 | 41 | CircularListElement(const CircularListElement & rhs); 42 | }; 43 | //! CircularList class. 44 | template < typename T > class CircularList 45 | { 46 | public: 47 | CircularListElement * & GetHead() { return m_head;} 48 | const CircularListElement * GetHead() const { return m_head;} 49 | bool IsEmpty() const { return (m_size == 0);} 50 | size_t GetSize() const { return m_size; } 51 | const T & GetData() const { return m_head->GetData(); } 52 | T & GetData() { return m_head->GetData();} 53 | bool Delete() ; 54 | bool Delete(CircularListElement * element); 55 | CircularListElement * Add(const T * data = 0); 56 | CircularListElement * Add(const T & data); 57 | bool Next(); 58 | bool Prev(); 59 | void Clear() { while(Delete());}; 60 | const CircularList& operator=(const CircularList& rhs); 61 | //! Constructor 62 | CircularList() 63 | { 64 | m_head = 0; 65 | m_size = 0; 66 | } 67 | CircularList(const CircularList& rhs); 68 | //! Destructor 69 | ~CircularList(void) {Clear();}; 70 | private: 71 | CircularListElement * m_head; //!< a pointer to the head of the circular list 72 | size_t m_size; //!< number of element in the circular list 73 | }; 74 | } 75 | #include "vhacdCircularList.inl" 76 | #endif // VHACD_CIRCULAR_LIST_H -------------------------------------------------------------------------------- /lib/VHACD_Lib/src/btAlignedAllocator.cpp: -------------------------------------------------------------------------------- 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 | #include "btAlignedAllocator.h" 17 | 18 | int gNumAlignedAllocs = 0; 19 | int gNumAlignedFree = 0; 20 | int gTotalBytesAlignedAllocs = 0;//detect memory leaks 21 | 22 | static void *btAllocDefault(size_t size) 23 | { 24 | return malloc(size); 25 | } 26 | 27 | static void btFreeDefault(void *ptr) 28 | { 29 | free(ptr); 30 | } 31 | 32 | static btAllocFunc *sAllocFunc = btAllocDefault; 33 | static btFreeFunc *sFreeFunc = btFreeDefault; 34 | 35 | 36 | 37 | #if defined (BT_HAS_ALIGNED_ALLOCATOR) 38 | #include 39 | static void *btAlignedAllocDefault(size_t size, int alignment) 40 | { 41 | return _aligned_malloc(size, (size_t)alignment); 42 | } 43 | 44 | static void btAlignedFreeDefault(void *ptr) 45 | { 46 | _aligned_free(ptr); 47 | } 48 | #elif defined(__CELLOS_LV2__) 49 | #include 50 | 51 | static inline void *btAlignedAllocDefault(size_t size, int alignment) 52 | { 53 | return memalign(alignment, size); 54 | } 55 | 56 | static inline void btAlignedFreeDefault(void *ptr) 57 | { 58 | free(ptr); 59 | } 60 | #else 61 | static inline void *btAlignedAllocDefault(size_t size, int alignment) 62 | { 63 | void *ret; 64 | char *real; 65 | unsigned long offset; 66 | 67 | real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1)); 68 | if (real) { 69 | offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1); 70 | ret = (void *)((real + sizeof(void *)) + offset); 71 | *((void **)(ret)-1) = (void *)(real); 72 | } else { 73 | ret = (void *)(real); 74 | } 75 | return (ret); 76 | } 77 | 78 | static inline void btAlignedFreeDefault(void *ptr) 79 | { 80 | void* real; 81 | 82 | if (ptr) { 83 | real = *((void **)(ptr)-1); 84 | sFreeFunc(real); 85 | } 86 | } 87 | #endif 88 | 89 | 90 | static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault; 91 | static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault; 92 | 93 | void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc) 94 | { 95 | sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault; 96 | sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault; 97 | } 98 | 99 | void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc) 100 | { 101 | sAllocFunc = allocFunc ? allocFunc : btAllocDefault; 102 | sFreeFunc = freeFunc ? freeFunc : btFreeDefault; 103 | } 104 | 105 | #ifdef BT_DEBUG_MEMORY_ALLOCATIONS 106 | //this generic allocator provides the total allocated number of bytes 107 | #include 108 | 109 | void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename) 110 | { 111 | void *ret; 112 | char *real; 113 | unsigned long offset; 114 | 115 | gTotalBytesAlignedAllocs += size; 116 | gNumAlignedAllocs++; 117 | 118 | 119 | real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1)); 120 | if (real) { 121 | offset = (alignment - (unsigned long)(real + 2*sizeof(void *))) & 122 | (alignment-1); 123 | ret = (void *)((real + 2*sizeof(void *)) + offset); 124 | *((void **)(ret)-1) = (void *)(real); 125 | *((int*)(ret)-2) = size; 126 | 127 | } else { 128 | ret = (void *)(real);//?? 129 | } 130 | 131 | printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size); 132 | 133 | int* ptr = (int*)ret; 134 | *ptr = 12; 135 | return (ret); 136 | } 137 | 138 | void btAlignedFreeInternal (void* ptr,int line,char* filename) 139 | { 140 | 141 | void* real; 142 | gNumAlignedFree++; 143 | 144 | if (ptr) { 145 | real = *((void **)(ptr)-1); 146 | int size = *((int*)(ptr)-2); 147 | gTotalBytesAlignedAllocs -= size; 148 | 149 | printf("free #%d at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size); 150 | 151 | sFreeFunc(real); 152 | } else 153 | { 154 | printf("NULL ptr\n"); 155 | } 156 | } 157 | 158 | #else //BT_DEBUG_MEMORY_ALLOCATIONS 159 | 160 | void* btAlignedAllocInternal (size_t size, int alignment) 161 | { 162 | gNumAlignedAllocs++; 163 | void* ptr; 164 | ptr = sAlignedAllocFunc(size, alignment); 165 | // printf("btAlignedAllocInternal %d, %x\n",size,ptr); 166 | return ptr; 167 | } 168 | 169 | void btAlignedFreeInternal (void* ptr) 170 | { 171 | if (!ptr) 172 | { 173 | return; 174 | } 175 | 176 | gNumAlignedFree++; 177 | // printf("btAlignedFreeInternal %x\n",ptr); 178 | sAlignedFreeFunc(ptr); 179 | } 180 | 181 | #endif //BT_DEBUG_MEMORY_ALLOCATIONS 182 | 183 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/vhacdMutex.h: -------------------------------------------------------------------------------- 1 | /*! 2 | ** 3 | ** Copyright (c) 2009 by John W. Ratcliff mailto:jratcliffscarab@gmail.com 4 | ** 5 | ** Portions of this source has been released with the PhysXViewer application, as well as 6 | ** Rocket, CreateDynamics, ODF, and as a number of sample code snippets. 7 | ** 8 | ** If you find this code useful or you are feeling particularily generous I would 9 | ** ask that you please go to http://www.amillionpixels.us and make a donation 10 | ** to Troy DeMolay. 11 | ** 12 | ** DeMolay is a youth group for young men between the ages of 12 and 21. 13 | ** It teaches strong moral principles, as well as leadership skills and 14 | ** public speaking. The donations page uses the 'pay for pixels' paradigm 15 | ** where, in this case, a pixel is only a single penny. Donations can be 16 | ** made for as small as $4 or as high as a $100 block. Each person who donates 17 | ** will get a link to their own site as well as acknowledgement on the 18 | ** donations blog located here http://www.amillionpixels.blogspot.com/ 19 | ** 20 | ** If you wish to contact me you can use the following methods: 21 | ** 22 | ** Skype ID: jratcliff63367 23 | ** Yahoo: jratcliff63367 24 | ** AOL: jratcliff1961 25 | ** email: jratcliffscarab@gmail.com 26 | ** 27 | ** 28 | ** The MIT license: 29 | ** 30 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 31 | ** of this software and associated documentation files (the "Software"), to deal 32 | ** in the Software without restriction, including without limitation the rights 33 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | ** copies of the Software, and to permit persons to whom the Software is furnished 35 | ** to do so, subject to the following conditions: 36 | ** 37 | ** The above copyright notice and this permission notice shall be included in all 38 | ** copies or substantial portions of the Software. 39 | 40 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 44 | ** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 45 | ** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 46 | 47 | */ 48 | 49 | #pragma once 50 | #ifndef VHACD_MUTEX_H 51 | #define VHACD_MUTEX_H 52 | 53 | 54 | #if defined(WIN32) 55 | 56 | #define _WIN32_WINNT 0x400 57 | #include 58 | #pragma comment(lib,"winmm.lib") 59 | #endif 60 | 61 | #if defined(__linux__) 62 | //#include 63 | #include 64 | #include 65 | #include 66 | #define __stdcall 67 | #endif 68 | 69 | #if defined(__APPLE__) || defined(__linux__) 70 | #include 71 | #endif 72 | 73 | #if defined(__APPLE__) 74 | #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE 75 | #endif 76 | 77 | 78 | #define VHACD_DEBUG 79 | 80 | #define VHACD_NDEBUG 81 | #ifdef VHACD_NDEBUG 82 | #define VHACD_VERIFY( x ) (x) 83 | #else 84 | #define VHACD_VERIFY( x ) assert((x)) 85 | #endif 86 | 87 | namespace VHACD 88 | { 89 | class Mutex 90 | { 91 | public: 92 | Mutex(void) 93 | { 94 | #if defined(WIN32) || defined(_XBOX) 95 | InitializeCriticalSection(&m_mutex); 96 | #elif defined(__APPLE__) || defined(__linux__) 97 | pthread_mutexattr_t mutexAttr; // Mutex Attribute 98 | VHACD_VERIFY(pthread_mutexattr_init(&mutexAttr) == 0); 99 | VHACD_VERIFY(pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_RECURSIVE_NP) == 0); 100 | VHACD_VERIFY(pthread_mutex_init(&m_mutex, &mutexAttr) == 0); 101 | VHACD_VERIFY(pthread_mutexattr_destroy(&mutexAttr) == 0); 102 | #endif 103 | } 104 | ~Mutex(void) 105 | { 106 | #if defined(WIN32) || defined(_XBOX) 107 | DeleteCriticalSection(&m_mutex); 108 | #elif defined(__APPLE__) || defined(__linux__) 109 | VHACD_VERIFY(pthread_mutex_destroy(&m_mutex) == 0); 110 | #endif 111 | } 112 | void Lock(void) 113 | { 114 | #if defined(WIN32) || defined(_XBOX) 115 | EnterCriticalSection(&m_mutex); 116 | #elif defined(__APPLE__) || defined(__linux__) 117 | VHACD_VERIFY(pthread_mutex_lock(&m_mutex) == 0); 118 | #endif 119 | } 120 | bool TryLock(void) 121 | { 122 | #if defined(WIN32) || defined(_XBOX) 123 | bool bRet = false; 124 | //assert(("TryEnterCriticalSection seems to not work on XP???", 0)); 125 | bRet = TryEnterCriticalSection(&m_mutex) ? true : false; 126 | return bRet; 127 | #elif defined(__APPLE__) || defined(__linux__) 128 | int result = pthread_mutex_trylock(&m_mutex); 129 | return (result == 0); 130 | #endif 131 | } 132 | 133 | void Unlock(void) 134 | { 135 | #if defined(WIN32) || defined(_XBOX) 136 | LeaveCriticalSection(&m_mutex); 137 | #elif defined(__APPLE__) || defined(__linux__) 138 | VHACD_VERIFY(pthread_mutex_unlock(&m_mutex) == 0); 139 | #endif 140 | } 141 | 142 | private: 143 | #if defined(WIN32) || defined(_XBOX) 144 | CRITICAL_SECTION m_mutex; 145 | #elif defined(__APPLE__) || defined(__linux__) 146 | pthread_mutex_t m_mutex; 147 | #endif 148 | }; 149 | 150 | } 151 | #endif // VHACD_MUTEX_H 152 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/vhacdVector.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) 2 | All rights reserved. 3 | 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | */ 15 | #pragma once 16 | #ifndef VHACD_VECTOR_H 17 | #define VHACD_VECTOR_H 18 | #include 19 | #include 20 | 21 | namespace VHACD 22 | { 23 | //! Vector dim 3. 24 | template < typename T > class Vec3 25 | { 26 | public: 27 | T & operator[](size_t i) { return m_data[i];} 28 | const T & operator[](size_t i) const { return m_data[i];} 29 | T & X(); 30 | T & Y(); 31 | T & Z(); 32 | const T & X() const; 33 | const T & Y() const; 34 | const T & Z() const; 35 | void Normalize(); 36 | T GetNorm() const; 37 | void operator= (const Vec3 & rhs); 38 | void operator+=(const Vec3 & rhs); 39 | void operator-=(const Vec3 & rhs); 40 | void operator-=(T a); 41 | void operator+=(T a); 42 | void operator/=(T a); 43 | void operator*=(T a); 44 | Vec3 operator^ (const Vec3 & rhs) const; 45 | T operator* (const Vec3 & rhs) const; 46 | Vec3 operator+ (const Vec3 & rhs) const; 47 | Vec3 operator- (const Vec3 & rhs) const; 48 | Vec3 operator- () const; 49 | Vec3 operator* (T rhs) const; 50 | Vec3 operator/ (T rhs) const; 51 | bool operator< (const Vec3 & rhs) const; 52 | bool operator> (const Vec3 & rhs) const; 53 | Vec3(); 54 | Vec3(T a); 55 | Vec3(T x, T y, T z); 56 | Vec3(const Vec3 & rhs); 57 | /*virtual*/ ~Vec3(void); 58 | 59 | private: 60 | T m_data[3]; 61 | }; 62 | //! Vector dim 2. 63 | template < typename T > class Vec2 64 | { 65 | public: 66 | T & operator[](size_t i) { return m_data[i];} 67 | const T & operator[](size_t i) const { return m_data[i];} 68 | T & X(); 69 | T & Y(); 70 | const T & X() const; 71 | const T & Y() const; 72 | void Normalize(); 73 | T GetNorm() const; 74 | void operator= (const Vec2 & rhs); 75 | void operator+=(const Vec2 & rhs); 76 | void operator-=(const Vec2 & rhs); 77 | void operator-=(T a); 78 | void operator+=(T a); 79 | void operator/=(T a); 80 | void operator*=(T a); 81 | T operator^ (const Vec2 & rhs) const; 82 | T operator* (const Vec2 & rhs) const; 83 | Vec2 operator+ (const Vec2 & rhs) const; 84 | Vec2 operator- (const Vec2 & rhs) const; 85 | Vec2 operator- () const; 86 | Vec2 operator* (T rhs) const; 87 | Vec2 operator/ (T rhs) const; 88 | Vec2(); 89 | Vec2(T a); 90 | Vec2(T x, T y); 91 | Vec2(const Vec2 & rhs); 92 | /*virtual*/ ~Vec2(void); 93 | 94 | private: 95 | T m_data[2]; 96 | }; 97 | 98 | template 99 | const bool Colinear(const Vec3 & a, const Vec3 & b, const Vec3 & c); 100 | template 101 | const T ComputeVolume4(const Vec3 & a, const Vec3 & b, const Vec3 & c, const Vec3 & d); 102 | 103 | } 104 | #include "vhacdVector.inl" // template implementation 105 | #endif -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/vhacdICHull.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) 2 | All rights reserved. 3 | 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | */ 15 | #pragma once 16 | #ifndef VHACD_ICHULL_H 17 | #define VHACD_ICHULL_H 18 | #include "vhacdManifoldMesh.h" 19 | #include "vhacdVector.h" 20 | 21 | namespace VHACD 22 | { 23 | //! Incremental Convex Hull algorithm (cf. http://maven.smith.edu/~orourke/books/ftp.html ). 24 | enum ICHullError 25 | { 26 | ICHullErrorOK = 0, 27 | ICHullErrorCoplanarPoints, 28 | ICHullErrorNoVolume, 29 | ICHullErrorInconsistent, 30 | ICHullErrorNotEnoughPoints 31 | }; 32 | class ICHull 33 | { 34 | public: 35 | static const double sc_eps; 36 | //! 37 | bool IsFlat() { return m_isFlat;} 38 | //! Returns the computed mesh 39 | TMMesh & GetMesh() { return m_mesh;} 40 | //! Add one point to the convex-hull 41 | bool AddPoint(const Vec3 & point) {return AddPoints(&point, 1);} 42 | //! Add one point to the convex-hull 43 | bool AddPoint(const Vec3 & point, int id); 44 | //! Add points to the convex-hull 45 | bool AddPoints(const Vec3 * points, size_t nPoints); 46 | //! 47 | ICHullError Process(); 48 | //! 49 | ICHullError Process(const unsigned int nPointsCH, const double minVolume = 0.0); 50 | //! 51 | bool IsInside(const Vec3 & pt0, const double eps = 0.0); 52 | //! 53 | const ICHull & operator=(ICHull & rhs); 54 | 55 | //! Constructor 56 | ICHull(); 57 | //! Destructor 58 | ~ICHull(void) {}; 59 | 60 | private: 61 | //! DoubleTriangle builds the initial double triangle. It first finds 3 noncollinear points and makes two faces out of them, in opposite order. It then finds a fourth point that is not coplanar with that face. The vertices are stored in the face structure in counterclockwise order so that the volume between the face and the point is negative. Lastly, the 3 newfaces to the fourth point are constructed and the data structures are cleaned up. 62 | ICHullError DoubleTriangle(); 63 | //! MakeFace creates a new face structure from three vertices (in ccw order). It returns a pointer to the face. 64 | CircularListElement * MakeFace(CircularListElement * v0, 65 | CircularListElement * v1, 66 | CircularListElement * v2, 67 | CircularListElement * fold); 68 | //! 69 | CircularListElement * MakeConeFace(CircularListElement * e, CircularListElement * v); 70 | //! 71 | bool ProcessPoint(); 72 | //! 73 | bool ComputePointVolume(double &totalVolume, bool markVisibleFaces); 74 | //! 75 | bool FindMaxVolumePoint(const double minVolume = 0.0); 76 | //! 77 | bool CleanEdges(); 78 | //! 79 | bool CleanVertices(unsigned int & addedPoints); 80 | //! 81 | bool CleanTriangles(); 82 | //! 83 | bool CleanUp(unsigned int & addedPoints); 84 | //! 85 | bool MakeCCW(CircularListElement * f, 86 | CircularListElement * e, 87 | CircularListElement * v); 88 | void Clear(); 89 | private: 90 | static const int sc_dummyIndex; 91 | TMMesh m_mesh; 92 | SArray *> m_edgesToDelete; 93 | SArray *> m_edgesToUpdate; 94 | SArray *> m_trianglesToDelete; 95 | Vec3 m_normal; 96 | bool m_isFlat; 97 | ICHull(const ICHull & rhs); 98 | }; 99 | } 100 | #endif // VHACD_ICHULL_H -------------------------------------------------------------------------------- /lib/VHACD_Lib/public/VHACD.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) 2 | All rights reserved. 3 | 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | */ 15 | #pragma once 16 | #ifndef VHACD_H 17 | #define VHACD_H 18 | 19 | #define VHACD_VERSION_MAJOR 2 20 | #define VHACD_VERSION_MINOR 2 21 | 22 | namespace VHACD 23 | { 24 | class IVHACD 25 | { 26 | public: 27 | class IUserCallback { 28 | public: 29 | virtual ~IUserCallback() {}; 30 | virtual void Update(const double overallProgress, 31 | const double stageProgress, 32 | const double operationProgress, 33 | const char * const stage, 34 | const char * const operation) = 0; 35 | }; 36 | 37 | class IUserLogger { 38 | public: 39 | virtual ~IUserLogger() {}; 40 | virtual void Log(const char * const msg) = 0; 41 | }; 42 | 43 | class ConvexHull { 44 | public: 45 | double * m_points; 46 | int * m_triangles; 47 | unsigned int m_nPoints; 48 | unsigned int m_nTriangles; 49 | }; 50 | 51 | class Parameters { 52 | public: 53 | Parameters(void) { Init(); } 54 | void Init(void) 55 | { 56 | m_resolution = 100000; 57 | m_depth = 20; 58 | m_concavity = 0.001; 59 | m_delta = 0.05; 60 | m_planeDownsampling = 4; 61 | m_convexhullDownsampling = 4; 62 | m_alpha = 0.05; 63 | m_beta = 0.05; 64 | m_gamma = 0.0005; 65 | m_pca = 0; 66 | m_mode = 0; // 0: voxel-based (recommended), 1: tetrahedron-based 67 | m_maxNumVerticesPerCH = 64; 68 | m_minVolumePerCH = 0.0001; 69 | m_callback = 0; 70 | m_logger = 0; 71 | m_convexhullApproximation = true; 72 | m_oclAcceleration = true; 73 | } 74 | double m_concavity; 75 | double m_alpha; 76 | double m_beta; 77 | double m_gamma; 78 | double m_delta; 79 | double m_minVolumePerCH; 80 | IUserCallback * m_callback; 81 | IUserLogger * m_logger; 82 | unsigned int m_resolution; 83 | unsigned int m_maxNumVerticesPerCH; 84 | int m_depth; 85 | int m_planeDownsampling; 86 | int m_convexhullDownsampling; 87 | int m_pca; 88 | int m_mode; 89 | int m_convexhullApproximation; 90 | int m_oclAcceleration; 91 | }; 92 | 93 | virtual void Cancel() = 0; 94 | virtual bool Compute(const float * const points, 95 | const unsigned int stridePoints, 96 | const unsigned int countPoints, 97 | const int * const triangles, 98 | const unsigned int strideTriangles, 99 | const unsigned int countTriangles, 100 | const Parameters & params) = 0; 101 | virtual bool Compute(const double * const points, 102 | const unsigned int stridePoints, 103 | const unsigned int countPoints, 104 | const int * const triangles, 105 | const unsigned int strideTriangles, 106 | const unsigned int countTriangles, 107 | const Parameters & params) = 0; 108 | virtual unsigned int GetNConvexHulls() const = 0; 109 | virtual void GetConvexHull(const unsigned int index, ConvexHull & ch) const = 0; 110 | virtual void Clean(void) = 0; // release internally allocated memory 111 | virtual void Release(void) = 0; // release IVHACD 112 | virtual bool OCLInit(void * const oclDevice, 113 | IUserLogger * const logger = 0) = 0; 114 | virtual bool OCLRelease(IUserLogger * const logger = 0) = 0; 115 | 116 | protected: 117 | virtual ~IVHACD(void) {} 118 | }; 119 | IVHACD * CreateVHACD(void); 120 | } 121 | #endif // VHACD_H -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/vhacdManifoldMesh.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) 2 | All rights reserved. 3 | 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | */ 15 | #pragma once 16 | #ifndef VHACD_MANIFOLD_MESH_H 17 | #define VHACD_MANIFOLD_MESH_H 18 | #include "vhacdCircularList.h" 19 | #include "vhacdVector.h" 20 | #include "vhacdSArray.h" 21 | namespace VHACD 22 | { 23 | class TMMTriangle; 24 | class TMMEdge; 25 | class TMMesh; 26 | class ICHull; 27 | 28 | //! Vertex data structure used in a triangular manifold mesh (TMM). 29 | class TMMVertex 30 | { 31 | public: 32 | void Initialize(); 33 | TMMVertex(void); 34 | ~TMMVertex(void); 35 | 36 | private: 37 | Vec3 m_pos; 38 | int m_name; 39 | size_t m_id; 40 | CircularListElement * m_duplicate; // pointer to incident cone edge (or NULL) 41 | bool m_onHull; 42 | bool m_tag; 43 | TMMVertex(const TMMVertex & rhs); 44 | friend class ICHull; 45 | friend class TMMesh; 46 | friend class TMMTriangle; 47 | friend class TMMEdge; 48 | }; 49 | 50 | //! Edge data structure used in a triangular manifold mesh (TMM). 51 | class TMMEdge 52 | { 53 | public: 54 | void Initialize(); 55 | TMMEdge(void); 56 | ~TMMEdge(void); 57 | private: 58 | size_t m_id; 59 | CircularListElement * m_triangles[2]; 60 | CircularListElement * m_vertices[2]; 61 | CircularListElement * m_newFace; 62 | TMMEdge(const TMMEdge & rhs); 63 | friend class ICHull; 64 | friend class TMMTriangle; 65 | friend class TMMVertex; 66 | friend class TMMesh; 67 | }; 68 | 69 | //! Triangle data structure used in a triangular manifold mesh (TMM). 70 | class TMMTriangle 71 | { 72 | public: 73 | void Initialize(); 74 | TMMTriangle(void); 75 | ~TMMTriangle(void); 76 | private: 77 | size_t m_id; 78 | CircularListElement * m_edges[3]; 79 | CircularListElement * m_vertices[3]; 80 | bool m_visible; 81 | 82 | TMMTriangle(const TMMTriangle & rhs); 83 | friend class ICHull; 84 | friend class TMMesh; 85 | friend class TMMVertex; 86 | friend class TMMEdge; 87 | }; 88 | //! triangular manifold mesh data structure. 89 | class TMMesh 90 | { 91 | public: 92 | //! Returns the number of vertices> 93 | inline size_t GetNVertices() const { return m_vertices.GetSize();} 94 | //! Returns the number of edges 95 | inline size_t GetNEdges() const { return m_edges.GetSize();} 96 | //! Returns the number of triangles 97 | inline size_t GetNTriangles() const { return m_triangles.GetSize();} 98 | //! Returns the vertices circular list 99 | inline const CircularList & GetVertices() const { return m_vertices;} 100 | //! Returns the edges circular list 101 | inline const CircularList & GetEdges() const { return m_edges;} 102 | //! Returns the triangles circular list 103 | inline const CircularList & GetTriangles() const { return m_triangles;} 104 | //! Returns the vertices circular list 105 | inline CircularList & GetVertices() { return m_vertices;} 106 | //! Returns the edges circular list 107 | inline CircularList & GetEdges() { return m_edges;} 108 | //! Returns the triangles circular list 109 | inline CircularList & GetTriangles() { return m_triangles;} 110 | //! Add vertex to the mesh 111 | CircularListElement * AddVertex() {return m_vertices.Add();} 112 | //! Add vertex to the mesh 113 | CircularListElement * AddEdge() {return m_edges.Add();} 114 | //! Add vertex to the mesh 115 | CircularListElement * AddTriangle() {return m_triangles.Add();} 116 | //! Print mesh information 117 | void Print(); 118 | //! 119 | void GetIFS(Vec3 * const points, Vec3 * const triangles); 120 | //! 121 | void Clear(); 122 | //! 123 | void Copy(TMMesh & mesh); 124 | //! 125 | bool CheckConsistancy(); 126 | //! 127 | bool Normalize(); 128 | //! 129 | bool Denormalize(); 130 | //! Constructor 131 | TMMesh(); 132 | //! Destructor 133 | virtual ~TMMesh(void); 134 | 135 | private: 136 | CircularList m_vertices; 137 | CircularList m_edges; 138 | CircularList m_triangles; 139 | 140 | // not defined 141 | TMMesh(const TMMesh & rhs); 142 | friend class ICHull; 143 | }; 144 | } 145 | #endif // VHACD_MANIFOLD_MESH_H -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/vhacdSArray.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) 2 | All rights reserved. 3 | 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | */ 15 | #pragma once 16 | #ifndef VHACD_SARRAY_H 17 | #define VHACD_SARRAY_H 18 | #include 19 | #include 20 | #include 21 | 22 | #define SARRAY_DEFAULT_MIN_SIZE 16 23 | 24 | namespace VHACD 25 | { 26 | //! SArray. 27 | template < typename T, size_t N = 64 > class SArray 28 | { 29 | public: 30 | T & operator[](size_t i) 31 | { 32 | T * const data = Data(); 33 | return data[i]; 34 | } 35 | const T & operator[](size_t i) const 36 | { 37 | const T * const data = Data(); 38 | return data[i]; 39 | } 40 | size_t Size() const 41 | { 42 | return m_size; 43 | } 44 | T * const Data() 45 | { 46 | return (m_maxSize == N)? m_data0 : m_data; 47 | } 48 | const T * const Data() const 49 | { 50 | return (m_maxSize == N)? m_data0 : m_data; 51 | } 52 | void Clear() 53 | { 54 | m_size = 0; 55 | delete [] m_data; 56 | m_data = 0; 57 | m_maxSize = N; 58 | } 59 | void PopBack() 60 | { 61 | --m_size; 62 | } 63 | void Allocate(size_t size) 64 | { 65 | if (size > m_maxSize) 66 | { 67 | T * temp = new T[size]; 68 | memcpy(temp, Data(), m_size*sizeof(T)); 69 | delete [] m_data; 70 | m_data = temp; 71 | m_maxSize = size; 72 | } 73 | } 74 | void Resize(size_t size) 75 | { 76 | Allocate(size); 77 | m_size = size; 78 | } 79 | 80 | void PushBack(const T & value) 81 | { 82 | if (m_size==m_maxSize) 83 | { 84 | size_t maxSize = (m_maxSize << 1); 85 | T * temp = new T[maxSize]; 86 | memcpy(temp, Data(), m_maxSize*sizeof(T)); 87 | delete [] m_data; 88 | m_data = temp; 89 | m_maxSize = maxSize; 90 | } 91 | T * const data = Data(); 92 | data[m_size++] = value; 93 | } 94 | bool Find(const T & value, size_t & pos) 95 | { 96 | T * const data = Data(); 97 | for(pos = 0; pos < m_size; ++pos) 98 | if (value == data[pos]) return true; 99 | return false; 100 | } 101 | bool Insert(const T & value) 102 | { 103 | size_t pos; 104 | if (Find(value, pos)) return false; 105 | PushBack(value); 106 | return true; 107 | } 108 | bool Erase(const T & value) 109 | { 110 | size_t pos; 111 | T * const data = Data(); 112 | if (Find(value, pos)) 113 | { 114 | for(size_t j = pos+1; j < m_size; ++j) 115 | data[j-1] = data[j]; 116 | --m_size; 117 | return true; 118 | } 119 | return false; 120 | } 121 | void operator=(const SArray & rhs) 122 | { 123 | if (m_maxSize < rhs.m_size) 124 | { 125 | delete [] m_data; 126 | m_maxSize = rhs.m_maxSize; 127 | m_data = new T[m_maxSize]; 128 | } 129 | m_size = rhs.m_size; 130 | memcpy(Data(), rhs.Data(), m_size*sizeof(T)); 131 | } 132 | void Initialize() 133 | { 134 | m_data = 0; 135 | m_size = 0; 136 | m_maxSize = N; 137 | } 138 | SArray(const SArray & rhs) 139 | { 140 | m_data = 0; 141 | m_size = 0; 142 | m_maxSize = N; 143 | *this = rhs; 144 | } 145 | SArray() 146 | { 147 | Initialize(); 148 | } 149 | ~SArray() 150 | { 151 | delete [] m_data; 152 | } 153 | private: 154 | T m_data0[N]; 155 | T * m_data; 156 | size_t m_size; 157 | size_t m_maxSize; 158 | }; 159 | } 160 | #endif -------------------------------------------------------------------------------- /lib/VHACD_Lib/src/vhacdManifoldMesh.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) 2 | All rights reserved. 3 | 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | */ 15 | #include "vhacdManifoldMesh.h" 16 | namespace VHACD 17 | { 18 | TMMVertex::TMMVertex(void) 19 | { 20 | Initialize(); 21 | } 22 | void TMMVertex::Initialize() 23 | { 24 | m_name = 0; 25 | m_id = 0; 26 | m_duplicate = 0; 27 | m_onHull = false; 28 | m_tag = false; 29 | } 30 | 31 | TMMVertex::~TMMVertex(void) 32 | { 33 | } 34 | TMMEdge::TMMEdge(void) 35 | { 36 | Initialize(); 37 | } 38 | void TMMEdge::Initialize() 39 | { 40 | m_id = 0; 41 | m_triangles[0] = m_triangles[1] = m_newFace = 0; 42 | m_vertices[0] = m_vertices[1] = 0; 43 | } 44 | TMMEdge::~TMMEdge(void) 45 | { 46 | } 47 | void TMMTriangle::Initialize() 48 | { 49 | m_id = 0; 50 | for(int i = 0; i < 3; i++) 51 | { 52 | m_edges[i] = 0; 53 | m_vertices[0] = 0; 54 | } 55 | m_visible = false; 56 | } 57 | TMMTriangle::TMMTriangle(void) 58 | { 59 | Initialize(); 60 | } 61 | TMMTriangle::~TMMTriangle(void) 62 | { 63 | } 64 | TMMesh::TMMesh() 65 | { 66 | } 67 | TMMesh::~TMMesh(void) 68 | { 69 | } 70 | void TMMesh::GetIFS(Vec3 * const points, Vec3 * const triangles) 71 | { 72 | size_t nV = m_vertices.GetSize(); 73 | size_t nT = m_triangles.GetSize(); 74 | 75 | for(size_t v = 0; v < nV; v++) 76 | { 77 | points[v] = m_vertices.GetData().m_pos; 78 | m_vertices.GetData().m_id = v; 79 | m_vertices.Next(); 80 | } 81 | for(size_t f = 0; f < nT; f++) 82 | { 83 | TMMTriangle & currentTriangle = m_triangles.GetData(); 84 | triangles[f].X() = static_cast(currentTriangle.m_vertices[0]->GetData().m_id); 85 | triangles[f].Y() = static_cast(currentTriangle.m_vertices[1]->GetData().m_id); 86 | triangles[f].Z() = static_cast(currentTriangle.m_vertices[2]->GetData().m_id); 87 | m_triangles.Next(); 88 | } 89 | } 90 | void TMMesh::Clear() 91 | { 92 | m_vertices.Clear(); 93 | m_edges.Clear(); 94 | m_triangles.Clear(); 95 | } 96 | void TMMesh::Copy(TMMesh & mesh) 97 | { 98 | Clear(); 99 | // updating the id's 100 | size_t nV = mesh.m_vertices.GetSize(); 101 | size_t nE = mesh. m_edges.GetSize(); 102 | size_t nT = mesh.m_triangles.GetSize(); 103 | for(size_t v = 0; v < nV; v++) 104 | { 105 | mesh.m_vertices.GetData().m_id = v; 106 | mesh.m_vertices.Next(); 107 | } 108 | for(size_t e = 0; e < nE; e++) 109 | { 110 | mesh.m_edges.GetData().m_id = e; 111 | mesh.m_edges.Next(); 112 | 113 | } 114 | for(size_t f = 0; f < nT; f++) 115 | { 116 | mesh.m_triangles.GetData().m_id = f; 117 | mesh.m_triangles.Next(); 118 | } 119 | // copying data 120 | m_vertices = mesh.m_vertices; 121 | m_edges = mesh.m_edges; 122 | m_triangles = mesh.m_triangles; 123 | 124 | // generate mapping 125 | CircularListElement ** vertexMap = new CircularListElement * [nV]; 126 | CircularListElement ** edgeMap = new CircularListElement * [nE]; 127 | CircularListElement ** triangleMap = new CircularListElement * [nT]; 128 | for(size_t v = 0; v < nV; v++) 129 | { 130 | vertexMap[v] = m_vertices.GetHead(); 131 | m_vertices.Next(); 132 | } 133 | for(size_t e = 0; e < nE; e++) 134 | { 135 | edgeMap[e] = m_edges.GetHead(); 136 | m_edges.Next(); 137 | } 138 | for(size_t f = 0; f < nT; f++) 139 | { 140 | triangleMap[f] = m_triangles.GetHead(); 141 | m_triangles.Next(); 142 | } 143 | 144 | // updating pointers 145 | for(size_t v = 0; v < nV; v++) 146 | { 147 | if (vertexMap[v]->GetData().m_duplicate) 148 | { 149 | vertexMap[v]->GetData().m_duplicate = edgeMap[vertexMap[v]->GetData().m_duplicate->GetData().m_id]; 150 | } 151 | } 152 | for(size_t e = 0; e < nE; e++) 153 | { 154 | if (edgeMap[e]->GetData().m_newFace) 155 | { 156 | edgeMap[e]->GetData().m_newFace = triangleMap[edgeMap[e]->GetData().m_newFace->GetData().m_id]; 157 | } 158 | if (nT > 0) 159 | { 160 | for(int f = 0; f < 2; f++) 161 | { 162 | if (edgeMap[e]->GetData().m_triangles[f]) 163 | { 164 | edgeMap[e]->GetData().m_triangles[f] = triangleMap[edgeMap[e]->GetData().m_triangles[f]->GetData().m_id]; 165 | } 166 | } 167 | } 168 | for(int v = 0; v < 2; v++) 169 | { 170 | if (edgeMap[e]->GetData().m_vertices[v]) 171 | { 172 | edgeMap[e]->GetData().m_vertices[v] = vertexMap[edgeMap[e]->GetData().m_vertices[v]->GetData().m_id]; 173 | } 174 | } 175 | } 176 | for(size_t f = 0; f < nT; f++) 177 | { 178 | if (nE > 0) 179 | { 180 | for(int e = 0; e < 3; e++) 181 | { 182 | if (triangleMap[f]->GetData().m_edges[e]) 183 | { 184 | triangleMap[f]->GetData().m_edges[e] = edgeMap[triangleMap[f]->GetData().m_edges[e]->GetData().m_id]; 185 | } 186 | } 187 | } 188 | for(int v = 0; v < 3; v++) 189 | { 190 | if (triangleMap[f]->GetData().m_vertices[v]) 191 | { 192 | triangleMap[f]->GetData().m_vertices[v] = vertexMap[triangleMap[f]->GetData().m_vertices[v]->GetData().m_id]; 193 | } 194 | } 195 | } 196 | delete [] vertexMap; 197 | delete [] edgeMap; 198 | delete [] triangleMap; 199 | 200 | } 201 | bool TMMesh::CheckConsistancy() 202 | { 203 | size_t nE = m_edges.GetSize(); 204 | size_t nT = m_triangles.GetSize(); 205 | for (size_t e = 0; e < nE; e++) 206 | { 207 | for (int f = 0; f < 2; f++) 208 | { 209 | if (!m_edges.GetHead()->GetData().m_triangles[f]) 210 | { 211 | return false; 212 | } 213 | } 214 | m_edges.Next(); 215 | } 216 | for (size_t f = 0; f < nT; f++) 217 | { 218 | for (int e = 0; e < 3; e++) 219 | { 220 | int found = 0; 221 | for (int k = 0; k < 2; k++) 222 | { 223 | if (m_triangles.GetHead()->GetData().m_edges[e]->GetData().m_triangles[k] == m_triangles.GetHead()) 224 | { 225 | found++; 226 | } 227 | } 228 | if (found != 1) 229 | { 230 | return false; 231 | } 232 | } 233 | m_triangles.Next(); 234 | } 235 | return true; 236 | } 237 | } -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/vhacdMesh.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) 2 | All rights reserved. 3 | 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | */ 15 | #pragma once 16 | #ifndef VHACD_MESH_H 17 | #define VHACD_MESH_H 18 | #include "vhacdSArray.h" 19 | #include "vhacdVector.h" 20 | 21 | #define VHACD_DEBUG_MESH 22 | 23 | namespace VHACD 24 | { 25 | enum AXIS 26 | { 27 | AXIS_X = 0, 28 | AXIS_Y = 1, 29 | AXIS_Z = 2 30 | }; 31 | struct Plane 32 | { 33 | double m_a; 34 | double m_b; 35 | double m_c; 36 | double m_d; 37 | AXIS m_axis; 38 | short m_index; 39 | }; 40 | #ifdef VHACD_DEBUG_MESH 41 | struct Material 42 | { 43 | 44 | Vec3 m_diffuseColor; 45 | double m_ambientIntensity; 46 | Vec3 m_specularColor; 47 | Vec3 m_emissiveColor; 48 | double m_shininess; 49 | double m_transparency; 50 | Material(void) 51 | { 52 | m_diffuseColor.X() = 0.5; 53 | m_diffuseColor.Y() = 0.5; 54 | m_diffuseColor.Z() = 0.5; 55 | m_specularColor.X() = 0.5; 56 | m_specularColor.Y() = 0.5; 57 | m_specularColor.Z() = 0.5; 58 | m_ambientIntensity = 0.4; 59 | m_emissiveColor.X() = 0.0; 60 | m_emissiveColor.Y() = 0.0; 61 | m_emissiveColor.Z() = 0.0; 62 | m_shininess = 0.4; 63 | m_transparency = 0.0; 64 | }; 65 | }; 66 | #endif // VHACD_DEBUG_MESH 67 | 68 | //! Triangular mesh data structure 69 | class Mesh 70 | { 71 | public: 72 | void AddPoint(const Vec3 & pt) { m_points.PushBack(pt);}; 73 | void SetPoint(size_t index, const Vec3 & pt) { m_points[index] = pt; }; 74 | const Vec3 & GetPoint(size_t index) const { return m_points[index]; }; 75 | Vec3 & GetPoint(size_t index) { return m_points[index]; }; 76 | size_t GetNPoints() const { return m_points.Size();}; 77 | double * GetPoints() { return (double *)m_points.Data(); } // ugly 78 | const double * const GetPoints() const { return (double *)m_points.Data(); } // ugly 79 | const Vec3 * const GetPointsBuffer() const { return m_points.Data(); } // 80 | Vec3 * const GetPointsBuffer() { return m_points.Data(); } // 81 | void AddTriangle(const Vec3 & tri) { m_triangles.PushBack(tri);}; 82 | void SetTriangle(size_t index, const Vec3 & tri) { m_triangles[index] = tri; }; 83 | const Vec3 & GetTriangle(size_t index) const { return m_triangles[index];}; 84 | Vec3 & GetTriangle(size_t index) { return m_triangles[index];}; 85 | size_t GetNTriangles() const { return m_triangles.Size();}; 86 | int * GetTriangles() { return (int *)m_triangles.Data(); } // ugly 87 | const int * const GetTriangles() const { return (int *)m_triangles.Data(); } // ugly 88 | const Vec3 * const GetTrianglesBuffer() const { return m_triangles.Data(); } 89 | Vec3 * const GetTrianglesBuffer() { return m_triangles.Data(); } 90 | const Vec3 & GetCenter() const { return m_center;} 91 | const Vec3 & GetMinBB() const { return m_minBB;} 92 | const Vec3 & GetMaxBB() const { return m_maxBB;} 93 | void ClearPoints() { m_points.Clear();} 94 | void ClearTriangles() { m_triangles.Clear();} 95 | void Clear() { ClearPoints(); ClearTriangles();} 96 | void ResizePoints(size_t nPts) { m_points.Resize(nPts);} 97 | void ResizeTriangles(size_t nTri) { m_triangles.Resize(nTri);} 98 | void CopyPoints(SArray< Vec3 >& points) const { points = m_points; } 99 | double GetDiagBB() const { return m_diag; } 100 | double ComputeVolume() const; 101 | void ComputeConvexHull(const double * const pts, 102 | const size_t nPts); 103 | void Clip(const Plane & plane, 104 | SArray< Vec3 > & positivePart, 105 | SArray< Vec3 > & negativePart) const; 106 | bool IsInside(const Vec3 & pt) const; 107 | double ComputeDiagBB(); 108 | 109 | #ifdef VHACD_DEBUG_MESH 110 | bool LoadOFF(const std::string & fileName, bool invert); 111 | bool SaveVRML2(const std::string & fileName) const ; 112 | bool SaveVRML2(std::ofstream & fout, const Material & material) const; 113 | bool SaveOFF(const std::string & fileName) const; 114 | #endif // VHACD_DEBUG_MESH 115 | 116 | //! Constructor. 117 | Mesh(); 118 | //! Destructor. 119 | ~Mesh(void); 120 | 121 | private: 122 | SArray< Vec3 > m_points; 123 | SArray< Vec3 > m_triangles; 124 | Vec3 m_minBB; 125 | Vec3 m_maxBB; 126 | Vec3 m_center; 127 | double m_diag; 128 | }; 129 | } 130 | #endif -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/vhacdVector.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef VHACD_VECTOR_INL 3 | #define VHACD_VECTOR_INL 4 | namespace VHACD 5 | { 6 | template 7 | inline Vec3 operator*(T lhs, const Vec3 & rhs) 8 | { 9 | return Vec3(lhs * rhs.X(), lhs * rhs.Y(), lhs * rhs.Z()); 10 | } 11 | template 12 | inline T & Vec3::X() 13 | { 14 | return m_data[0]; 15 | } 16 | template 17 | inline T & Vec3::Y() 18 | { 19 | return m_data[1]; 20 | } 21 | template 22 | inline T & Vec3::Z() 23 | { 24 | return m_data[2]; 25 | } 26 | template 27 | inline const T & Vec3::X() const 28 | { 29 | return m_data[0]; 30 | } 31 | template 32 | inline const T & Vec3::Y() const 33 | { 34 | return m_data[1]; 35 | } 36 | template 37 | inline const T & Vec3::Z() const 38 | { 39 | return m_data[2]; 40 | } 41 | template 42 | inline void Vec3::Normalize() 43 | { 44 | T n = sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]+m_data[2]*m_data[2]); 45 | if (n != 0.0) (*this) /= n; 46 | } 47 | template 48 | inline T Vec3::GetNorm() const 49 | { 50 | return sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]+m_data[2]*m_data[2]); 51 | } 52 | template 53 | inline void Vec3::operator= (const Vec3 & rhs) 54 | { 55 | this->m_data[0] = rhs.m_data[0]; 56 | this->m_data[1] = rhs.m_data[1]; 57 | this->m_data[2] = rhs.m_data[2]; 58 | } 59 | template 60 | inline void Vec3::operator+=(const Vec3 & rhs) 61 | { 62 | this->m_data[0] += rhs.m_data[0]; 63 | this->m_data[1] += rhs.m_data[1]; 64 | this->m_data[2] += rhs.m_data[2]; 65 | } 66 | template 67 | inline void Vec3::operator-=(const Vec3 & rhs) 68 | { 69 | this->m_data[0] -= rhs.m_data[0]; 70 | this->m_data[1] -= rhs.m_data[1]; 71 | this->m_data[2] -= rhs.m_data[2]; 72 | } 73 | template 74 | inline void Vec3::operator-=(T a) 75 | { 76 | this->m_data[0] -= a; 77 | this->m_data[1] -= a; 78 | this->m_data[2] -= a; 79 | } 80 | template 81 | inline void Vec3::operator+=(T a) 82 | { 83 | this->m_data[0] += a; 84 | this->m_data[1] += a; 85 | this->m_data[2] += a; 86 | } 87 | template 88 | inline void Vec3::operator/=(T a) 89 | { 90 | this->m_data[0] /= a; 91 | this->m_data[1] /= a; 92 | this->m_data[2] /= a; 93 | } 94 | template 95 | inline void Vec3::operator*=(T a) 96 | { 97 | this->m_data[0] *= a; 98 | this->m_data[1] *= a; 99 | this->m_data[2] *= a; 100 | } 101 | template 102 | inline Vec3 Vec3::operator^ (const Vec3 & rhs) const 103 | { 104 | return Vec3(m_data[1] * rhs.m_data[2] - m_data[2] * rhs.m_data[1], 105 | m_data[2] * rhs.m_data[0] - m_data[0] * rhs.m_data[2], 106 | m_data[0] * rhs.m_data[1] - m_data[1] * rhs.m_data[0]); 107 | } 108 | template 109 | inline T Vec3::operator*(const Vec3 & rhs) const 110 | { 111 | return (m_data[0] * rhs.m_data[0] + m_data[1] * rhs.m_data[1] + m_data[2] * rhs.m_data[2]); 112 | } 113 | template 114 | inline Vec3 Vec3::operator+(const Vec3 & rhs) const 115 | { 116 | return Vec3(m_data[0] + rhs.m_data[0],m_data[1] + rhs.m_data[1],m_data[2] + rhs.m_data[2]); 117 | } 118 | template 119 | inline Vec3 Vec3::operator-(const Vec3 & rhs) const 120 | { 121 | return Vec3(m_data[0] - rhs.m_data[0],m_data[1] - rhs.m_data[1],m_data[2] - rhs.m_data[2]) ; 122 | } 123 | template 124 | inline Vec3 Vec3::operator-() const 125 | { 126 | return Vec3(-m_data[0],-m_data[1],-m_data[2]) ; 127 | } 128 | 129 | template 130 | inline Vec3 Vec3::operator*(T rhs) const 131 | { 132 | return Vec3(rhs * this->m_data[0], rhs * this->m_data[1], rhs * this->m_data[2]); 133 | } 134 | template 135 | inline Vec3 Vec3::operator/ (T rhs) const 136 | { 137 | return Vec3(m_data[0] / rhs, m_data[1] / rhs, m_data[2] / rhs); 138 | } 139 | template 140 | inline Vec3::Vec3(T a) 141 | { 142 | m_data[0] = m_data[1] = m_data[2] = a; 143 | } 144 | template 145 | inline Vec3::Vec3(T x, T y, T z) 146 | { 147 | m_data[0] = x; 148 | m_data[1] = y; 149 | m_data[2] = z; 150 | } 151 | template 152 | inline Vec3::Vec3(const Vec3 & rhs) 153 | { 154 | m_data[0] = rhs.m_data[0]; 155 | m_data[1] = rhs.m_data[1]; 156 | m_data[2] = rhs.m_data[2]; 157 | } 158 | template 159 | inline Vec3::~Vec3(void){}; 160 | 161 | template 162 | inline Vec3::Vec3() {} 163 | 164 | template 165 | inline const bool Colinear(const Vec3 & a, const Vec3 & b, const Vec3 & c) 166 | { 167 | return ((c.Z() - a.Z()) * (b.Y() - a.Y()) - (b.Z() - a.Z()) * (c.Y() - a.Y()) == 0.0 /*EPS*/) && 168 | ((b.Z() - a.Z()) * (c.X() - a.X()) - (b.X() - a.X()) * (c.Z() - a.Z()) == 0.0 /*EPS*/) && 169 | ((b.X() - a.X()) * (c.Y() - a.Y()) - (b.Y() - a.Y()) * (c.X() - a.X()) == 0.0 /*EPS*/); 170 | } 171 | 172 | template 173 | inline const T ComputeVolume4(const Vec3 & a, const Vec3 & b, const Vec3 & c, const Vec3 & d) 174 | { 175 | return (a-d) * ((b-d) ^ (c-d)); 176 | } 177 | 178 | template 179 | inline bool Vec3::operator<(const Vec3 & rhs) const 180 | { 181 | if (X() == rhs[0]) 182 | { 183 | if (Y() == rhs[1]) 184 | { 185 | return (Z() 192 | inline bool Vec3::operator>(const Vec3 & rhs) const 193 | { 194 | if (X() == rhs[0]) 195 | { 196 | if (Y() == rhs[1]) 197 | { 198 | return (Z()>rhs[2]); 199 | } 200 | return (Y()>rhs[1]); 201 | } 202 | return (X()>rhs[0]); 203 | } 204 | template 205 | inline Vec2 operator*(T lhs, const Vec2 & rhs) 206 | { 207 | return Vec2(lhs * rhs.X(), lhs * rhs.Y()); 208 | } 209 | template 210 | inline T & Vec2::X() 211 | { 212 | return m_data[0]; 213 | } 214 | template 215 | inline T & Vec2::Y() 216 | { 217 | return m_data[1]; 218 | } 219 | template 220 | inline const T & Vec2::X() const 221 | { 222 | return m_data[0]; 223 | } 224 | template 225 | inline const T & Vec2::Y() const 226 | { 227 | return m_data[1]; 228 | } 229 | template 230 | inline void Vec2::Normalize() 231 | { 232 | T n = sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]); 233 | if (n != 0.0) (*this) /= n; 234 | } 235 | template 236 | inline T Vec2::GetNorm() const 237 | { 238 | return sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]); 239 | } 240 | template 241 | inline void Vec2::operator= (const Vec2 & rhs) 242 | { 243 | this->m_data[0] = rhs.m_data[0]; 244 | this->m_data[1] = rhs.m_data[1]; 245 | } 246 | template 247 | inline void Vec2::operator+=(const Vec2 & rhs) 248 | { 249 | this->m_data[0] += rhs.m_data[0]; 250 | this->m_data[1] += rhs.m_data[1]; 251 | } 252 | template 253 | inline void Vec2::operator-=(const Vec2 & rhs) 254 | { 255 | this->m_data[0] -= rhs.m_data[0]; 256 | this->m_data[1] -= rhs.m_data[1]; 257 | } 258 | template 259 | inline void Vec2::operator-=(T a) 260 | { 261 | this->m_data[0] -= a; 262 | this->m_data[1] -= a; 263 | } 264 | template 265 | inline void Vec2::operator+=(T a) 266 | { 267 | this->m_data[0] += a; 268 | this->m_data[1] += a; 269 | } 270 | template 271 | inline void Vec2::operator/=(T a) 272 | { 273 | this->m_data[0] /= a; 274 | this->m_data[1] /= a; 275 | } 276 | template 277 | inline void Vec2::operator*=(T a) 278 | { 279 | this->m_data[0] *= a; 280 | this->m_data[1] *= a; 281 | } 282 | template 283 | inline T Vec2::operator^ (const Vec2 & rhs) const 284 | { 285 | return m_data[0] * rhs.m_data[1] - m_data[1] * rhs.m_data[0]; 286 | } 287 | template 288 | inline T Vec2::operator*(const Vec2 & rhs) const 289 | { 290 | return (m_data[0] * rhs.m_data[0] + m_data[1] * rhs.m_data[1]); 291 | } 292 | template 293 | inline Vec2 Vec2::operator+(const Vec2 & rhs) const 294 | { 295 | return Vec2(m_data[0] + rhs.m_data[0],m_data[1] + rhs.m_data[1]); 296 | } 297 | template 298 | inline Vec2 Vec2::operator-(const Vec2 & rhs) const 299 | { 300 | return Vec2(m_data[0] - rhs.m_data[0],m_data[1] - rhs.m_data[1]); 301 | } 302 | template 303 | inline Vec2 Vec2::operator-() const 304 | { 305 | return Vec2(-m_data[0],-m_data[1]) ; 306 | } 307 | 308 | template 309 | inline Vec2 Vec2::operator*(T rhs) const 310 | { 311 | return Vec2(rhs * this->m_data[0], rhs * this->m_data[1]); 312 | } 313 | template 314 | inline Vec2 Vec2::operator/ (T rhs) const 315 | { 316 | return Vec2(m_data[0] / rhs, m_data[1] / rhs); 317 | } 318 | template 319 | inline Vec2::Vec2(T a) 320 | { 321 | m_data[0] = m_data[1] = a; 322 | } 323 | template 324 | inline Vec2::Vec2(T x, T y) 325 | { 326 | m_data[0] = x; 327 | m_data[1] = y; 328 | } 329 | template 330 | inline Vec2::Vec2(const Vec2 & rhs) 331 | { 332 | m_data[0] = rhs.m_data[0]; 333 | m_data[1] = rhs.m_data[1]; 334 | } 335 | template 336 | inline Vec2::~Vec2(void){}; 337 | 338 | template 339 | inline Vec2::Vec2() {} 340 | 341 | /* 342 | InsideTriangle decides if a point P is Inside of the triangle 343 | defined by A, B, C. 344 | */ 345 | template 346 | inline const bool InsideTriangle(const Vec2 & a, const Vec2 & b, const Vec2 & c, const Vec2 & p) 347 | { 348 | T ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; 349 | T cCROSSap, bCROSScp, aCROSSbp; 350 | ax = c.X() - b.X(); ay = c.Y() - b.Y(); 351 | bx = a.X() - c.X(); by = a.Y() - c.Y(); 352 | cx = b.X() - a.X(); cy = b.Y() - a.Y(); 353 | apx= p.X() - a.X(); apy= p.Y() - a.Y(); 354 | bpx= p.X() - b.X(); bpy= p.Y() - b.Y(); 355 | cpx= p.X() - c.X(); cpy= p.Y() - c.Y(); 356 | aCROSSbp = ax*bpy - ay*bpx; 357 | cCROSSap = cx*apy - cy*apx; 358 | bCROSScp = bx*cpy - by*cpx; 359 | return ((aCROSSbp >= 0.0) && (bCROSScp >= 0.0) && (cCROSSap >= 0.0)); 360 | } 361 | } 362 | #endif //VHACD_VECTOR_INL -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/btAlignedObjectArray.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 | 17 | #ifndef BT_OBJECT_ARRAY__ 18 | #define BT_OBJECT_ARRAY__ 19 | 20 | #include "btScalar.h" // has definitions like SIMD_FORCE_INLINE 21 | #include "btAlignedAllocator.h" 22 | 23 | ///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW 24 | ///then the btAlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors 25 | ///You can enable BT_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator= 26 | ///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and 27 | ///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240 28 | 29 | #define BT_USE_PLACEMENT_NEW 1 30 | //#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in or or otherwise... 31 | #define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful 32 | 33 | #ifdef BT_USE_MEMCPY 34 | #include 35 | #include 36 | #endif //BT_USE_MEMCPY 37 | 38 | #ifdef BT_USE_PLACEMENT_NEW 39 | #include //for placement new 40 | #endif //BT_USE_PLACEMENT_NEW 41 | 42 | 43 | ///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods 44 | ///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data 45 | template 46 | //template 47 | class btAlignedObjectArray 48 | { 49 | btAlignedAllocator m_allocator; 50 | 51 | int m_size; 52 | int m_capacity; 53 | T* m_data; 54 | //PCK: added this line 55 | bool m_ownsMemory; 56 | 57 | #ifdef BT_ALLOW_ARRAY_COPY_OPERATOR 58 | public: 59 | SIMD_FORCE_INLINE btAlignedObjectArray& operator=(const btAlignedObjectArray &other) 60 | { 61 | copyFromArray(other); 62 | return *this; 63 | } 64 | #else//BT_ALLOW_ARRAY_COPY_OPERATOR 65 | private: 66 | SIMD_FORCE_INLINE btAlignedObjectArray& operator=(const btAlignedObjectArray &other); 67 | #endif//BT_ALLOW_ARRAY_COPY_OPERATOR 68 | 69 | protected: 70 | SIMD_FORCE_INLINE int allocSize(int size) 71 | { 72 | return (size ? size*2 : 1); 73 | } 74 | SIMD_FORCE_INLINE void copy(int start,int end, T* dest) const 75 | { 76 | int i; 77 | for (i=start;i=0); 157 | btAssert(n=0); 164 | btAssert(n=0); 171 | btAssert(n=0); 178 | btAssert(n0); 196 | m_size--; 197 | m_data[m_size].~T(); 198 | } 199 | 200 | ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument. 201 | ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations. 202 | SIMD_FORCE_INLINE void resize(int newsize, const T& fillData=T()) 203 | { 204 | int curSize = size(); 205 | 206 | if (newsize < curSize) 207 | { 208 | for(int i = newsize; i < curSize; i++) 209 | { 210 | m_data[i].~T(); 211 | } 212 | } else 213 | { 214 | if (newsize > size()) 215 | { 216 | reserve(newsize); 217 | } 218 | #ifdef BT_USE_PLACEMENT_NEW 219 | for (int i=curSize;i 317 | void quickSortInternal(const L& CompareFunc,int lo, int hi) 318 | { 319 | // lo is the lower index, hi is the upper index 320 | // of the region of array a that is to be sorted 321 | int i=lo, j=hi; 322 | T x=m_data[(lo+hi)/2]; 323 | 324 | // partition 325 | do 326 | { 327 | while (CompareFunc(m_data[i],x)) 328 | i++; 329 | while (CompareFunc(x,m_data[j])) 330 | j--; 331 | if (i<=j) 332 | { 333 | swap(i,j); 334 | i++; j--; 335 | } 336 | } while (i<=j); 337 | 338 | // recursion 339 | if (lo 347 | void quickSort(const L& CompareFunc) 348 | { 349 | //don't sort 0 or 1 elements 350 | if (size()>1) 351 | { 352 | quickSortInternal(CompareFunc,0,size()-1); 353 | } 354 | } 355 | 356 | 357 | ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/ 358 | template 359 | void downHeap(T *pArr, int k, int n, const L& CompareFunc) 360 | { 361 | /* PRE: a[k+1..N] is a heap */ 362 | /* POST: a[k..N] is a heap */ 363 | 364 | T temp = pArr[k - 1]; 365 | /* k has child(s) */ 366 | while (k <= n/2) 367 | { 368 | int child = 2*k; 369 | 370 | if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child])) 371 | { 372 | child++; 373 | } 374 | /* pick larger child */ 375 | if (CompareFunc(temp , pArr[child - 1])) 376 | { 377 | /* move child up */ 378 | pArr[k - 1] = pArr[child - 1]; 379 | k = child; 380 | } 381 | else 382 | { 383 | break; 384 | } 385 | } 386 | pArr[k - 1] = temp; 387 | } /*downHeap*/ 388 | 389 | void swap(int index0,int index1) 390 | { 391 | #ifdef BT_USE_MEMCPY 392 | char temp[sizeof(T)]; 393 | memcpy(temp,&m_data[index0],sizeof(T)); 394 | memcpy(&m_data[index0],&m_data[index1],sizeof(T)); 395 | memcpy(&m_data[index1],temp,sizeof(T)); 396 | #else 397 | T temp = m_data[index0]; 398 | m_data[index0] = m_data[index1]; 399 | m_data[index1] = temp; 400 | #endif //BT_USE_PLACEMENT_NEW 401 | 402 | } 403 | 404 | template 405 | void heapSort(const L& CompareFunc) 406 | { 407 | /* sort a[0..N-1], N.B. 0 to N-1 */ 408 | int k; 409 | int n = m_size; 410 | for (k = n/2; k > 0; k--) 411 | { 412 | downHeap(m_data, k, n, CompareFunc); 413 | } 414 | 415 | /* a[1..N] is now a heap */ 416 | while ( n>=1 ) 417 | { 418 | swap(0,n-1); /* largest of a[0..n-1] */ 419 | 420 | 421 | n = n - 1; 422 | /* restore a[1..i-1] heap */ 423 | downHeap(m_data, 1, n, CompareFunc); 424 | } 425 | } 426 | 427 | ///non-recursive binary search, assumes sorted array 428 | int findBinarySearch(const T& key) const 429 | { 430 | int first = 0; 431 | int last = size()-1; 432 | 433 | //assume sorted array 434 | while (first <= last) { 435 | int mid = (first + last) / 2; // compute mid point. 436 | if (key > m_data[mid]) 437 | first = mid + 1; // repeat search in top half. 438 | else if (key < m_data[mid]) 439 | last = mid - 1; // repeat search in bottom half. 440 | else 441 | return mid; // found it. return position ///// 442 | } 443 | return size(); // failed to find key 444 | } 445 | 446 | 447 | int findLinearSearch(const T& key) const 448 | { 449 | int index=size(); 450 | int i; 451 | 452 | for (i=0;i 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "btConvexHullComputer.h" 24 | #include "vhacdMesh.h" 25 | 26 | namespace VHACD 27 | { 28 | Mesh::Mesh() 29 | { 30 | m_diag = 1.0; 31 | } 32 | Mesh::~Mesh() 33 | { 34 | } 35 | double Mesh::ComputeVolume() const 36 | { 37 | const size_t nV = GetNPoints(); 38 | const size_t nT = GetNTriangles(); 39 | if (nV == 0 || nT == 0) 40 | { 41 | return 0.0; 42 | } 43 | 44 | Vec3 bary(0.0, 0.0, 0.0); 45 | for (size_t v = 0; v < nV; v++) 46 | { 47 | bary += GetPoint(v); 48 | } 49 | bary /= static_cast(nV); 50 | 51 | Vec3 ver0, ver1, ver2; 52 | double totalVolume = 0.0; 53 | for(int t = 0; t < nT; t++) 54 | { 55 | const Vec3 & tri = GetTriangle(t); 56 | ver0 = GetPoint(tri[0]); 57 | ver1 = GetPoint(tri[1]); 58 | ver2 = GetPoint(tri[2]); 59 | totalVolume += ComputeVolume4(ver0, ver1, ver2, bary); 60 | } 61 | return totalVolume/6.0; 62 | } 63 | 64 | void Mesh::ComputeConvexHull(const double * const pts, 65 | const size_t nPts) 66 | { 67 | ResizePoints(0); 68 | ResizeTriangles(0); 69 | btConvexHullComputer ch; 70 | ch.compute(pts, 3 * sizeof(double), (int) nPts, -1.0, -1.0); 71 | for (int v = 0; v < ch.vertices.size(); v++) 72 | { 73 | AddPoint(Vec3(ch.vertices[v].getX(), ch.vertices[v].getY(), ch.vertices[v].getZ())); 74 | } 75 | const int nt = ch.faces.size(); 76 | for (int t = 0; t < nt; ++t) 77 | { 78 | const btConvexHullComputer::Edge * sourceEdge = &(ch.edges[ch.faces[t]]); 79 | int a = sourceEdge->getSourceVertex(); 80 | int b = sourceEdge->getTargetVertex(); 81 | const btConvexHullComputer::Edge * edge = sourceEdge->getNextEdgeOfFace(); 82 | int c = edge->getTargetVertex(); 83 | while (c != a) 84 | { 85 | AddTriangle(Vec3(a, b, c)); 86 | edge = edge->getNextEdgeOfFace(); 87 | b = c; 88 | c = edge->getTargetVertex(); 89 | } 90 | } 91 | } 92 | void Mesh::Clip(const Plane & plane, 93 | SArray< Vec3 > & positivePart, 94 | SArray< Vec3 > & negativePart) const 95 | { 96 | const size_t nV = GetNPoints(); 97 | if (nV == 0) 98 | { 99 | return; 100 | } 101 | double d; 102 | for (size_t v = 0; v < nV; v++) 103 | { 104 | const Vec3 & pt = GetPoint(v); 105 | d = plane.m_a * pt[0] + plane.m_b * pt[1] + plane.m_c * pt[2] + plane.m_d; 106 | if (d > 0.0) 107 | { 108 | positivePart.PushBack(pt); 109 | } 110 | else if (d < 0.0) 111 | { 112 | negativePart.PushBack(pt); 113 | } 114 | else 115 | { 116 | positivePart.PushBack(pt); 117 | negativePart.PushBack(pt); 118 | } 119 | } 120 | } 121 | bool Mesh::IsInside(const Vec3 & pt) const 122 | { 123 | const size_t nV = GetNPoints(); 124 | const size_t nT = GetNTriangles(); 125 | if (nV == 0 || nT == 0) 126 | { 127 | return false; 128 | } 129 | Vec3 ver0, ver1, ver2; 130 | double volume; 131 | for (int t = 0; t < nT; t++) 132 | { 133 | const Vec3 & tri = GetTriangle(t); 134 | ver0 = GetPoint(tri[0]); 135 | ver1 = GetPoint(tri[1]); 136 | ver2 = GetPoint(tri[2]); 137 | volume = ComputeVolume4(ver0, ver1, ver2, pt); 138 | if (volume < 0.0) 139 | { 140 | return false; 141 | } 142 | } 143 | return true; 144 | } 145 | double Mesh::ComputeDiagBB() 146 | { 147 | const size_t nPoints = GetNPoints(); 148 | if (nPoints == 0) return 0.0; 149 | Vec3< double > minBB = m_points[0]; 150 | Vec3< double > maxBB = m_points[0]; 151 | double x, y, z; 152 | for (size_t v = 1; v < nPoints; v++) 153 | { 154 | x = m_points[v][0]; 155 | y = m_points[v][1]; 156 | z = m_points[v][2]; 157 | if (x < minBB[0]) minBB[0] = x; 158 | else if (x > maxBB[0]) maxBB[0] = x; 159 | if (y < minBB[1]) minBB[1] = y; 160 | else if (y > maxBB[1]) maxBB[1] = y; 161 | if (z < minBB[2]) minBB[2] = z; 162 | else if (z > maxBB[2]) maxBB[2] = z; 163 | } 164 | return (m_diag = (maxBB - minBB).GetNorm()); 165 | } 166 | 167 | #ifdef VHACD_DEBUG_MESH 168 | bool Mesh::SaveVRML2(const std::string & fileName) const 169 | { 170 | std::ofstream fout(fileName.c_str()); 171 | if (fout.is_open()) 172 | { 173 | const Material material; 174 | 175 | if (SaveVRML2(fout, material)) 176 | { 177 | fout.close(); 178 | return true; 179 | } 180 | return false; 181 | } 182 | return false; 183 | } 184 | bool Mesh::SaveVRML2(std::ofstream & fout, const Material & material) const 185 | { 186 | if (fout.is_open()) 187 | { 188 | fout.setf(std::ios::fixed, std::ios::floatfield); 189 | fout.setf(std::ios::showpoint); 190 | fout.precision(6); 191 | size_t nV = m_points.Size(); 192 | size_t nT = m_triangles.Size(); 193 | fout << "#VRML V2.0 utf8" << std::endl; 194 | fout << "" << std::endl; 195 | fout << "# Vertices: " << nV << std::endl; 196 | fout << "# Triangles: " << nT << std::endl; 197 | fout << "" << std::endl; 198 | fout << "Group {" << std::endl; 199 | fout << " children [" << std::endl; 200 | fout << " Shape {" << std::endl; 201 | fout << " appearance Appearance {" << std::endl; 202 | fout << " material Material {" << std::endl; 203 | fout << " diffuseColor " << material.m_diffuseColor[0] << " " 204 | << material.m_diffuseColor[1] << " " 205 | << material.m_diffuseColor[2] << std::endl; 206 | fout << " ambientIntensity " << material.m_ambientIntensity << std::endl; 207 | fout << " specularColor " << material.m_specularColor[0] << " " 208 | << material.m_specularColor[1] << " " 209 | << material.m_specularColor[2] << std::endl; 210 | fout << " emissiveColor " << material.m_emissiveColor[0] << " " 211 | << material.m_emissiveColor[1] << " " 212 | << material.m_emissiveColor[2] << std::endl; 213 | fout << " shininess " << material.m_shininess << std::endl; 214 | fout << " transparency " << material.m_transparency << std::endl; 215 | fout << " }" << std::endl; 216 | fout << " }" << std::endl; 217 | fout << " geometry IndexedFaceSet {" << std::endl; 218 | fout << " ccw TRUE" << std::endl; 219 | fout << " solid TRUE" << std::endl; 220 | fout << " convex TRUE" << std::endl; 221 | if (nV > 0) 222 | { 223 | fout << " coord DEF co Coordinate {" << std::endl; 224 | fout << " point [" << std::endl; 225 | for (size_t v = 0; v < nV; v++) 226 | { 227 | fout << " " << m_points[v][0] << " " 228 | << m_points[v][1] << " " 229 | << m_points[v][2] << "," << std::endl; 230 | } 231 | fout << " ]" << std::endl; 232 | fout << " }" << std::endl; 233 | } 234 | if (nT > 0) 235 | { 236 | fout << " coordIndex [ " << std::endl; 237 | for (size_t f = 0; f < nT; f++) 238 | { 239 | fout << " " << m_triangles[f][0] << ", " 240 | << m_triangles[f][1] << ", " 241 | << m_triangles[f][2] << ", -1," << std::endl; 242 | } 243 | fout << " ]" << std::endl; 244 | } 245 | fout << " }" << std::endl; 246 | fout << " }" << std::endl; 247 | fout << " ]" << std::endl; 248 | fout << "}" << std::endl; 249 | return true; 250 | } 251 | return false; 252 | } 253 | bool Mesh::SaveOFF(const std::string & fileName) const 254 | { 255 | std::ofstream fout(fileName.c_str()); 256 | if (fout.is_open()) 257 | { 258 | size_t nV = m_points.Size(); 259 | size_t nT = m_triangles.Size(); 260 | fout << "OFF" << std::endl; 261 | fout << nV << " " << nT << " " << 0 << std::endl; 262 | for (size_t v = 0; v < nV; v++) 263 | { 264 | fout << m_points[v][0] << " " 265 | << m_points[v][1] << " " 266 | << m_points[v][2] << std::endl; 267 | } 268 | for (size_t f = 0; f < nT; f++) 269 | { 270 | fout << "3 " << m_triangles[f][0] << " " 271 | << m_triangles[f][1] << " " 272 | << m_triangles[f][2] << std::endl; 273 | } 274 | fout.close(); 275 | return true; 276 | } 277 | return false; 278 | } 279 | 280 | bool Mesh::LoadOFF(const std::string & fileName, bool invert) 281 | { 282 | FILE * fid = fopen(fileName.c_str(), "r"); 283 | if (fid) 284 | { 285 | const std::string strOFF("OFF"); 286 | char temp[1024]; 287 | fscanf(fid, "%s", temp); 288 | if (std::string(temp) != strOFF) 289 | { 290 | fclose(fid); 291 | return false; 292 | } 293 | else 294 | { 295 | int nv = 0; 296 | int nf = 0; 297 | int ne = 0; 298 | fscanf(fid, "%i", &nv); 299 | fscanf(fid, "%i", &nf); 300 | fscanf(fid, "%i", &ne); 301 | m_points.Resize(nv); 302 | m_triangles.Resize(nf); 303 | Vec3 coord; 304 | float x, y, z; 305 | for (int p = 0; p < nv; p++) 306 | { 307 | fscanf(fid, "%f", &x); 308 | fscanf(fid, "%f", &y); 309 | fscanf(fid, "%f", &z); 310 | m_points[p][0] = x; 311 | m_points[p][1] = y; 312 | m_points[p][2] = z; 313 | } 314 | int i, j, k, s; 315 | for (int t = 0; t < nf; ++t) { 316 | fscanf(fid, "%i", &s); 317 | if (s == 3) 318 | { 319 | fscanf(fid, "%i", &i); 320 | fscanf(fid, "%i", &j); 321 | fscanf(fid, "%i", &k); 322 | m_triangles[t][0] = i; 323 | if (invert) 324 | { 325 | m_triangles[t][1] = k; 326 | m_triangles[t][2] = j; 327 | } 328 | else 329 | { 330 | m_triangles[t][1] = j; 331 | m_triangles[t][2] = k; 332 | } 333 | } 334 | else // Fix me: support only triangular meshes 335 | { 336 | for (int h = 0; h < s; ++h) fscanf(fid, "%i", &s); 337 | } 338 | } 339 | fclose(fid); 340 | } 341 | } 342 | else 343 | { 344 | return false; 345 | } 346 | return true; 347 | } 348 | #endif // VHACD_DEBUG_MESH 349 | 350 | } 351 | -------------------------------------------------------------------------------- /src/HACD.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, Bo Zhou 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | class StdCallback : public VHACD::IVHACD::IUserCallback 52 | { 53 | public: 54 | StdCallback() 55 | { 56 | } 57 | ~StdCallback() 58 | { 59 | } 60 | 61 | void Update(const double overallProgress, 62 | const double stageProgress, 63 | const double operationProgress, 64 | const char * const stage, 65 | const char * const operation) 66 | { 67 | std::cout << std::setfill(' ') << std::setw(3) << (int)(overallProgress +0.5) << "% " 68 | << "[ " << stage << " " << std::setfill(' ') << std::setw(3) << (int)(stageProgress +0.5) << "% ] " 69 | << operation << " " << std::setfill(' ') << std::setw(3) << (int)(operationProgress+0.5) << "%" << std::endl; 70 | }; 71 | }; 72 | 73 | class StdLogger : public VHACD::IVHACD::IUserLogger 74 | { 75 | public: 76 | StdLogger() 77 | { 78 | } 79 | 80 | ~StdLogger() 81 | { 82 | } 83 | 84 | void Log(const char * const msg) 85 | { 86 | std::cout << msg; 87 | } 88 | }; 89 | 90 | class SOP_HACD : public SOP_Node 91 | { 92 | public: 93 | 94 | static PRM_Template myTemplateList[]; 95 | static OP_Node *myConstructor(OP_Network *net, const char *name, OP_Operator *op); 96 | 97 | SOP_HACD(OP_Network *net, const char *name, OP_Operator *op); 98 | 99 | virtual ~SOP_HACD(); 100 | 101 | protected: 102 | 103 | virtual OP_ERROR cookMySop(OP_Context &context); 104 | 105 | private: 106 | 107 | void evalParams(fpreal time); 108 | 109 | VHACD::IVHACD::Parameters myHacdParams; 110 | 111 | static cl_device_id myCLDeviceId; 112 | static VHACD::IVHACD *interfaceVHACD; 113 | static StdCallback myCallback; 114 | static StdLogger myLogger; 115 | }; 116 | 117 | cl_device_id SOP_HACD::myCLDeviceId = NULL; 118 | VHACD::IVHACD *SOP_HACD::interfaceVHACD = NULL; 119 | StdCallback SOP_HACD::myCallback; 120 | StdLogger SOP_HACD::myLogger; 121 | 122 | // 123 | static PRM_Name resolutionName("resolution", "Resolution"); 124 | static PRM_Default resolutionDefault(100000); 125 | 126 | static PRM_Name depthName("depth", "Depth"); 127 | static PRM_Default depthDefault(20); 128 | 129 | static PRM_Name concavityName("concavity", "Concavity"); 130 | static PRM_Default concavityDefault(0.001); 131 | 132 | static PRM_Name deltaName("delta", "Delta"); 133 | static PRM_Default deltaDefault(0.05); 134 | 135 | static PRM_Name planeDownsamplingName("planeDownsamping", "Plane Downsampling"); 136 | static PRM_Default planeDownsamplingDefault(4); 137 | 138 | static PRM_Name convexhullDownsamplingName("convexhullDownsampling", "Convex Hull Downsampling"); 139 | static PRM_Default convexhullDownsamplingDefault(4); 140 | 141 | static PRM_Name alphaName("alpha", "Alpha"); 142 | static PRM_Default alphaDefault(0.05); 143 | 144 | static PRM_Name betaName("beta", "Beta"); 145 | static PRM_Default betaDefault(0.05); 146 | 147 | static PRM_Name gammaName("gamma", "Gamma"); 148 | static PRM_Default gammaDefault(0.0005); 149 | 150 | static PRM_Name pcaName("pca", "PCA"); 151 | static PRM_Default pcaDefault(0); 152 | 153 | static PRM_Name modeName("mode", "Mode"); 154 | static PRM_Name modeChoices[] = 155 | { 156 | PRM_Name("voxel", "Voxel"), 157 | PRM_Name("tetrahedron", "Tetrahedron"), 158 | PRM_Name() 159 | }; 160 | static PRM_ChoiceList modeMenu(PRM_CHOICELIST_SINGLE, modeChoices); 161 | static PRM_Default modeDefault(0, "voxel"); 162 | 163 | static PRM_Name maxNumVerticesPerCHName("maxNumVerticesPerCH", "Max Num. Vertices Per Convex Hull"); 164 | static PRM_Default maxNumVerticesPerCHDefault(64); 165 | 166 | static PRM_Name minVolumePerChName("minVolumePerCh", "Min Volume Per Ch"); 167 | static PRM_Default minVolumePerChDefault(0.0001); 168 | 169 | static PRM_Name convexhullApproximationName("convexhullApproximation", "Convex Hull Approximation"); 170 | static PRM_Default convexhullApproximationDefault(true); 171 | 172 | PRM_Template SOP_HACD::myTemplateList[] = 173 | { 174 | PRM_Template(PRM_INT, PRM_Template::PRM_EXPORT_MED, 1, &resolutionName, &resolutionDefault), 175 | PRM_Template(PRM_INT, PRM_Template::PRM_EXPORT_MED, 1, &depthName, &depthDefault), 176 | PRM_Template(PRM_FLT, PRM_Template::PRM_EXPORT_MED, 1, &concavityName, &concavityDefault), 177 | PRM_Template(PRM_FLT, PRM_Template::PRM_EXPORT_MED, 1, &deltaName, &deltaDefault), 178 | PRM_Template(PRM_INT, PRM_Template::PRM_EXPORT_MED, 1, &planeDownsamplingName, &planeDownsamplingDefault), 179 | PRM_Template(PRM_INT, PRM_Template::PRM_EXPORT_MED, 1, &convexhullDownsamplingName, &convexhullDownsamplingDefault), 180 | PRM_Template(PRM_FLT, PRM_Template::PRM_EXPORT_MED, 1, &alphaName, &alphaDefault), 181 | PRM_Template(PRM_FLT, PRM_Template::PRM_EXPORT_MED, 1, &betaName, &betaDefault), 182 | PRM_Template(PRM_FLT, PRM_Template::PRM_EXPORT_MED, 1, &gammaName, &gammaDefault), 183 | PRM_Template(PRM_INT, PRM_Template::PRM_EXPORT_MED, 1, &pcaName, &pcaDefault), 184 | PRM_Template(PRM_ORD, PRM_Template::PRM_EXPORT_MED, &modeName, &modeDefault, &modeMenu), 185 | PRM_Template(PRM_INT, PRM_Template::PRM_EXPORT_MED, 1, &maxNumVerticesPerCHName, &maxNumVerticesPerCHDefault), 186 | PRM_Template(PRM_FLT, PRM_Template::PRM_EXPORT_MED, 1, &minVolumePerChName, &minVolumePerChDefault), 187 | PRM_Template(PRM_TOGGLE, PRM_Template::PRM_EXPORT_MED, &convexhullApproximationName, &convexhullApproximationDefault), 188 | PRM_Template() 189 | }; 190 | 191 | OP_Node * SOP_HACD::myConstructor(OP_Network *net, const char *name, OP_Operator *op) 192 | { 193 | return new SOP_HACD(net, name, op); 194 | } 195 | 196 | SOP_HACD::SOP_HACD(OP_Network *net, const char *name, OP_Operator *op) 197 | : 198 | SOP_Node(net, name, op), 199 | myHacdParams() 200 | { 201 | bool useOpenCL = false; 202 | #ifdef USE_OPENCL 203 | useOpenCL = true; 204 | #endif 205 | myHacdParams.m_logger = &myLogger; 206 | myHacdParams.m_callback = &myCallback; 207 | 208 | if (! interfaceVHACD ) 209 | { 210 | interfaceVHACD = VHACD::CreateVHACD(); 211 | if (useOpenCL) 212 | { 213 | if (! myCLDeviceId) 214 | { 215 | cl_platform_id platformIds[2] = {NULL, NULL}; 216 | cl_uint numPlatforms = 0; 217 | clGetPlatformIDs(2, platformIds, &numPlatforms); 218 | for (cl_uint i = 0; i < numPlatforms; ++ i) 219 | { 220 | char buf[2048]; 221 | memset(buf, '\0', 2048); 222 | clGetPlatformInfo(platformIds[i], CL_PLATFORM_NAME, 2048, buf, NULL); 223 | std::cout << "HACD : Found OpenCL platform " << i << " [" << buf << "]" << std::endl; 224 | } 225 | 226 | if (numPlatforms) 227 | { 228 | cl_uint numDevices = 0; 229 | for (cl_uint i = 0; i < numPlatforms; ++ i) 230 | { 231 | if (clGetDeviceIDs(platformIds[i], CL_DEVICE_TYPE_ALL, 1, &myCLDeviceId, &numDevices) == CL_SUCCESS) 232 | { 233 | std::cout << "HACD : Choosed platform " << i << std::endl; 234 | break; 235 | } 236 | } 237 | } 238 | } 239 | if (myCLDeviceId) 240 | { 241 | if (interfaceVHACD->OCLInit(&myCLDeviceId, &myLogger)) 242 | { 243 | myHacdParams.m_oclAcceleration = true; 244 | } 245 | } 246 | } 247 | } 248 | } 249 | 250 | SOP_HACD::~SOP_HACD() 251 | { 252 | } 253 | 254 | OP_ERROR SOP_HACD::cookMySop(OP_Context &context) 255 | { 256 | OP_AutoLockInputs inputs(this); 257 | if (inputs.lock(context) >= UT_ERROR_ABORT) 258 | return error(); 259 | 260 | // 261 | duplicateSource(0, context); 262 | 263 | std::vector pointVec; 264 | pointVec.reserve(gdp->getNumPoints() * 3); 265 | 266 | const GA_Attribute * attrP = gdp->getP(); 267 | const GA_Detail & detailP = attrP->getDetail(); 268 | const GA_Range rangeP = detailP.getPointRange(); 269 | 270 | UT_ValArray arrayP; 271 | detailP.getPos3AsArray(rangeP, arrayP); 272 | for (UT_ValArray::const_iterator itr = arrayP.begin(); itr != arrayP.end(); ++ itr) 273 | { 274 | pointVec.push_back(itr->x()); 275 | pointVec.push_back(itr->y()); 276 | pointVec.push_back(itr->z()); 277 | } 278 | 279 | // 280 | std::vector idxVec; 281 | idxVec.reserve(gdp->getNumPrimitives() * 3); 282 | 283 | GEO_Primitive * prim = NULL; 284 | GA_FOR_ALL_PRIMITIVES(gdp, prim) 285 | { 286 | const GA_Size vtxCount = prim->getVertexCount(); 287 | if (vtxCount != 3) 288 | { 289 | addError(SOP_MESSAGE, "Not triangulated"); 290 | return error(); 291 | } 292 | for (GA_Size i = 0; i < vtxCount; ++ i) 293 | { 294 | idxVec.push_back(prim->getPointOffset(i)); 295 | } 296 | } 297 | 298 | gdp->clear(); 299 | 300 | // 301 | evalParams(context.getTime()); 302 | 303 | bool success = interfaceVHACD->Compute(&pointVec[0], 3, pointVec.size() / 3, &idxVec[0], 3, idxVec.size() / 3, myHacdParams); 304 | if (success && interfaceVHACD->GetNConvexHulls()) 305 | { 306 | for (unsigned int i = 0; i < interfaceVHACD->GetNConvexHulls(); ++ i) 307 | { 308 | VHACD::IVHACD::ConvexHull ch; 309 | ch.m_nPoints = 0; 310 | ch.m_points = NULL; 311 | ch.m_nTriangles = 0; 312 | ch.m_triangles = NULL; 313 | interfaceVHACD->GetConvexHull(i, ch); 314 | if(! ch.m_nPoints || ! ch.m_nTriangles) 315 | { 316 | continue; 317 | } 318 | 319 | // 320 | UT_String pointGroupName; 321 | pointGroupName.sprintf("chPoints_%u", i); 322 | GA_PointGroup *pointsGroup = gdp->newPointGroup(pointGroupName); 323 | 324 | UT_String primGroupName; 325 | primGroupName.sprintf("chPrims_%u", i); 326 | GA_PrimitiveGroup *primsGroup = gdp->newPrimitiveGroup(primGroupName); 327 | 328 | std::vector pOffsets; 329 | pOffsets.reserve(ch.m_nPoints); 330 | for (unsigned int p = 0; p < ch.m_nPoints * 3; p += 3) 331 | { 332 | GA_Offset pOffset = gdp->appendPointOffset(); 333 | pOffsets.push_back(pOffset); 334 | const UT_Vector3 point(ch.m_points[p], ch.m_points[p + 1], ch.m_points[p + 2]); 335 | gdp->setPos3(pOffset, point); 336 | pointsGroup->addOffset(pOffset); 337 | } 338 | 339 | for (unsigned int t = 0; t < ch.m_nTriangles * 3; t += 3) 340 | { 341 | GEO_PrimPoly *tri = static_cast(gdp->appendPrimitive(GEO_PRIMPOLY)); 342 | tri->setSize(0); 343 | tri->appendVertex(pOffsets[ch.m_triangles[t + 0]]); 344 | tri->appendVertex(pOffsets[ch.m_triangles[t + 1]]); 345 | tri->appendVertex(pOffsets[ch.m_triangles[t + 2]]); 346 | tri->close(); 347 | primsGroup->add(tri); 348 | } 349 | } 350 | } 351 | else 352 | { 353 | addError(SOP_MESSAGE, "Computation failed"); 354 | } 355 | 356 | interfaceVHACD->Clean(); 357 | 358 | return error(); 359 | } 360 | 361 | void SOP_HACD::evalParams(fpreal time) 362 | { 363 | myHacdParams.m_resolution = evalInt(resolutionName.getToken(), 0, time); 364 | myHacdParams.m_depth = evalInt(depthName.getToken(), 0, time); 365 | myHacdParams.m_concavity = evalFloat(concavityName.getToken(), 0, time); 366 | myHacdParams.m_delta = evalFloat(deltaName.getToken(), 0, time); 367 | myHacdParams.m_planeDownsampling = evalInt(planeDownsamplingName.getToken(), 0, time); 368 | myHacdParams.m_convexhullDownsampling = evalInt(convexhullDownsamplingName.getToken(), 0, time); 369 | myHacdParams.m_alpha = evalFloat(alphaName.getToken(),0, time); 370 | myHacdParams.m_beta = evalFloat(betaName.getToken(), 0, time); 371 | myHacdParams.m_gamma = evalFloat(gammaName.getToken(), 0, time); 372 | myHacdParams.m_pca = evalInt(pcaName.getToken(), 0, time); 373 | myHacdParams.m_mode = evalInt(modeName.getToken(), 0, time); 374 | myHacdParams.m_maxNumVerticesPerCH = evalInt(maxNumVerticesPerCHName.getToken(), 0, time); 375 | myHacdParams.m_minVolumePerCH = evalFloat(minVolumePerChName.getToken(), 0, time); 376 | myHacdParams.m_convexhullApproximation = evalInt(convexhullApproximationName.getToken(), 0, time); 377 | } 378 | 379 | void newSopOperator(OP_OperatorTable *table) 380 | { 381 | table->addOperator(new OP_Operator("hacd", 382 | "HACD", 383 | SOP_HACD::myConstructor, 384 | SOP_HACD::myTemplateList, 385 | 1, 386 | 1, 387 | NULL, 388 | OP_FLAG_GENERATOR)); 389 | } 390 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/btScalar.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2009 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 | 16 | 17 | #ifndef BT_SCALAR_H 18 | #define BT_SCALAR_H 19 | 20 | #ifdef BT_MANAGED_CODE 21 | //Aligned data types not supported in managed code 22 | #pragma unmanaged 23 | #endif 24 | 25 | 26 | #include 27 | #include //size_t for MSVC 6.0 28 | #include 29 | 30 | /* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/ 31 | #define BT_BULLET_VERSION 279 32 | 33 | inline int btGetVersion() 34 | { 35 | return BT_BULLET_VERSION; 36 | } 37 | 38 | #if defined(DEBUG) || defined (_DEBUG) 39 | #define BT_DEBUG 40 | #endif 41 | 42 | 43 | #ifdef _WIN32 44 | 45 | #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) 46 | 47 | #define SIMD_FORCE_INLINE inline 48 | #define ATTRIBUTE_ALIGNED16(a) a 49 | #define ATTRIBUTE_ALIGNED64(a) a 50 | #define ATTRIBUTE_ALIGNED128(a) a 51 | #else 52 | //#define BT_HAS_ALIGNED_ALLOCATOR 53 | #pragma warning(disable : 4324) // disable padding warning 54 | // #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning. 55 | // #pragma warning(disable:4996) //Turn off warnings about deprecated C routines 56 | // #pragma warning(disable:4786) // Disable the "debug name too long" warning 57 | 58 | #define SIMD_FORCE_INLINE __forceinline 59 | #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a 60 | #define ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a 61 | #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a 62 | #ifdef _XBOX 63 | #define BT_USE_VMX128 64 | 65 | #include 66 | #define BT_HAVE_NATIVE_FSEL 67 | #define btFsel(a,b,c) __fsel((a),(b),(c)) 68 | #else 69 | 70 | #if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION)) 71 | #define BT_USE_SSE 72 | #include 73 | #endif 74 | 75 | #endif//_XBOX 76 | 77 | #endif //__MINGW32__ 78 | 79 | #include 80 | #ifdef BT_DEBUG 81 | #define btAssert assert 82 | #else 83 | #define btAssert(x) 84 | #endif 85 | //btFullAssert is optional, slows down a lot 86 | #define btFullAssert(x) 87 | 88 | #define btLikely(_c) _c 89 | #define btUnlikely(_c) _c 90 | 91 | #else 92 | 93 | #if defined (__CELLOS_LV2__) 94 | #define SIMD_FORCE_INLINE inline __attribute__((always_inline)) 95 | #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) 96 | #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) 97 | #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) 98 | #ifndef assert 99 | #include 100 | #endif 101 | #ifdef BT_DEBUG 102 | #ifdef __SPU__ 103 | #include 104 | #define printf spu_printf 105 | #define btAssert(x) {if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}} 106 | #else 107 | #define btAssert assert 108 | #endif 109 | 110 | #else 111 | #define btAssert(x) 112 | #endif 113 | //btFullAssert is optional, slows down a lot 114 | #define btFullAssert(x) 115 | 116 | #define btLikely(_c) _c 117 | #define btUnlikely(_c) _c 118 | 119 | #else 120 | 121 | #ifdef USE_LIBSPE2 122 | 123 | #define SIMD_FORCE_INLINE __inline 124 | #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) 125 | #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) 126 | #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) 127 | #ifndef assert 128 | #include 129 | #endif 130 | #ifdef BT_DEBUG 131 | #define btAssert assert 132 | #else 133 | #define btAssert(x) 134 | #endif 135 | //btFullAssert is optional, slows down a lot 136 | #define btFullAssert(x) 137 | 138 | 139 | #define btLikely(_c) __builtin_expect((_c), 1) 140 | #define btUnlikely(_c) __builtin_expect((_c), 0) 141 | 142 | 143 | #else 144 | //non-windows systems 145 | 146 | #if (defined (__APPLE__) && defined (__i386__) && (!defined (BT_USE_DOUBLE_PRECISION))) 147 | #define BT_USE_SSE 148 | #include 149 | 150 | #define SIMD_FORCE_INLINE inline 151 | ///@todo: check out alignment methods for other platforms/compilers 152 | #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) 153 | #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) 154 | #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) 155 | #ifndef assert 156 | #include 157 | #endif 158 | 159 | #if defined(DEBUG) || defined (_DEBUG) 160 | #define btAssert assert 161 | #else 162 | #define btAssert(x) 163 | #endif 164 | 165 | //btFullAssert is optional, slows down a lot 166 | #define btFullAssert(x) 167 | #define btLikely(_c) _c 168 | #define btUnlikely(_c) _c 169 | 170 | #else 171 | 172 | #define SIMD_FORCE_INLINE inline 173 | ///@todo: check out alignment methods for other platforms/compilers 174 | ///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) 175 | ///#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) 176 | ///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) 177 | #define ATTRIBUTE_ALIGNED16(a) a 178 | #define ATTRIBUTE_ALIGNED64(a) a 179 | #define ATTRIBUTE_ALIGNED128(a) a 180 | #ifndef assert 181 | #include 182 | #endif 183 | 184 | #if defined(DEBUG) || defined (_DEBUG) 185 | #define btAssert assert 186 | #else 187 | #define btAssert(x) 188 | #endif 189 | 190 | //btFullAssert is optional, slows down a lot 191 | #define btFullAssert(x) 192 | #define btLikely(_c) _c 193 | #define btUnlikely(_c) _c 194 | #endif //__APPLE__ 195 | 196 | #endif // LIBSPE2 197 | 198 | #endif //__CELLOS_LV2__ 199 | #endif 200 | 201 | 202 | ///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision. 203 | #if defined(BT_USE_DOUBLE_PRECISION) 204 | typedef double btScalar; 205 | //this number could be bigger in double precision 206 | #define BT_LARGE_FLOAT 1e30 207 | #else 208 | typedef float btScalar; 209 | //keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX 210 | #define BT_LARGE_FLOAT 1e18f 211 | #endif 212 | 213 | 214 | 215 | #define BT_DECLARE_ALIGNED_ALLOCATOR() \ 216 | SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ 217 | SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \ 218 | SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \ 219 | SIMD_FORCE_INLINE void operator delete(void*, void*) { } \ 220 | SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ 221 | SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \ 222 | SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \ 223 | SIMD_FORCE_INLINE void operator delete[](void*, void*) { } \ 224 | 225 | 226 | 227 | #if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS) 228 | 229 | SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); } 230 | SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); } 231 | SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); } 232 | SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); } 233 | SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); } 234 | SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { if (xbtScalar(1)) x=btScalar(1); return acos(x); } 235 | SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { if (xbtScalar(1)) x=btScalar(1); return asin(x); } 236 | SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); } 237 | SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); } 238 | SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); } 239 | SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); } 240 | SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); } 241 | SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmod(x,y); } 242 | 243 | #else 244 | 245 | SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) 246 | { 247 | #ifdef USE_APPROXIMATION 248 | double x, z, tempf; 249 | unsigned long *tfptr = ((unsigned long *)&tempf) + 1; 250 | 251 | tempf = y; 252 | *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */ 253 | x = tempf; 254 | z = y*btScalar(0.5); 255 | x = (btScalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */ 256 | x = (btScalar(1.5)*x)-(x*x)*(x*z); 257 | x = (btScalar(1.5)*x)-(x*x)*(x*z); 258 | x = (btScalar(1.5)*x)-(x*x)*(x*z); 259 | x = (btScalar(1.5)*x)-(x*x)*(x*z); 260 | return x*y; 261 | #else 262 | return sqrtf(y); 263 | #endif 264 | } 265 | SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); } 266 | SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } 267 | SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } 268 | SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } 269 | SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { 270 | if (xbtScalar(1)) 273 | x=btScalar(1); 274 | return acosf(x); 275 | } 276 | SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { 277 | if (xbtScalar(1)) 280 | x=btScalar(1); 281 | return asinf(x); 282 | } 283 | SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } 284 | SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } 285 | SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); } 286 | SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); } 287 | SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); } 288 | SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmodf(x,y); } 289 | 290 | #endif 291 | 292 | #define SIMD_2_PI btScalar(6.283185307179586232) 293 | #define SIMD_PI (SIMD_2_PI * btScalar(0.5)) 294 | #define SIMD_HALF_PI (SIMD_2_PI * btScalar(0.25)) 295 | #define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0)) 296 | #define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI) 297 | #define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490) 298 | 299 | #define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x)))) /* reciprocal square root */ 300 | 301 | 302 | #ifdef BT_USE_DOUBLE_PRECISION 303 | #define SIMD_EPSILON DBL_EPSILON 304 | #define SIMD_INFINITY DBL_MAX 305 | #else 306 | #define SIMD_EPSILON FLT_EPSILON 307 | #define SIMD_INFINITY FLT_MAX 308 | #endif 309 | 310 | SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x) 311 | { 312 | btScalar coeff_1 = SIMD_PI / 4.0f; 313 | btScalar coeff_2 = 3.0f * coeff_1; 314 | btScalar abs_y = btFabs(y); 315 | btScalar angle; 316 | if (x >= 0.0f) { 317 | btScalar r = (x - abs_y) / (x + abs_y); 318 | angle = coeff_1 - coeff_1 * r; 319 | } else { 320 | btScalar r = (x + abs_y) / (abs_y - x); 321 | angle = coeff_2 - coeff_1 * r; 322 | } 323 | return (y < 0.0f) ? -angle : angle; 324 | } 325 | 326 | SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; } 327 | 328 | SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps) { 329 | return (((a) <= eps) && !((a) < -eps)); 330 | } 331 | SIMD_FORCE_INLINE bool btGreaterEqual (btScalar a, btScalar eps) { 332 | return (!((a) <= eps)); 333 | } 334 | 335 | 336 | SIMD_FORCE_INLINE int btIsNegative(btScalar x) { 337 | return x < btScalar(0.0) ? 1 : 0; 338 | } 339 | 340 | SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; } 341 | SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; } 342 | 343 | #define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name 344 | 345 | #ifndef btFsel 346 | SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c) 347 | { 348 | return a >= 0 ? b : c; 349 | } 350 | #endif 351 | #define btFsels(a,b,c) (btScalar)btFsel(a,b,c) 352 | 353 | 354 | SIMD_FORCE_INLINE bool btMachineIsLittleEndian() 355 | { 356 | long int i = 1; 357 | const char *p = (const char *) &i; 358 | if (p[0] == 1) // Lowest address contains the least significant byte 359 | return true; 360 | else 361 | return false; 362 | } 363 | 364 | 365 | 366 | ///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360 367 | ///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html 368 | SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) 369 | { 370 | // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero 371 | // Rely on positive value or'ed with its negative having sign bit on 372 | // and zero value or'ed with its negative (which is still zero) having sign bit off 373 | // Use arithmetic shift right, shifting the sign bit through all 32 bits 374 | unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); 375 | unsigned testEqz = ~testNz; 376 | return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); 377 | } 378 | SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero) 379 | { 380 | unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); 381 | unsigned testEqz = ~testNz; 382 | return static_cast((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); 383 | } 384 | SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero) 385 | { 386 | #ifdef BT_HAVE_NATIVE_FSEL 387 | return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero); 388 | #else 389 | return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; 390 | #endif 391 | } 392 | 393 | template SIMD_FORCE_INLINE void btSwap(T& a, T& b) 394 | { 395 | T tmp = a; 396 | a = b; 397 | b = tmp; 398 | } 399 | 400 | 401 | //PCK: endian swapping functions 402 | SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val) 403 | { 404 | return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); 405 | } 406 | 407 | SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val) 408 | { 409 | return static_cast(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)); 410 | } 411 | 412 | SIMD_FORCE_INLINE unsigned btSwapEndian(int val) 413 | { 414 | return btSwapEndian((unsigned)val); 415 | } 416 | 417 | SIMD_FORCE_INLINE unsigned short btSwapEndian(short val) 418 | { 419 | return btSwapEndian((unsigned short) val); 420 | } 421 | 422 | ///btSwapFloat uses using char pointers to swap the endianness 423 | ////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values 424 | ///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754. 425 | ///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception. 426 | ///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you. 427 | ///so instead of returning a float/double, we return integer/long long integer 428 | SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d) 429 | { 430 | unsigned int a = 0; 431 | unsigned char *dst = (unsigned char *)&a; 432 | unsigned char *src = (unsigned char *)&d; 433 | 434 | dst[0] = src[3]; 435 | dst[1] = src[2]; 436 | dst[2] = src[1]; 437 | dst[3] = src[0]; 438 | return a; 439 | } 440 | 441 | // unswap using char pointers 442 | SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) 443 | { 444 | float d = 0.0f; 445 | unsigned char *src = (unsigned char *)&a; 446 | unsigned char *dst = (unsigned char *)&d; 447 | 448 | dst[0] = src[3]; 449 | dst[1] = src[2]; 450 | dst[2] = src[1]; 451 | dst[3] = src[0]; 452 | 453 | return d; 454 | } 455 | 456 | 457 | // swap using char pointers 458 | SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst) 459 | { 460 | unsigned char *src = (unsigned char *)&d; 461 | 462 | dst[0] = src[7]; 463 | dst[1] = src[6]; 464 | dst[2] = src[5]; 465 | dst[3] = src[4]; 466 | dst[4] = src[3]; 467 | dst[5] = src[2]; 468 | dst[6] = src[1]; 469 | dst[7] = src[0]; 470 | 471 | } 472 | 473 | // unswap using char pointers 474 | SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) 475 | { 476 | double d = 0.0; 477 | unsigned char *dst = (unsigned char *)&d; 478 | 479 | dst[0] = src[7]; 480 | dst[1] = src[6]; 481 | dst[2] = src[5]; 482 | dst[3] = src[4]; 483 | dst[4] = src[3]; 484 | dst[5] = src[2]; 485 | dst[6] = src[1]; 486 | dst[7] = src[0]; 487 | 488 | return d; 489 | } 490 | 491 | // returns normalized value in range [-SIMD_PI, SIMD_PI] 492 | SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians) 493 | { 494 | angleInRadians = btFmod(angleInRadians, SIMD_2_PI); 495 | if(angleInRadians < -SIMD_PI) 496 | { 497 | return angleInRadians + SIMD_2_PI; 498 | } 499 | else if(angleInRadians > SIMD_PI) 500 | { 501 | return angleInRadians - SIMD_2_PI; 502 | } 503 | else 504 | { 505 | return angleInRadians; 506 | } 507 | } 508 | 509 | ///rudimentary class to provide type info 510 | struct btTypedObject 511 | { 512 | btTypedObject(int objectType) 513 | :m_objectType(objectType) 514 | { 515 | } 516 | int m_objectType; 517 | inline int getObjectType() const 518 | { 519 | return m_objectType; 520 | } 521 | }; 522 | #endif //BT_SCALAR_H 523 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/vhacdVHACD.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com) 2 | All rights reserved. 3 | 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | */ 15 | #pragma once 16 | #ifndef VHACD_VHACD_H 17 | #define VHACD_VHACD_H 18 | 19 | #ifdef OPENCL_FOUND 20 | #ifdef __MACH__ 21 | #include 22 | #else 23 | #include 24 | #endif 25 | #endif //OPENCL_FOUND 26 | 27 | #include "vhacdMutex.h" 28 | 29 | #define USE_THREAD 1 30 | #define OCL_MIN_NUM_PRIMITIVES 4096 31 | #define CH_APP_MIN_NUM_PRIMITIVES 64000 32 | namespace VHACD 33 | { 34 | class VHACD : public IVHACD 35 | { 36 | public: 37 | //! Constructor. 38 | VHACD() 39 | { 40 | #if USE_THREAD == 1 && _OPENMP 41 | m_ompNumProcessors = 2*omp_get_num_procs(); 42 | omp_set_num_threads(m_ompNumProcessors); 43 | #else //USE_THREAD == 1 && _OPENMP 44 | m_ompNumProcessors = 1; 45 | #endif //USE_THREAD == 1 && _OPENMP 46 | #ifdef CL_VERSION_1_1 47 | m_oclWorkGroupSize = 0; 48 | m_oclDevice = 0; 49 | m_oclQueue = 0; 50 | m_oclKernelComputePartialVolumes = 0; 51 | m_oclKernelComputeSum = 0; 52 | #endif //CL_VERSION_1_1 53 | Init(); 54 | } 55 | //! Destructor. 56 | ~VHACD(void) {} 57 | unsigned int GetNConvexHulls() const 58 | { 59 | return (unsigned int)m_convexHulls.Size(); 60 | } 61 | void Cancel() 62 | { 63 | SetCancel(true); 64 | } 65 | void GetConvexHull(const unsigned int index, ConvexHull & ch) const 66 | { 67 | Mesh * mesh = m_convexHulls[index]; 68 | ch.m_nPoints = (unsigned int)mesh->GetNPoints(); 69 | ch.m_nTriangles = (unsigned int)mesh->GetNTriangles(); 70 | ch.m_points = mesh->GetPoints(); 71 | ch.m_triangles = mesh->GetTriangles(); 72 | } 73 | void Clean(void) 74 | { 75 | delete m_volume; 76 | delete m_pset; 77 | size_t nCH = m_convexHulls.Size(); 78 | for (size_t p = 0; p < nCH; ++p) 79 | { 80 | delete m_convexHulls[p]; 81 | } 82 | m_convexHulls.Clear(); 83 | Init(); 84 | } 85 | void Release(void) 86 | { 87 | delete this; 88 | } 89 | bool Compute(const float * const points, 90 | const unsigned int stridePoints, 91 | const unsigned int nPoints, 92 | const int * const triangles, 93 | const unsigned int strideTriangles, 94 | const unsigned int nTriangles, 95 | const Parameters & params); 96 | bool Compute(const double * const points, 97 | const unsigned int stridePoints, 98 | const unsigned int nPoints, 99 | const int * const triangles, 100 | const unsigned int strideTriangles, 101 | const unsigned int nTriangles, 102 | const Parameters & params); 103 | bool OCLInit(void * const oclDevice, 104 | IUserLogger * const logger = 0); 105 | bool OCLRelease(IUserLogger * const logger = 0); 106 | private: 107 | void SetCancel(bool cancel) 108 | { 109 | m_cancelMutex.Lock(); 110 | m_cancel = cancel; 111 | m_cancelMutex.Unlock(); 112 | } 113 | bool GetCancel() 114 | { 115 | 116 | m_cancelMutex.Lock(); 117 | bool cancel = m_cancel; 118 | m_cancelMutex.Unlock(); 119 | return cancel; 120 | } 121 | void Update(const double stageProgress, 122 | const double operationProgress, 123 | const Parameters & params) 124 | { 125 | m_stageProgress = stageProgress; 126 | m_operationProgress = operationProgress; 127 | if (params.m_callback) 128 | { 129 | params.m_callback->Update(m_overallProgress, 130 | m_stageProgress, 131 | m_operationProgress, 132 | m_stage.c_str(), 133 | m_operation.c_str()); 134 | } 135 | } 136 | void Init() 137 | { 138 | memset(m_rot, 0, sizeof(double) * 9); 139 | m_dim = 64; 140 | m_volume = 0; 141 | m_volumeCH0 = 0.0; 142 | m_pset = 0; 143 | m_overallProgress = 0.0; 144 | m_stageProgress = 0.0; 145 | m_operationProgress = 0.0; 146 | m_stage = ""; 147 | m_operation = ""; 148 | m_barycenter[0] = m_barycenter[1] = m_barycenter[2] = 0.0; 149 | m_rot[0][0] = m_rot[1][1] = m_rot[2][2] = 1.0; 150 | SetCancel(false); 151 | } 152 | void ComputePrimitiveSet(const Parameters & params); 153 | void ComputeACD(const Parameters & params); 154 | void MergeConvexHulls(const Parameters & params); 155 | void SimplifyConvexHulls(const Parameters & params); 156 | void ComputeBestClippingPlane(const PrimitiveSet * inputPSet, 157 | const double volume, 158 | const SArray< Plane > & planes, 159 | const Vec3 & preferredCuttingDirection, 160 | const double w, 161 | const double alpha, 162 | const double beta, 163 | const double delta, 164 | const int convexhullDownsampling, 165 | const double progress0, 166 | const double progress1, 167 | Plane & bestPlane, 168 | double & minConcavity, 169 | const Parameters & params); 170 | template 171 | void AlignMesh(const T * const points, 172 | const unsigned int stridePoints, 173 | const unsigned int nPoints, 174 | const int * const triangles, 175 | const unsigned int strideTriangles, 176 | const unsigned int nTriangles, 177 | const Parameters & params) 178 | { 179 | if (GetCancel() || !params.m_pca) 180 | { 181 | return; 182 | } 183 | m_timer.Tic(); 184 | 185 | m_stage = "Align mesh"; 186 | m_operation = "Voxelization"; 187 | 188 | std::ostringstream msg; 189 | if (params.m_logger) 190 | { 191 | msg << "+ " << m_stage << std::endl; 192 | params.m_logger->Log(msg.str().c_str()); 193 | } 194 | 195 | Update(0.0, 0.0, params); 196 | if (GetCancel()) 197 | { 198 | return; 199 | } 200 | m_dim = (size_t)(pow((double)params.m_resolution, 1.0 / 3.0) + 0.5); 201 | Volume volume; 202 | volume.Voxelize(points, stridePoints, nPoints, 203 | triangles, strideTriangles, nTriangles, 204 | m_dim, m_barycenter, m_rot); 205 | size_t n = volume.GetNPrimitivesOnSurf() + volume.GetNPrimitivesInsideSurf(); 206 | Update(50.0, 100.0, params); 207 | 208 | if (params.m_logger) 209 | { 210 | msg.str(""); 211 | msg << "\t dim = " << m_dim << "\t-> " << n << " voxels" << std::endl; 212 | params.m_logger->Log(msg.str().c_str()); 213 | } 214 | if (GetCancel()) 215 | { 216 | return; 217 | } 218 | m_operation = "PCA"; 219 | Update(50.0, 0.0, params); 220 | volume.AlignToPrincipalAxes(m_rot); 221 | m_overallProgress = 1.0; 222 | Update(100.0, 100.0, params); 223 | 224 | m_timer.Toc(); 225 | if (params.m_logger) 226 | { 227 | msg.str(""); 228 | msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl; 229 | params.m_logger->Log(msg.str().c_str()); 230 | } 231 | } 232 | template 233 | void VoxelizeMesh(const T * const points, 234 | const unsigned int stridePoints, 235 | const unsigned int nPoints, 236 | const int * const triangles, 237 | const unsigned int strideTriangles, 238 | const unsigned int nTriangles, 239 | const Parameters & params) 240 | { 241 | if (GetCancel()) 242 | { 243 | return; 244 | } 245 | 246 | m_timer.Tic(); 247 | m_stage = "Voxelization"; 248 | 249 | std::ostringstream msg; 250 | if (params.m_logger) 251 | { 252 | msg << "+ " << m_stage << std::endl; 253 | params.m_logger->Log(msg.str().c_str()); 254 | } 255 | 256 | delete m_volume; 257 | m_volume = 0; 258 | int iteration = 0; 259 | const int maxIteration = 5; 260 | double progress = 0.0; 261 | while (iteration++ < maxIteration && !m_cancel) 262 | { 263 | msg.str(""); 264 | msg << "Iteration " << iteration; 265 | m_operation = msg.str(); 266 | 267 | progress = iteration * 100.0 / maxIteration; 268 | Update(progress, 0.0, params); 269 | 270 | m_volume = new Volume; 271 | m_volume->Voxelize(points, stridePoints, nPoints, 272 | triangles, strideTriangles, nTriangles, 273 | m_dim, m_barycenter, m_rot); 274 | 275 | Update(progress, 100.0, params); 276 | 277 | size_t n = m_volume->GetNPrimitivesOnSurf() + m_volume->GetNPrimitivesInsideSurf(); 278 | if (params.m_logger) 279 | { 280 | msg.str(""); 281 | msg << "\t dim = " << m_dim << "\t-> " << n << " voxels" << std::endl; 282 | params.m_logger->Log(msg.str().c_str()); 283 | } 284 | 285 | double a = pow((double)(params.m_resolution) / n, 0.33); 286 | size_t dim_next = (size_t)(m_dim * a + 0.5); 287 | if (n < params.m_resolution && 288 | iteration < maxIteration && 289 | m_volume->GetNPrimitivesOnSurf() < params.m_resolution / 8 && 290 | m_dim != dim_next) 291 | { 292 | delete m_volume; 293 | m_volume = 0; 294 | m_dim = dim_next; 295 | } 296 | else 297 | { 298 | break; 299 | } 300 | } 301 | m_overallProgress = 10.0; 302 | Update(100.0, 100.0, params); 303 | 304 | m_timer.Toc(); 305 | if (params.m_logger) 306 | { 307 | msg.str(""); 308 | msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl; 309 | params.m_logger->Log(msg.str().c_str()); 310 | } 311 | } 312 | template 313 | bool ComputeACD(const T * const points, 314 | const unsigned int stridePoints, 315 | const unsigned int nPoints, 316 | const int * const triangles, 317 | const unsigned int strideTriangles, 318 | const unsigned int nTriangles, 319 | const Parameters & params) 320 | { 321 | Init(); 322 | if (params.m_oclAcceleration) 323 | { 324 | // build kernals 325 | } 326 | AlignMesh(points, stridePoints, nPoints, triangles, strideTriangles, nTriangles, params); 327 | VoxelizeMesh(points, stridePoints, nPoints, triangles, strideTriangles, nTriangles, params); 328 | ComputePrimitiveSet(params); 329 | ComputeACD(params); 330 | MergeConvexHulls(params); 331 | SimplifyConvexHulls(params); 332 | if (params.m_oclAcceleration) 333 | { 334 | // Release kernals 335 | } 336 | if (GetCancel()) 337 | { 338 | Clean(); 339 | return false; 340 | } 341 | return true; 342 | } 343 | 344 | 345 | private: 346 | SArray m_convexHulls; 347 | std::string m_stage; 348 | std::string m_operation; 349 | double m_overallProgress; 350 | double m_stageProgress; 351 | double m_operationProgress; 352 | double m_rot[3][3]; 353 | double m_volumeCH0; 354 | Vec3 m_barycenter; 355 | Timer m_timer; 356 | size_t m_dim; 357 | Volume * m_volume; 358 | PrimitiveSet * m_pset; 359 | Mutex m_cancelMutex; 360 | bool m_cancel; 361 | int m_ompNumProcessors; 362 | #ifdef CL_VERSION_1_1 363 | cl_device_id * m_oclDevice; 364 | cl_context m_oclContext; 365 | cl_program m_oclProgram; 366 | cl_command_queue * m_oclQueue; 367 | cl_kernel * m_oclKernelComputePartialVolumes; 368 | cl_kernel * m_oclKernelComputeSum; 369 | size_t m_oclWorkGroupSize; 370 | #endif //CL_VERSION_1_1 371 | }; 372 | } 373 | #endif // VHACD_VHACD_H 374 | 375 | -------------------------------------------------------------------------------- /lib/VHACD_Lib/inc/btVector3.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 | 17 | #ifndef BT_VECTOR3_H 18 | #define BT_VECTOR3_H 19 | 20 | 21 | #include "btScalar.h" 22 | #include "btMinMax.h" 23 | 24 | #ifdef BT_USE_DOUBLE_PRECISION 25 | #define btVector3Data btVector3DoubleData 26 | #define btVector3DataName "btVector3DoubleData" 27 | #else 28 | #define btVector3Data btVector3FloatData 29 | #define btVector3DataName "btVector3FloatData" 30 | #endif //BT_USE_DOUBLE_PRECISION 31 | 32 | 33 | 34 | 35 | /**@brief btVector3 can be used to represent 3D points and vectors. 36 | * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user 37 | * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers 38 | */ 39 | ATTRIBUTE_ALIGNED16(class) btVector3 40 | { 41 | public: 42 | 43 | #if defined (__SPU__) && defined (__CELLOS_LV2__) 44 | btScalar m_floats[4]; 45 | public: 46 | SIMD_FORCE_INLINE const vec_float4& get128() const 47 | { 48 | return *((const vec_float4*)&m_floats[0]); 49 | } 50 | public: 51 | #else //__CELLOS_LV2__ __SPU__ 52 | #ifdef BT_USE_SSE // _WIN32 53 | union { 54 | __m128 mVec128; 55 | btScalar m_floats[4]; 56 | }; 57 | SIMD_FORCE_INLINE __m128 get128() const 58 | { 59 | return mVec128; 60 | } 61 | SIMD_FORCE_INLINE void set128(__m128 v128) 62 | { 63 | mVec128 = v128; 64 | } 65 | #else 66 | btScalar m_floats[4]; 67 | #endif 68 | #endif //__CELLOS_LV2__ __SPU__ 69 | 70 | public: 71 | 72 | /**@brief No initialization constructor */ 73 | SIMD_FORCE_INLINE btVector3() {} 74 | 75 | 76 | 77 | /**@brief Constructor from scalars 78 | * @param x X value 79 | * @param y Y value 80 | * @param z Z value 81 | */ 82 | SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z) 83 | { 84 | m_floats[0] = x; 85 | m_floats[1] = y; 86 | m_floats[2] = z; 87 | m_floats[3] = btScalar(0.); 88 | } 89 | 90 | 91 | /**@brief Add a vector to this one 92 | * @param The vector to add to this one */ 93 | SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v) 94 | { 95 | 96 | m_floats[0] += v.m_floats[0]; m_floats[1] += v.m_floats[1];m_floats[2] += v.m_floats[2]; 97 | return *this; 98 | } 99 | 100 | 101 | /**@brief Subtract a vector from this one 102 | * @param The vector to subtract */ 103 | SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v) 104 | { 105 | m_floats[0] -= v.m_floats[0]; m_floats[1] -= v.m_floats[1];m_floats[2] -= v.m_floats[2]; 106 | return *this; 107 | } 108 | /**@brief Scale the vector 109 | * @param s Scale factor */ 110 | SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s) 111 | { 112 | m_floats[0] *= s; m_floats[1] *= s;m_floats[2] *= s; 113 | return *this; 114 | } 115 | 116 | /**@brief Inversely scale the vector 117 | * @param s Scale factor to divide by */ 118 | SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s) 119 | { 120 | btFullAssert(s != btScalar(0.0)); 121 | return *this *= btScalar(1.0) / s; 122 | } 123 | 124 | /**@brief Return the dot product 125 | * @param v The other vector in the dot product */ 126 | SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const 127 | { 128 | return m_floats[0] * v.m_floats[0] + m_floats[1] * v.m_floats[1] +m_floats[2] * v.m_floats[2]; 129 | } 130 | 131 | /**@brief Return the length of the vector squared */ 132 | SIMD_FORCE_INLINE btScalar length2() const 133 | { 134 | return dot(*this); 135 | } 136 | 137 | /**@brief Return the length of the vector */ 138 | SIMD_FORCE_INLINE btScalar length() const 139 | { 140 | return btSqrt(length2()); 141 | } 142 | 143 | /**@brief Return the distance squared between the ends of this and another vector 144 | * This is symantically treating the vector like a point */ 145 | SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const; 146 | 147 | /**@brief Return the distance between the ends of this and another vector 148 | * This is symantically treating the vector like a point */ 149 | SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const; 150 | 151 | SIMD_FORCE_INLINE btVector3& safeNormalize() 152 | { 153 | btVector3 absVec = this->absolute(); 154 | int maxIndex = absVec.maxAxis(); 155 | if (absVec[maxIndex]>0) 156 | { 157 | *this /= absVec[maxIndex]; 158 | return *this /= length(); 159 | } 160 | setValue(1,0,0); 161 | return *this; 162 | } 163 | 164 | /**@brief Normalize this vector 165 | * x^2 + y^2 + z^2 = 1 */ 166 | SIMD_FORCE_INLINE btVector3& normalize() 167 | { 168 | return *this /= length(); 169 | } 170 | 171 | /**@brief Return a normalized version of this vector */ 172 | SIMD_FORCE_INLINE btVector3 normalized() const; 173 | 174 | /**@brief Return a rotated version of this vector 175 | * @param wAxis The axis to rotate about 176 | * @param angle The angle to rotate by */ 177 | SIMD_FORCE_INLINE btVector3 rotate( const btVector3& wAxis, const btScalar angle ) const; 178 | 179 | /**@brief Return the angle between this and another vector 180 | * @param v The other vector */ 181 | SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const 182 | { 183 | btScalar s = btSqrt(length2() * v.length2()); 184 | btFullAssert(s != btScalar(0.0)); 185 | return btAcos(dot(v) / s); 186 | } 187 | /**@brief Return a vector will the absolute values of each element */ 188 | SIMD_FORCE_INLINE btVector3 absolute() const 189 | { 190 | return btVector3( 191 | btFabs(m_floats[0]), 192 | btFabs(m_floats[1]), 193 | btFabs(m_floats[2])); 194 | } 195 | /**@brief Return the cross product between this and another vector 196 | * @param v The other vector */ 197 | SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const 198 | { 199 | return btVector3( 200 | m_floats[1] * v.m_floats[2] -m_floats[2] * v.m_floats[1], 201 | m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2], 202 | m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]); 203 | } 204 | 205 | SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const 206 | { 207 | return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) + 208 | m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) + 209 | m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]); 210 | } 211 | 212 | /**@brief Return the axis with the smallest value 213 | * Note return values are 0,1,2 for x, y, or z */ 214 | SIMD_FORCE_INLINE int minAxis() const 215 | { 216 | return m_floats[0] < m_floats[1] ? (m_floats[0] return this, t=1 => return other) */ 249 | SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const 250 | { 251 | return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t, 252 | m_floats[1] + (v.m_floats[1] - m_floats[1]) * t, 253 | m_floats[2] + (v.m_floats[2] -m_floats[2]) * t); 254 | } 255 | 256 | /**@brief Elementwise multiply this vector by the other 257 | * @param v The other vector */ 258 | SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v) 259 | { 260 | m_floats[0] *= v.m_floats[0]; m_floats[1] *= v.m_floats[1];m_floats[2] *= v.m_floats[2]; 261 | return *this; 262 | } 263 | 264 | /**@brief Return the x value */ 265 | SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; } 266 | /**@brief Return the y value */ 267 | SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; } 268 | /**@brief Return the z value */ 269 | SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; } 270 | /**@brief Set the x value */ 271 | SIMD_FORCE_INLINE void setX(btScalar x) { m_floats[0] = x;}; 272 | /**@brief Set the y value */ 273 | SIMD_FORCE_INLINE void setY(btScalar y) { m_floats[1] = y;}; 274 | /**@brief Set the z value */ 275 | SIMD_FORCE_INLINE void setZ(btScalar z) {m_floats[2] = z;}; 276 | /**@brief Set the w value */ 277 | SIMD_FORCE_INLINE void setW(btScalar w) { m_floats[3] = w;}; 278 | /**@brief Return the x value */ 279 | SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; } 280 | /**@brief Return the y value */ 281 | SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; } 282 | /**@brief Return the z value */ 283 | SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; } 284 | /**@brief Return the w value */ 285 | SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; } 286 | 287 | //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; } 288 | //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; } 289 | ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons. 290 | SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; } 291 | SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; } 292 | 293 | SIMD_FORCE_INLINE bool operator==(const btVector3& other) const 294 | { 295 | return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0])); 296 | } 297 | 298 | SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const 299 | { 300 | return !(*this == other); 301 | } 302 | 303 | /**@brief Set each element to the max of the current values and the values of another btVector3 304 | * @param other The other btVector3 to compare with 305 | */ 306 | SIMD_FORCE_INLINE void setMax(const btVector3& other) 307 | { 308 | btSetMax(m_floats[0], other.m_floats[0]); 309 | btSetMax(m_floats[1], other.m_floats[1]); 310 | btSetMax(m_floats[2], other.m_floats[2]); 311 | btSetMax(m_floats[3], other.w()); 312 | } 313 | /**@brief Set each element to the min of the current values and the values of another btVector3 314 | * @param other The other btVector3 to compare with 315 | */ 316 | SIMD_FORCE_INLINE void setMin(const btVector3& other) 317 | { 318 | btSetMin(m_floats[0], other.m_floats[0]); 319 | btSetMin(m_floats[1], other.m_floats[1]); 320 | btSetMin(m_floats[2], other.m_floats[2]); 321 | btSetMin(m_floats[3], other.w()); 322 | } 323 | 324 | SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z) 325 | { 326 | m_floats[0]=x; 327 | m_floats[1]=y; 328 | m_floats[2]=z; 329 | m_floats[3] = btScalar(0.); 330 | } 331 | 332 | void getSkewSymmetricMatrix(btVector3* v0,btVector3* v1,btVector3* v2) const 333 | { 334 | v0->setValue(0. ,-z() ,y()); 335 | v1->setValue(z() ,0. ,-x()); 336 | v2->setValue(-y() ,x() ,0.); 337 | } 338 | 339 | void setZero() 340 | { 341 | setValue(btScalar(0.),btScalar(0.),btScalar(0.)); 342 | } 343 | 344 | SIMD_FORCE_INLINE bool isZero() const 345 | { 346 | return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0); 347 | } 348 | 349 | SIMD_FORCE_INLINE bool fuzzyZero() const 350 | { 351 | return length2() < SIMD_EPSILON; 352 | } 353 | 354 | SIMD_FORCE_INLINE void serialize(struct btVector3Data& dataOut) const; 355 | 356 | SIMD_FORCE_INLINE void deSerialize(const struct btVector3Data& dataIn); 357 | 358 | SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData& dataOut) const; 359 | 360 | SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn); 361 | 362 | SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData& dataOut) const; 363 | 364 | SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn); 365 | 366 | }; 367 | 368 | /**@brief Return the sum of two vectors (Point symantics)*/ 369 | SIMD_FORCE_INLINE btVector3 370 | operator+(const btVector3& v1, const btVector3& v2) 371 | { 372 | return btVector3(v1.m_floats[0] + v2.m_floats[0], v1.m_floats[1] + v2.m_floats[1], v1.m_floats[2] + v2.m_floats[2]); 373 | } 374 | 375 | /**@brief Return the elementwise product of two vectors */ 376 | SIMD_FORCE_INLINE btVector3 377 | operator*(const btVector3& v1, const btVector3& v2) 378 | { 379 | return btVector3(v1.m_floats[0] * v2.m_floats[0], v1.m_floats[1] * v2.m_floats[1], v1.m_floats[2] * v2.m_floats[2]); 380 | } 381 | 382 | /**@brief Return the difference between two vectors */ 383 | SIMD_FORCE_INLINE btVector3 384 | operator-(const btVector3& v1, const btVector3& v2) 385 | { 386 | return btVector3(v1.m_floats[0] - v2.m_floats[0], v1.m_floats[1] - v2.m_floats[1], v1.m_floats[2] - v2.m_floats[2]); 387 | } 388 | /**@brief Return the negative of the vector */ 389 | SIMD_FORCE_INLINE btVector3 390 | operator-(const btVector3& v) 391 | { 392 | return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]); 393 | } 394 | 395 | /**@brief Return the vector scaled by s */ 396 | SIMD_FORCE_INLINE btVector3 397 | operator*(const btVector3& v, const btScalar& s) 398 | { 399 | return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s); 400 | } 401 | 402 | /**@brief Return the vector scaled by s */ 403 | SIMD_FORCE_INLINE btVector3 404 | operator*(const btScalar& s, const btVector3& v) 405 | { 406 | return v * s; 407 | } 408 | 409 | /**@brief Return the vector inversely scaled by s */ 410 | SIMD_FORCE_INLINE btVector3 411 | operator/(const btVector3& v, const btScalar& s) 412 | { 413 | btFullAssert(s != btScalar(0.0)); 414 | return v * (btScalar(1.0) / s); 415 | } 416 | 417 | /**@brief Return the vector inversely scaled by s */ 418 | SIMD_FORCE_INLINE btVector3 419 | operator/(const btVector3& v1, const btVector3& v2) 420 | { 421 | return btVector3(v1.m_floats[0] / v2.m_floats[0],v1.m_floats[1] / v2.m_floats[1],v1.m_floats[2] / v2.m_floats[2]); 422 | } 423 | 424 | /**@brief Return the dot product between two vectors */ 425 | SIMD_FORCE_INLINE btScalar 426 | btDot(const btVector3& v1, const btVector3& v2) 427 | { 428 | return v1.dot(v2); 429 | } 430 | 431 | 432 | /**@brief Return the distance squared between two vectors */ 433 | SIMD_FORCE_INLINE btScalar 434 | btDistance2(const btVector3& v1, const btVector3& v2) 435 | { 436 | return v1.distance2(v2); 437 | } 438 | 439 | 440 | /**@brief Return the distance between two vectors */ 441 | SIMD_FORCE_INLINE btScalar 442 | btDistance(const btVector3& v1, const btVector3& v2) 443 | { 444 | return v1.distance(v2); 445 | } 446 | 447 | /**@brief Return the angle between two vectors */ 448 | SIMD_FORCE_INLINE btScalar 449 | btAngle(const btVector3& v1, const btVector3& v2) 450 | { 451 | return v1.angle(v2); 452 | } 453 | 454 | /**@brief Return the cross product of two vectors */ 455 | SIMD_FORCE_INLINE btVector3 456 | btCross(const btVector3& v1, const btVector3& v2) 457 | { 458 | return v1.cross(v2); 459 | } 460 | 461 | SIMD_FORCE_INLINE btScalar 462 | btTriple(const btVector3& v1, const btVector3& v2, const btVector3& v3) 463 | { 464 | return v1.triple(v2, v3); 465 | } 466 | 467 | /**@brief Return the linear interpolation between two vectors 468 | * @param v1 One vector 469 | * @param v2 The other vector 470 | * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */ 471 | SIMD_FORCE_INLINE btVector3 472 | lerp(const btVector3& v1, const btVector3& v2, const btScalar& t) 473 | { 474 | return v1.lerp(v2, t); 475 | } 476 | 477 | 478 | 479 | SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const 480 | { 481 | return (v - *this).length2(); 482 | } 483 | 484 | SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const 485 | { 486 | return (v - *this).length(); 487 | } 488 | 489 | SIMD_FORCE_INLINE btVector3 btVector3::normalized() const 490 | { 491 | return *this / length(); 492 | } 493 | 494 | SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar angle ) const 495 | { 496 | // wAxis must be a unit lenght vector 497 | 498 | btVector3 o = wAxis * wAxis.dot( *this ); 499 | btVector3 x = *this - o; 500 | btVector3 y; 501 | 502 | y = wAxis.cross( *this ); 503 | 504 | return ( o + x * btCos( angle ) + y * btSin( angle ) ); 505 | } 506 | 507 | class btVector4 : public btVector3 508 | { 509 | public: 510 | 511 | SIMD_FORCE_INLINE btVector4() {} 512 | 513 | 514 | SIMD_FORCE_INLINE btVector4(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) 515 | : btVector3(x,y,z) 516 | { 517 | m_floats[3] = w; 518 | } 519 | 520 | 521 | SIMD_FORCE_INLINE btVector4 absolute4() const 522 | { 523 | return btVector4( 524 | btFabs(m_floats[0]), 525 | btFabs(m_floats[1]), 526 | btFabs(m_floats[2]), 527 | btFabs(m_floats[3])); 528 | } 529 | 530 | 531 | 532 | btScalar getW() const { return m_floats[3];} 533 | 534 | 535 | SIMD_FORCE_INLINE int maxAxis4() const 536 | { 537 | int maxIndex = -1; 538 | btScalar maxVal = btScalar(-BT_LARGE_FLOAT); 539 | if (m_floats[0] > maxVal) 540 | { 541 | maxIndex = 0; 542 | maxVal = m_floats[0]; 543 | } 544 | if (m_floats[1] > maxVal) 545 | { 546 | maxIndex = 1; 547 | maxVal = m_floats[1]; 548 | } 549 | if (m_floats[2] > maxVal) 550 | { 551 | maxIndex = 2; 552 | maxVal =m_floats[2]; 553 | } 554 | if (m_floats[3] > maxVal) 555 | { 556 | maxIndex = 3; 557 | maxVal = m_floats[3]; 558 | } 559 | 560 | 561 | 562 | 563 | return maxIndex; 564 | 565 | } 566 | 567 | 568 | SIMD_FORCE_INLINE int minAxis4() const 569 | { 570 | int minIndex = -1; 571 | btScalar minVal = btScalar(BT_LARGE_FLOAT); 572 | if (m_floats[0] < minVal) 573 | { 574 | minIndex = 0; 575 | minVal = m_floats[0]; 576 | } 577 | if (m_floats[1] < minVal) 578 | { 579 | minIndex = 1; 580 | minVal = m_floats[1]; 581 | } 582 | if (m_floats[2] < minVal) 583 | { 584 | minIndex = 2; 585 | minVal =m_floats[2]; 586 | } 587 | if (m_floats[3] < minVal) 588 | { 589 | minIndex = 3; 590 | minVal = m_floats[3]; 591 | } 592 | 593 | return minIndex; 594 | 595 | } 596 | 597 | 598 | SIMD_FORCE_INLINE int closestAxis4() const 599 | { 600 | return absolute4().maxAxis4(); 601 | } 602 | 603 | 604 | 605 | 606 | /**@brief Set x,y,z and zero w 607 | * @param x Value of x 608 | * @param y Value of y 609 | * @param z Value of z 610 | */ 611 | 612 | 613 | /* void getValue(btScalar *m) const 614 | { 615 | m[0] = m_floats[0]; 616 | m[1] = m_floats[1]; 617 | m[2] =m_floats[2]; 618 | } 619 | */ 620 | /**@brief Set the values 621 | * @param x Value of x 622 | * @param y Value of y 623 | * @param z Value of z 624 | * @param w Value of w 625 | */ 626 | SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) 627 | { 628 | m_floats[0]=x; 629 | m_floats[1]=y; 630 | m_floats[2]=z; 631 | m_floats[3]=w; 632 | } 633 | 634 | 635 | }; 636 | 637 | 638 | ///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization 639 | SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal) 640 | { 641 | #ifdef BT_USE_DOUBLE_PRECISION 642 | unsigned char* dest = (unsigned char*) &destVal; 643 | unsigned char* src = (unsigned char*) &sourceVal; 644 | dest[0] = src[7]; 645 | dest[1] = src[6]; 646 | dest[2] = src[5]; 647 | dest[3] = src[4]; 648 | dest[4] = src[3]; 649 | dest[5] = src[2]; 650 | dest[6] = src[1]; 651 | dest[7] = src[0]; 652 | #else 653 | unsigned char* dest = (unsigned char*) &destVal; 654 | unsigned char* src = (unsigned char*) &sourceVal; 655 | dest[0] = src[3]; 656 | dest[1] = src[2]; 657 | dest[2] = src[1]; 658 | dest[3] = src[0]; 659 | #endif //BT_USE_DOUBLE_PRECISION 660 | } 661 | ///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization 662 | SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec) 663 | { 664 | for (int i=0;i<4;i++) 665 | { 666 | btSwapScalarEndian(sourceVec[i],destVec[i]); 667 | } 668 | 669 | } 670 | 671 | ///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization 672 | SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector) 673 | { 674 | 675 | btVector3 swappedVec; 676 | for (int i=0;i<4;i++) 677 | { 678 | btSwapScalarEndian(vector[i],swappedVec[i]); 679 | } 680 | vector = swappedVec; 681 | } 682 | 683 | template 684 | SIMD_FORCE_INLINE void btPlaneSpace1 (const T& n, T& p, T& q) 685 | { 686 | if (btFabs(n[2]) > SIMDSQRT12) { 687 | // choose p in y-z plane 688 | btScalar a = n[1]*n[1] + n[2]*n[2]; 689 | btScalar k = btRecipSqrt (a); 690 | p[0] = 0; 691 | p[1] = -n[2]*k; 692 | p[2] = n[1]*k; 693 | // set q = n x p 694 | q[0] = a*k; 695 | q[1] = -n[0]*p[2]; 696 | q[2] = n[0]*p[1]; 697 | } 698 | else { 699 | // choose p in x-y plane 700 | btScalar a = n[0]*n[0] + n[1]*n[1]; 701 | btScalar k = btRecipSqrt (a); 702 | p[0] = -n[1]*k; 703 | p[1] = n[0]*k; 704 | p[2] = 0; 705 | // set q = n x p 706 | q[0] = -n[2]*p[1]; 707 | q[1] = n[2]*p[0]; 708 | q[2] = a*k; 709 | } 710 | } 711 | 712 | 713 | struct btVector3FloatData 714 | { 715 | float m_floats[4]; 716 | }; 717 | 718 | struct btVector3DoubleData 719 | { 720 | double m_floats[4]; 721 | 722 | }; 723 | 724 | SIMD_FORCE_INLINE void btVector3::serializeFloat(struct btVector3FloatData& dataOut) const 725 | { 726 | ///could also do a memcpy, check if it is worth it 727 | for (int i=0;i<4;i++) 728 | dataOut.m_floats[i] = float(m_floats[i]); 729 | } 730 | 731 | SIMD_FORCE_INLINE void btVector3::deSerializeFloat(const struct btVector3FloatData& dataIn) 732 | { 733 | for (int i=0;i<4;i++) 734 | m_floats[i] = btScalar(dataIn.m_floats[i]); 735 | } 736 | 737 | 738 | SIMD_FORCE_INLINE void btVector3::serializeDouble(struct btVector3DoubleData& dataOut) const 739 | { 740 | ///could also do a memcpy, check if it is worth it 741 | for (int i=0;i<4;i++) 742 | dataOut.m_floats[i] = double(m_floats[i]); 743 | } 744 | 745 | SIMD_FORCE_INLINE void btVector3::deSerializeDouble(const struct btVector3DoubleData& dataIn) 746 | { 747 | for (int i=0;i<4;i++) 748 | m_floats[i] = btScalar(dataIn.m_floats[i]); 749 | } 750 | 751 | 752 | SIMD_FORCE_INLINE void btVector3::serialize(struct btVector3Data& dataOut) const 753 | { 754 | ///could also do a memcpy, check if it is worth it 755 | for (int i=0;i<4;i++) 756 | dataOut.m_floats[i] = m_floats[i]; 757 | } 758 | 759 | SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3Data& dataIn) 760 | { 761 | for (int i=0;i<4;i++) 762 | m_floats[i] = dataIn.m_floats[i]; 763 | } 764 | 765 | 766 | #endif //BT_VECTOR3_H 767 | --------------------------------------------------------------------------------