mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-07 22:40:44 +00:00
Merge pull request #826 from Ragora/adjustment-bullet-update
Adjustment: Update Bullet version to 3.24
This commit is contained in:
commit
62d808cc69
6148 changed files with 2112532 additions and 56873 deletions
7
Engine/lib/bullet/.ci/docker/env.list
Normal file
7
Engine/lib/bullet/.ci/docker/env.list
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
TRAVIS_OS_NAME
|
||||
TRAVIS_PULL_REQUEST
|
||||
|
||||
BUILD_NAME
|
||||
CC
|
||||
CXX
|
||||
SUDO
|
||||
19
Engine/lib/bullet/.ci/docker/ubuntu-bionic
Normal file
19
Engine/lib/bullet/.ci/docker/ubuntu-bionic
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
FROM ubuntu:bionic
|
||||
|
||||
RUN apt-get update -qq
|
||||
RUN apt-get install -y \
|
||||
build-essential \
|
||||
clang \
|
||||
cmake \
|
||||
curl \
|
||||
git \
|
||||
libgl-dev \
|
||||
libglu-dev \
|
||||
libpython3-dev \
|
||||
lsb-release \
|
||||
pkg-config \
|
||||
python3 \
|
||||
python3-dev \
|
||||
python3-distutils \
|
||||
software-properties-common \
|
||||
sudo
|
||||
18
Engine/lib/bullet/.ci/docker/ubuntu-xenial
Normal file
18
Engine/lib/bullet/.ci/docker/ubuntu-xenial
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
FROM ubuntu:xenial
|
||||
|
||||
RUN apt-get update -qq
|
||||
RUN apt-get install -y \
|
||||
build-essential \
|
||||
clang \
|
||||
cmake \
|
||||
curl \
|
||||
git \
|
||||
libgl-dev \
|
||||
libglu-dev \
|
||||
libpython3-dev \
|
||||
lsb-release \
|
||||
pkg-config \
|
||||
python3 \
|
||||
python3-dev \
|
||||
software-properties-common \
|
||||
sudo
|
||||
31
Engine/lib/bullet/.ci/script.sh
Executable file
31
Engine/lib/bullet/.ci/script.sh
Executable file
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env bash
|
||||
set -ex
|
||||
|
||||
echo "CXX="$CXX
|
||||
echo "CC="$CC
|
||||
if [[ "$TRAVIS_OS_NAME" == "linux" && "$CXX" = "g++" ]]; then
|
||||
$SUDO apt-get update
|
||||
$SUDO apt-get install -y python3
|
||||
$SUDO apt-get install -y python3-pip
|
||||
$SUDO apt-get install python3-dev
|
||||
$SUDO pip3 install -U wheel
|
||||
$SUDO pip3 install -U setuptools
|
||||
python3 setup.py install --user
|
||||
python3 examples/pybullet/unittests/unittests.py --verbose
|
||||
python3 examples/pybullet/unittests/userDataTest.py --verbose
|
||||
python3 examples/pybullet/unittests/saveRestoreStateTest.py --verbose
|
||||
fi
|
||||
cmake . -DBUILD_PYBULLET=ON -G"Unix Makefiles" #-DCMAKE_CXX_FLAGS=-Werror
|
||||
make -j8
|
||||
ctest -j8 --output-on-failure
|
||||
|
||||
# Build again with double precision
|
||||
cmake . -G "Unix Makefiles" -DUSE_DOUBLE_PRECISION=ON #-DCMAKE_CXX_FLAGS=-Werror
|
||||
make -j8
|
||||
ctest -j8 --output-on-failure
|
||||
|
||||
# Build again with shared libraries
|
||||
cmake . -G "Unix Makefiles" -DBUILD_SHARED_LIBS=ON
|
||||
make -j8
|
||||
ctest -j8 --output-on-failure
|
||||
$SUDO make install
|
||||
38
Engine/lib/bullet/.github/workflows/cmake.yml
vendored
Normal file
38
Engine/lib/bullet/.github/workflows/cmake.yml
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
name: CMake
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# The CMake configure and build commands are platform agnostic and should work equally
|
||||
# well on Windows or Mac. You can convert this to a matrix build if you need
|
||||
# cross-platform coverage.
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{github.workspace}}/build
|
||||
# Execute tests defined by the CMake configuration.
|
||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||
run: ctest -C ${{env.BUILD_TYPE}}
|
||||
|
||||
42
Engine/lib/bullet/.gitignore
vendored
Normal file
42
Engine/lib/bullet/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/bin
|
||||
/build3/gmake
|
||||
/build3/vs2010
|
||||
/build_cmake/
|
||||
|
||||
*.pyc
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# Pip
|
||||
pip-selfcheck.json
|
||||
*.whl
|
||||
*.egg
|
||||
*.egg-info
|
||||
|
||||
# Setuptools
|
||||
/build
|
||||
/dist
|
||||
*.eggs
|
||||
|
||||
# CMake
|
||||
CMakeFiles/
|
||||
CMakeCache.txt
|
||||
cmake_install.cmake
|
||||
CTestTestFile.cmake
|
||||
|
||||
# Visual Studio build files
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
*.sln
|
||||
|
||||
# Apple Finder metadata
|
||||
*.DS_Store
|
||||
|
||||
# vim temp files
|
||||
*.swp
|
||||
|
||||
.vscode/
|
||||
.idea/
|
||||
cmake-build-debug/
|
||||
5
Engine/lib/bullet/.style.yapf
Normal file
5
Engine/lib/bullet/.style.yapf
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
[style]
|
||||
based_on_style = google
|
||||
column_limit = 99
|
||||
indent_width = 2
|
||||
|
||||
|
|
@ -24,18 +24,22 @@ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
|||
#MESSAGE("CMAKE_CXX_FLAGS_DEBUG="+${CMAKE_CXX_FLAGS_DEBUG})
|
||||
|
||||
OPTION(USE_DOUBLE_PRECISION "Use double precision" OFF)
|
||||
SET(CLAMP_VELOCITIES "0" CACHE STRING "Clamp rigid bodies' velocity to this value, if larger than zero. Useful to prevent floating point errors or in general runaway velocities in complex scenarios")
|
||||
OPTION(USE_GRAPHICAL_BENCHMARK "Use Graphical Benchmark" ON)
|
||||
OPTION(BUILD_SHARED_LIBS "Use shared libraries" OFF)
|
||||
OPTION(USE_SOFT_BODY_MULTI_BODY_DYNAMICS_WORLD "Use btSoftMultiBodyDynamicsWorld" OFF)
|
||||
OPTION(USE_SOFT_BODY_MULTI_BODY_DYNAMICS_WORLD "Use btSoftMultiBodyDynamicsWorld" ON)
|
||||
OPTION(USE_OPENVR "Use OpenVR for virtual reality" OFF)
|
||||
|
||||
OPTION(BULLET2_USE_THREAD_LOCKS "Build Bullet 2 libraries with mutex locking around certain operations (required for multi-threading)" OFF)
|
||||
IF (BULLET2_USE_THREAD_LOCKS)
|
||||
OPTION(ENABLE_VHACD "Use VHACD in BulletRobotics and pybullet" ON)
|
||||
|
||||
OPTION(BULLET2_MULTITHREADING "Build Bullet 2 libraries with mutex locking around certain operations (required for multi-threading)" OFF)
|
||||
IF (BULLET2_MULTITHREADING)
|
||||
OPTION(BULLET2_USE_OPEN_MP_MULTITHREADING "Build Bullet 2 with support for multi-threading with OpenMP (requires a compiler with OpenMP support)" OFF)
|
||||
OPTION(BULLET2_USE_TBB_MULTITHREADING "Build Bullet 2 with support for multi-threading with Intel Threading Building Blocks (requires the TBB library to be already installed)" OFF)
|
||||
IF (MSVC)
|
||||
OPTION(BULLET2_USE_PPL_MULTITHREADING "Build Bullet 2 with support for multi-threading with Microsoft Parallel Patterns Library (requires MSVC compiler)" OFF)
|
||||
ENDIF (MSVC)
|
||||
ENDIF (BULLET2_USE_THREAD_LOCKS)
|
||||
ENDIF (BULLET2_MULTITHREADING)
|
||||
|
||||
|
||||
IF(NOT WIN32)
|
||||
|
|
@ -55,7 +59,6 @@ IF(NOT WIN32)
|
|||
ENDIF(NOT WIN32)
|
||||
|
||||
OPTION(USE_MSVC_INCREMENTAL_LINKING "Use MSVC Incremental Linking" OFF)
|
||||
OPTION(USE_CUSTOM_VECTOR_MATH "Use custom vectormath library" OFF)
|
||||
|
||||
#statically linking VC++ isn't supported for WindowsPhone/WindowsStore
|
||||
IF (CMAKE_SYSTEM_NAME STREQUAL WindowsPhone OR CMAKE_SYSTEM_NAME STREQUAL WindowsStore)
|
||||
|
|
@ -63,6 +66,7 @@ IF (CMAKE_SYSTEM_NAME STREQUAL WindowsPhone OR CMAKE_SYSTEM_NAME STREQUAL Window
|
|||
ELSE ()
|
||||
OPTION(USE_MSVC_RUNTIME_LIBRARY_DLL "Use MSVC Runtime Library DLL (/MD or /MDd)" OFF)
|
||||
ENDIF (CMAKE_SYSTEM_NAME STREQUAL WindowsPhone OR CMAKE_SYSTEM_NAME STREQUAL WindowsStore)
|
||||
OPTION(USE_MSVC_RELEASE_RUNTIME_ALWAYS "Use MSVC Release Runtime Library even in Debug" OFF)
|
||||
|
||||
#SET(CMAKE_EXE_LINKER_FLAGS_INIT "/STACK:10000000 /INCREMENTAL:NO")
|
||||
#SET(CMAKE_EXE_LINKER_FLAGS "/STACK:10000000 /INCREMENTAL:NO")
|
||||
|
|
@ -75,11 +79,11 @@ IF(MSVC)
|
|||
#MESSAGE("MSVC_INCREMENTAL_DEFAULT"+${MSVC_INCREMENTAL_DEFAULT})
|
||||
SET( MSVC_INCREMENTAL_YES_FLAG "/INCREMENTAL:NO")
|
||||
|
||||
STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags ${CMAKE_EXE_LINKER_FLAGS_DEBUG})
|
||||
STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags "${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "/INCREMENTAL:NO ${replacementFlags}" )
|
||||
MESSAGE("CMAKE_EXE_LINKER_FLAGS_DEBUG=${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
|
||||
|
||||
STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags2 ${CMAKE_EXE_LINKER_FLAGS})
|
||||
STRING(REPLACE "INCREMENTAL:YES" "INCREMENTAL:NO" replacementFlags2 "${CMAKE_EXE_LINKER_FLAGS}")
|
||||
|
||||
SET(CMAKE_EXE_LINKER_FLAGS ${replacementFlag2})
|
||||
STRING(REPLACE "INCREMENTAL:YES" "" replacementFlags3 "${CMAKE_EXTRA_LINK_FLAGS}")
|
||||
|
|
@ -94,7 +98,7 @@ IF(MSVC)
|
|||
ENDIF (NOT USE_MSVC_INCREMENTAL_LINKING)
|
||||
|
||||
IF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL)
|
||||
#We statically link to reduce dependancies
|
||||
#We statically link to reduce dependencies
|
||||
FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO )
|
||||
IF(${flag_var} MATCHES "/MD")
|
||||
STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||
|
|
@ -105,10 +109,25 @@ IF(MSVC)
|
|||
ENDFOREACH(flag_var)
|
||||
ENDIF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL)
|
||||
|
||||
IF (USE_MSVC_RELEASE_RUNTIME_ALWAYS)
|
||||
FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO )
|
||||
IF(${flag_var} MATCHES "/MDd")
|
||||
STRING(REGEX REPLACE "/MDd" "/MD" ${flag_var} "${${flag_var}}")
|
||||
ENDIF(${flag_var} MATCHES "/MDd")
|
||||
IF(${flag_var} MATCHES "/MTd")
|
||||
STRING(REGEX REPLACE "/MTd" "/MT" ${flag_var} "${${flag_var}}")
|
||||
ENDIF(${flag_var} MATCHES "/MTd")
|
||||
# Need to remove _DEBUG too otherwise things like _ITERATOR_DEBUG_LEVEL mismatch
|
||||
IF(${flag_var} MATCHES "-D_DEBUG")
|
||||
STRING(REGEX REPLACE "-D_DEBUG" "" ${flag_var} "${${flag_var}}")
|
||||
ENDIF(${flag_var} MATCHES "-D_DEBUG")
|
||||
ENDFOREACH(flag_var)
|
||||
ENDIF (USE_MSVC_RELEASE_RUNTIME_ALWAYS)
|
||||
|
||||
IF (CMAKE_CL_64)
|
||||
ADD_DEFINITIONS(-D_WIN64)
|
||||
ELSE()
|
||||
OPTION(USE_MSVC_SSE "Use MSVC /arch:sse option" ON)
|
||||
OPTION(USE_MSVC_SSE "Use MSVC /arch:sse option" OFF)
|
||||
option(USE_MSVC_SSE2 "Compile your program with SSE2 instructions" ON)
|
||||
|
||||
IF (USE_MSVC_SSE)
|
||||
|
|
@ -212,25 +231,33 @@ IF (INTERNAL_UPDATE_SERIALIZATION_STRUCTURES)
|
|||
ADD_DEFINITIONS( -DBT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES)
|
||||
ENDIF (INTERNAL_UPDATE_SERIALIZATION_STRUCTURES)
|
||||
|
||||
IF (CLAMP_VELOCITIES)
|
||||
ADD_DEFINITIONS( -DBT_CLAMP_VELOCITY_TO=${CLAMP_VELOCITIES})
|
||||
ENDIF (CLAMP_VELOCITIES)
|
||||
|
||||
IF (USE_DOUBLE_PRECISION)
|
||||
ADD_DEFINITIONS( -DBT_USE_DOUBLE_PRECISION)
|
||||
SET( BULLET_DOUBLE_DEF "-DBT_USE_DOUBLE_PRECISION")
|
||||
ENDIF (USE_DOUBLE_PRECISION)
|
||||
|
||||
IF (USE_SOFT_BODY_MULTI_BODY_DYNAMICS_WORLD)
|
||||
ADD_DEFINITIONS(-DUSE_SOFT_BODY_MULTI_BODY_DYNAMICS_WORLD)
|
||||
ENDIF (USE_SOFT_BODY_MULTI_BODY_DYNAMICS_WORLD)
|
||||
IF (NOT USE_SOFT_BODY_MULTI_BODY_DYNAMICS_WORLD)
|
||||
ADD_DEFINITIONS(-DSKIP_SOFT_BODY_MULTI_BODY_DYNAMICS_WORLD)
|
||||
ENDIF ()
|
||||
|
||||
IF(USE_GRAPHICAL_BENCHMARK)
|
||||
ADD_DEFINITIONS( -DUSE_GRAPHICAL_BENCHMARK)
|
||||
ENDIF (USE_GRAPHICAL_BENCHMARK)
|
||||
|
||||
IF(BULLET2_USE_THREAD_LOCKS)
|
||||
IF(BULLET2_MULTITHREADING)
|
||||
ADD_DEFINITIONS( -DBT_THREADSAFE=1 )
|
||||
IF (NOT MSVC)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
ENDIF (NOT MSVC)
|
||||
ENDIF (BULLET2_USE_THREAD_LOCKS)
|
||||
IF (NOT WIN32)
|
||||
FIND_PACKAGE(Threads)
|
||||
LINK_LIBRARIES( ${CMAKE_THREAD_LIBS_INIT} )
|
||||
ENDIF (NOT WIN32)
|
||||
ENDIF (BULLET2_MULTITHREADING)
|
||||
|
||||
IF (BULLET2_USE_OPEN_MP_MULTITHREADING)
|
||||
ADD_DEFINITIONS("-DBT_USE_OPENMP=1")
|
||||
|
|
@ -301,25 +328,26 @@ IF (APPLE)
|
|||
ENDIF()
|
||||
|
||||
OPTION(BUILD_BULLET3 "Set when you want to build Bullet 3" ON)
|
||||
|
||||
# Optional Python configuration
|
||||
# builds pybullet automatically if all the requirements are met
|
||||
SET(PYTHON_VERSION_PYBULLET "" CACHE STRING "Python version pybullet will use.")
|
||||
SET(Python_ADDITIONAL_VERSIONS 3 3.6 3.5 3.4 3.3 3.2 3.1 3.0 2.7 2.7.12 2.7.10 2.7.3 )
|
||||
SET_PROPERTY(CACHE PYTHON_VERSION_PYBULLET PROPERTY STRINGS ${Python_ADDITIONAL_VERSIONS})
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/build3/cmake ${CMAKE_MODULE_PATH})
|
||||
OPTION(EXACT_PYTHON_VERSION "Require Python and match PYTHON_VERSION_PYBULLET exactly, e.g. 2.7.12" OFF)
|
||||
IF(EXACT_PYTHON_VERSION)
|
||||
set(EXACT_PYTHON_VERSION_FLAG EXACT REQUIRED)
|
||||
ENDIF(EXACT_PYTHON_VERSION)
|
||||
# first find the python interpreter
|
||||
FIND_PACKAGE(PythonInterp ${PYTHON_VERSION_PYBULLET} ${EXACT_PYTHON_VERSION_FLAG})
|
||||
# python library should exactly match that of the interpreter
|
||||
FIND_PACKAGE(PythonLibs ${PYTHON_VERSION_STRING} EXACT)
|
||||
SET(DEFAULT_BUILD_PYBULLET OFF)
|
||||
IF(PYTHONLIBS_FOUND)
|
||||
SET(DEFAULT_BUILD_PYBULLET ON)
|
||||
ENDIF(PYTHONLIBS_FOUND)
|
||||
OPTION(BUILD_PYBULLET "Set when you want to build pybullet (Python bindings for Bullet)" ${DEFAULT_BUILD_PYBULLET})
|
||||
# Will not probe environment for Python configuration (which can abort the
|
||||
# build process) unless you explicitly turn on BUILD_PYBULLET.
|
||||
OPTION(BUILD_PYBULLET "Set when you want to build pybullet (Python bindings for Bullet)" OFF)
|
||||
IF(BUILD_PYBULLET)
|
||||
SET(PYTHON_VERSION_PYBULLET "" CACHE STRING "Python version pybullet will use.")
|
||||
SET(Python_ADDITIONAL_VERSIONS 3 3.6 3.5 3.4 3.3 3.2 3.1 3.0 2.7 2.7.12 2.7.10 2.7.3 )
|
||||
SET_PROPERTY(CACHE PYTHON_VERSION_PYBULLET PROPERTY STRINGS ${Python_ADDITIONAL_VERSIONS})
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/build3/cmake ${CMAKE_MODULE_PATH})
|
||||
OPTION(EXACT_PYTHON_VERSION "Require Python and match PYTHON_VERSION_PYBULLET exactly, e.g. 2.7.12" OFF)
|
||||
IF(EXACT_PYTHON_VERSION)
|
||||
set(EXACT_PYTHON_VERSION_FLAG EXACT REQUIRED)
|
||||
ENDIF(EXACT_PYTHON_VERSION)
|
||||
# first find the python interpreter
|
||||
FIND_PACKAGE(PythonInterp ${PYTHON_VERSION_PYBULLET} ${EXACT_PYTHON_VERSION_FLAG})
|
||||
# python library should exactly match that of the interpreter
|
||||
# the following can result in fatal error if you don't have the right python configuration
|
||||
FIND_PACKAGE(PythonLibs ${PYTHON_VERSION_STRING} EXACT)
|
||||
ENDIF(BUILD_PYBULLET)
|
||||
|
||||
OPTION(BUILD_ENET "Set when you want to build apps with enet UDP networking support" ON)
|
||||
OPTION(BUILD_CLSOCKET "Set when you want to build apps with enet TCP networking support" ON)
|
||||
|
|
@ -365,6 +393,13 @@ IF(BUILD_PYBULLET)
|
|||
|
||||
ENDIF(BUILD_PYBULLET)
|
||||
|
||||
IF(NOT WIN32 AND NOT APPLE)
|
||||
OPTION(BUILD_EGL "Build OpenGL/EGL" ON)
|
||||
IF(BUILD_EGL)
|
||||
ADD_DEFINITIONS(-DBT_USE_EGL)
|
||||
ENDIF(BUILD_EGL)
|
||||
ENDIF()
|
||||
|
||||
IF(BUILD_BULLET3)
|
||||
IF(APPLE)
|
||||
MESSAGE("Mac OSX Version is ${_CURRENT_OSX_VERSION}")
|
||||
|
|
@ -455,6 +490,7 @@ IF (BUILD_UNIT_TESTS)
|
|||
ENDIF()
|
||||
|
||||
set (BULLET_CONFIG_CMAKE_PATH lib${LIB_SUFFIX}/cmake/bullet )
|
||||
list (APPEND BULLET_DEFINITIONS ${BULLET_DOUBLE_DEF})
|
||||
list (APPEND BULLET_LIBRARIES LinearMath)
|
||||
list (APPEND BULLET_LIBRARIES Bullet3Common)
|
||||
list (APPEND BULLET_LIBRARIES BulletInverseDynamics)
|
||||
|
|
|
|||
317
Engine/lib/bullet/Extras/BulletRobotics/CMakeLists.txt
Normal file
317
Engine/lib/bullet/Extras/BulletRobotics/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples/SharedMemory
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/enet/include
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/clsocket/src
|
||||
)
|
||||
ADD_DEFINITIONS(-DSTATIC_LINK_SPD_PLUGIN)
|
||||
|
||||
|
||||
|
||||
SET(BulletRobotics_INCLUDES
|
||||
../../examples/CommonInterfaces/Common2dCanvasInterface.h
|
||||
../../examples/CommonInterfaces/CommonCallbacks.h
|
||||
../../examples/CommonInterfaces/CommonCameraInterface.h
|
||||
../../examples/CommonInterfaces/CommonExampleInterface.h
|
||||
../../examples/CommonInterfaces/CommonFileIOInterface.h
|
||||
../../examples/CommonInterfaces/CommonGraphicsAppInterface.h
|
||||
../../examples/CommonInterfaces/CommonGUIHelperInterface.h
|
||||
../../examples/CommonInterfaces/CommonMultiBodyBase.h
|
||||
../../examples/CommonInterfaces/CommonParameterInterface.h
|
||||
../../examples/CommonInterfaces/CommonRenderInterface.h
|
||||
../../examples/CommonInterfaces/CommonRigidBodyBase.h
|
||||
../../examples/CommonInterfaces/CommonWindowInterface.h
|
||||
|
||||
../../examples/OpenGLWindow/SimpleCamera.h
|
||||
|
||||
../../examples/TinyRenderer/geometry.h
|
||||
../../examples/TinyRenderer/model.h
|
||||
../../examples/TinyRenderer/tgaimage.h
|
||||
../../examples/TinyRenderer/our_gl.h
|
||||
../../examples/TinyRenderer/TinyRenderer.h
|
||||
|
||||
../../examples/SharedMemory/plugins/collisionFilterPlugin/collisionFilterPlugin.h
|
||||
../../examples/SharedMemory/plugins/pdControlPlugin/pdControlPlugin.h
|
||||
../../examples/SharedMemory/b3RobotSimulatorClientAPI_NoGUI.h
|
||||
../../examples/SharedMemory/b3RobotSimulatorClientAPI_NoDirect.h
|
||||
../../examples/SharedMemory/IKTrajectoryHelper.h
|
||||
../../examples/SharedMemory/plugins/tinyRendererPlugin/tinyRendererPlugin.h
|
||||
../../examples/SharedMemory/plugins/tinyRendererPlugin/TinyRendererVisualShapeConverter.h
|
||||
../../examples/SharedMemory/InProcessMemory.h
|
||||
../../examples/SharedMemory/PhysicsServer.h
|
||||
../../examples/SharedMemory/PhysicsClient.h
|
||||
../../examples/SharedMemory/PhysicsServerSharedMemory.h
|
||||
../../examples/SharedMemory/PhysicsDirect.h
|
||||
../../examples/SharedMemory/PhysicsDirectC_API.h
|
||||
../../examples/SharedMemory/PhysicsServerCommandProcessor.h
|
||||
../../examples/SharedMemory/b3PluginManager.h
|
||||
../../examples/SharedMemory/PhysicsClientSharedMemory.h
|
||||
../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h
|
||||
../../examples/SharedMemory/PhysicsClientC_API.h
|
||||
../../examples/SharedMemory/SharedMemoryPublic.h
|
||||
../../examples/SharedMemory/Win32SharedMemory.h
|
||||
../../examples/SharedMemory/PosixSharedMemory.h
|
||||
|
||||
../../examples/Utils/b3ResourcePath.h
|
||||
../../examples/Utils/RobotLoggingUtil.h
|
||||
../../examples/Utils/b3Clock.h
|
||||
../../examples/Utils/b3ResourcePath.h
|
||||
../../examples/Utils/ChromeTraceUtil.h
|
||||
../../examples/Utils/b3ERPCFMHelper.hpp
|
||||
../../examples/Utils/b3ReferenceFrameHelper.hpp
|
||||
|
||||
../../examples/ThirdPartyLibs/tinyxml2/tinyxml2.h
|
||||
../../examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.h
|
||||
../../examples/ThirdPartyLibs/stb_image/stb_image.h
|
||||
../../examples/ThirdPartyLibs/BussIK/Jacobian.h
|
||||
../../examples/ThirdPartyLibs/BussIK/LinearR2.h
|
||||
../../examples/ThirdPartyLibs/BussIK/LinearR3.h
|
||||
../../examples/ThirdPartyLibs/BussIK/LinearR4.h
|
||||
../../examples/ThirdPartyLibs/BussIK/MatrixRmn.h
|
||||
../../examples/ThirdPartyLibs/BussIK/Node.h
|
||||
../../examples/ThirdPartyLibs/BussIK/Tree.h
|
||||
../../examples/ThirdPartyLibs/BussIK/VectorRn.h
|
||||
|
||||
../../examples/Importers/ImportColladaDemo/LoadMeshFromCollada.h
|
||||
../../examples/Importers/ImportObjDemo/LoadMeshFromObj.h
|
||||
../../examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.h
|
||||
../../examples/Importers/ImportMJCFDemo/BulletMJCFImporter.h
|
||||
../../examples/Importers/ImportURDFDemo/BulletUrdfImporter.h
|
||||
../../examples/Importers/ImportURDFDemo/MyMultiBodyCreator.h
|
||||
../../examples/Importers/ImportURDFDemo/URDF2Bullet.h
|
||||
../../examples/Importers/ImportURDFDemo/UrdfParser.h
|
||||
../../examples/Importers/ImportURDFDemo/urdfStringSplit.h
|
||||
../../examples/Importers/ImportURDFDemo/URDFImporterInterface.h
|
||||
../../examples/Importers/ImportURDFDemo/URDFJointTypes.h
|
||||
../../examples/Importers/ImportURDFDemo/SDFAudioTypes.h
|
||||
../../examples/Importers/ImportURDFDemo/UrdfRenderingInterface.h
|
||||
../../examples/Importers/ImportURDFDemo/MultiBodyCreationInterface.h
|
||||
../../examples/Importers/ImportMeshUtility/b3ImportMeshUtility.h
|
||||
|
||||
../../examples/MultiThreading/b3PosixThreadSupport.h
|
||||
../../examples/MultiThreading/b3Win32ThreadSupport.h
|
||||
../../examples/MultiThreading/b3ThreadSupportInterface.h
|
||||
)
|
||||
|
||||
SET(BulletRobotics_SRCS ${BulletRobotics_INCLUDES}
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/SpAlg.cpp
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/SpAlg.h
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/Shape.cpp
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/Shape.h
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/RBDUtil.cpp
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/RBDUtil.h
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/RBDModel.cpp
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/RBDModel.h
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/MathUtil.cpp
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/MathUtil.h
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/KinTree.cpp
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/KinTree.h
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/BulletConversion.cpp
|
||||
../../examples/SharedMemory/plugins/stablePDPlugin/BulletConversion.h
|
||||
|
||||
../../examples/OpenGLWindow/SimpleCamera.cpp
|
||||
|
||||
../../examples/TinyRenderer/geometry.cpp
|
||||
../../examples/TinyRenderer/model.cpp
|
||||
../../examples/TinyRenderer/tgaimage.cpp
|
||||
../../examples/TinyRenderer/our_gl.cpp
|
||||
../../examples/TinyRenderer/TinyRenderer.cpp
|
||||
|
||||
../../examples/SharedMemory/plugins/collisionFilterPlugin/collisionFilterPlugin.cpp
|
||||
../../examples/SharedMemory/plugins/pdControlPlugin/pdControlPlugin.cpp
|
||||
../../examples/SharedMemory/b3RobotSimulatorClientAPI_NoGUI.cpp
|
||||
../../examples/SharedMemory/b3RobotSimulatorClientAPI_NoDirect.cpp
|
||||
../../examples/SharedMemory/IKTrajectoryHelper.cpp
|
||||
../../examples/SharedMemory/plugins/tinyRendererPlugin/tinyRendererPlugin.cpp
|
||||
../../examples/SharedMemory/plugins/tinyRendererPlugin/TinyRendererVisualShapeConverter.cpp
|
||||
../../examples/SharedMemory/InProcessMemory.cpp
|
||||
../../examples/SharedMemory/PhysicsClient.cpp
|
||||
../../examples/SharedMemory/PhysicsServer.cpp
|
||||
../../examples/SharedMemory/PhysicsServerSharedMemory.cpp
|
||||
../../examples/SharedMemory/PhysicsDirect.cpp
|
||||
../../examples/SharedMemory/PhysicsDirectC_API.cpp
|
||||
../../examples/SharedMemory/PhysicsServerCommandProcessor.cpp
|
||||
../../examples/SharedMemory/b3PluginManager.cpp
|
||||
../../examples/SharedMemory/PhysicsClientSharedMemory.cpp
|
||||
../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp
|
||||
../../examples/SharedMemory/PhysicsClientC_API.cpp
|
||||
../../examples/SharedMemory/Win32SharedMemory.cpp
|
||||
../../examples/SharedMemory/PosixSharedMemory.cpp
|
||||
|
||||
../../examples/Utils/b3ResourcePath.cpp
|
||||
../../examples/Utils/RobotLoggingUtil.cpp
|
||||
../../examples/Utils/b3Clock.cpp
|
||||
../../examples/Utils/b3ResourcePath.cpp
|
||||
../../examples/Utils/ChromeTraceUtil.cpp
|
||||
|
||||
../../examples/ThirdPartyLibs/tinyxml2/tinyxml2.cpp
|
||||
../../examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp
|
||||
../../examples/ThirdPartyLibs/stb_image/stb_image.cpp
|
||||
../../examples/ThirdPartyLibs/BussIK/Jacobian.cpp
|
||||
../../examples/ThirdPartyLibs/BussIK/LinearR2.cpp
|
||||
../../examples/ThirdPartyLibs/BussIK/LinearR3.cpp
|
||||
../../examples/ThirdPartyLibs/BussIK/LinearR4.cpp
|
||||
../../examples/ThirdPartyLibs/BussIK/MatrixRmn.cpp
|
||||
../../examples/ThirdPartyLibs/BussIK/Misc.cpp
|
||||
../../examples/ThirdPartyLibs/BussIK/Node.cpp
|
||||
../../examples/ThirdPartyLibs/BussIK/Tree.cpp
|
||||
../../examples/ThirdPartyLibs/BussIK/VectorRn.cpp
|
||||
|
||||
../../examples/Importers/ImportColladaDemo/LoadMeshFromCollada.cpp
|
||||
../../examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp
|
||||
../../examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp
|
||||
../../examples/Importers/ImportMJCFDemo/BulletMJCFImporter.cpp
|
||||
../../examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp
|
||||
../../examples/Importers/ImportURDFDemo/MyMultiBodyCreator.cpp
|
||||
../../examples/Importers/ImportURDFDemo/URDF2Bullet.cpp
|
||||
../../examples/Importers/ImportURDFDemo/UrdfParser.cpp
|
||||
../../examples/Importers/ImportURDFDemo/urdfStringSplit.cpp
|
||||
../../examples/Importers/ImportMeshUtility/b3ImportMeshUtility.cpp
|
||||
|
||||
../../examples/MultiThreading/b3PosixThreadSupport.cpp
|
||||
../../examples/MultiThreading/b3Win32ThreadSupport.cpp
|
||||
../../examples/MultiThreading/b3ThreadSupportInterface.cpp
|
||||
|
||||
|
||||
)
|
||||
|
||||
IF(ENABLE_VHACD)
|
||||
ADD_DEFINITIONS(-DBT_ENABLE_VHACD)
|
||||
SET(BulletRobotics_SRCS ${BulletRobotics_SRCS}
|
||||
../../Extras/VHACD/test/src/main_vhacd.cpp
|
||||
../../Extras/VHACD/src/VHACD.cpp
|
||||
../../Extras/VHACD/src/vhacdICHull.cpp
|
||||
../../Extras/VHACD/src/vhacdManifoldMesh.cpp
|
||||
../../Extras/VHACD/src/vhacdMesh.cpp
|
||||
../../Extras/VHACD/src/vhacdVolume.cpp
|
||||
)
|
||||
INCLUDE_DIRECTORIES(
|
||||
../../Extras/VHACD/inc
|
||||
../../Extras/VHACD/public
|
||||
)
|
||||
ENDIF(ENABLE_VHACD)
|
||||
|
||||
IF(BUILD_CLSOCKET)
|
||||
ADD_DEFINITIONS(-DBT_ENABLE_CLSOCKET)
|
||||
ENDIF(BUILD_CLSOCKET)
|
||||
|
||||
IF(WIN32)
|
||||
IF(BUILD_ENET)
|
||||
ADD_DEFINITIONS(-DWIN32 -DBT_ENABLE_ENET)
|
||||
ENDIF(BUILD_ENET)
|
||||
IF(BUILD_CLSOCKET)
|
||||
ADD_DEFINITIONS(-DWIN32)
|
||||
ENDIF(BUILD_CLSOCKET)
|
||||
|
||||
ELSE(WIN32)
|
||||
IF(BUILD_ENET)
|
||||
ADD_DEFINITIONS(-DHAS_SOCKLEN_T -DBT_ENABLE_ENET)
|
||||
ENDIF(BUILD_ENET)
|
||||
|
||||
IF(BUILD_CLSOCKET)
|
||||
ADD_DEFINITIONS(${OSDEF})
|
||||
ENDIF(BUILD_CLSOCKET)
|
||||
|
||||
IF(NOT APPLE)
|
||||
FIND_PACKAGE(Threads)
|
||||
LINK_LIBRARIES( ${CMAKE_THREAD_LIBS_INIT} ${DL} )
|
||||
ENDIF(NOT APPLE)
|
||||
ENDIF(WIN32)
|
||||
|
||||
IF(BUILD_ENET)
|
||||
set(BulletRobotics_ENET_INCLUDES
|
||||
../../examples/SharedMemory/PhysicsClientUDP.h
|
||||
../../examples/SharedMemory/PhysicsClientUDP_C_API.h
|
||||
../../examples/ThirdPartyLibs/enet/include/enet/win32.h
|
||||
../../examples/ThirdPartyLibs/enet/include/enet/unix.h
|
||||
../../examples/ThirdPartyLibs/enet/include/enet/callbacks.h
|
||||
../../examples/ThirdPartyLibs/enet/include/enet/list.h
|
||||
../../examples/ThirdPartyLibs/enet/include/enet/protocol.h
|
||||
)
|
||||
set(BulletRobotics_ENET_SRCS
|
||||
../../examples/SharedMemory/PhysicsClientUDP.cpp
|
||||
../../examples/SharedMemory/PhysicsClientUDP_C_API.cpp
|
||||
../../examples/ThirdPartyLibs/enet/win32.c
|
||||
../../examples/ThirdPartyLibs/enet/unix.c
|
||||
../../examples/ThirdPartyLibs/enet/callbacks.c
|
||||
../../examples/ThirdPartyLibs/enet/compress.c
|
||||
../../examples/ThirdPartyLibs/enet/host.c
|
||||
../../examples/ThirdPartyLibs/enet/list.c
|
||||
../../examples/ThirdPartyLibs/enet/packet.c
|
||||
../../examples/ThirdPartyLibs/enet/peer.c
|
||||
../../examples/ThirdPartyLibs/enet/protocol.c
|
||||
)
|
||||
|
||||
set(BulletRobotics_INCLUDES
|
||||
${BulletRobotics_INCLUDES}
|
||||
${BulletRobotics_ENET_INCLUDES}
|
||||
)
|
||||
|
||||
set(BulletRobotics_SRCS
|
||||
${BulletRobotics_SRCS}
|
||||
${BulletRobotics_ENET_INCLUDES}
|
||||
${BulletRobotics_ENET_SRCS}
|
||||
)
|
||||
|
||||
ENDIF(BUILD_ENET)
|
||||
|
||||
IF(BUILD_CLSOCKET)
|
||||
set(BulletRobotics_CLSOCKET_SRCS
|
||||
../../examples/SharedMemory/PhysicsClientTCP.cpp
|
||||
../../examples/SharedMemory/PhysicsClientTCP_C_API.cpp
|
||||
../../examples/ThirdPartyLibs/clsocket/src/SimpleSocket.cpp
|
||||
../../examples/ThirdPartyLibs/clsocket/src/ActiveSocket.cpp
|
||||
../../examples/ThirdPartyLibs/clsocket/src/PassiveSocket.cpp
|
||||
)
|
||||
|
||||
set(BulletRobotics_SRCS
|
||||
${BulletRobotics_SRCS}
|
||||
${BulletRobotics_CLSOCKET_SRCS}
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
ADD_DEFINITIONS(-DPHYSICS_SERVER_DIRECT)
|
||||
|
||||
|
||||
ADD_LIBRARY(BulletRobotics ${BulletRobotics_SRCS})
|
||||
|
||||
SET_TARGET_PROPERTIES(BulletRobotics PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(BulletRobotics PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
TARGET_LINK_LIBRARIES(BulletRobotics BulletInverseDynamicsUtils BulletWorldImporter BulletFileLoader BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamics LinearMath Bullet3Common)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
|
||||
|
||||
INSTALL (
|
||||
DIRECTORY ${CMAKE_SOURCE_DIR}/examples/
|
||||
DESTINATION include/bullet
|
||||
FILES_MATCHING PATTERN "*.h*")
|
||||
|
||||
INSTALL(TARGETS
|
||||
BulletRobotics
|
||||
LIBRARY DESTINATION lib${LIB_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LIB_SUFFIX}
|
||||
)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(BulletRobotics PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(BulletRobotics PROPERTIES PUBLIC_HEADER "PhysicsClientC_API.h" )
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
|
||||
IF(NOT MSVC)
|
||||
SET(PKGCONFIG_INSTALL_PREFIX "lib${LIB_SUFFIX}/pkgconfig/" CACHE STRING "Base directory for pkgconfig files")
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/bullet_robotics.pc.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/bullet_robotics.pc @ONLY)
|
||||
INSTALL(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/bullet_robotics.pc
|
||||
DESTINATION
|
||||
${PKGCONFIG_INSTALL_PREFIX}
|
||||
)
|
||||
ENDIF(NOT MSVC)
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
Name: bullet_robotics
|
||||
Description: Bullet extras that include several utilities for robotics including a urdf parser
|
||||
Requires: bullet
|
||||
Version: @BULLET_VERSION@
|
||||
Libs: -L@CMAKE_INSTALL_PREFIX@/@LIB_DESTINATION@ -lBulletRobotics
|
||||
Cflags: @BULLET_DOUBLE_DEF@ -I@CMAKE_INSTALL_PREFIX@/@INCLUDE_INSTALL_DIR@ -I@CMAKE_INSTALL_PREFIX@/include/bullet_robotics
|
||||
183
Engine/lib/bullet/Extras/BulletRobotics/premake4.lua
Normal file
183
Engine/lib/bullet/Extras/BulletRobotics/premake4.lua
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
|
||||
|
||||
project ("BulletRobotics")
|
||||
language "C++"
|
||||
kind "StaticLib"
|
||||
|
||||
includedirs {"../../src", "../../examples",
|
||||
"../../examples/ThirdPartyLibs"}
|
||||
defines {"PHYSICS_IN_PROCESS_EXAMPLE_BROWSER"}
|
||||
hasCL = findOpenCL("clew")
|
||||
|
||||
links{"BulletExampleBrowserLib","gwen", "BulletFileLoader","BulletWorldImporter","OpenGL_Window","BulletSoftBody", "BulletInverseDynamicsUtils", "BulletInverseDynamics", "BulletDynamics","BulletCollision","LinearMath","BussIK", "Bullet3Common"}
|
||||
initOpenGL()
|
||||
initGlew()
|
||||
|
||||
includedirs {
|
||||
"../../src",
|
||||
"../../examples",
|
||||
"../../examples/SharedMemory",
|
||||
"../ThirdPartyLibs",
|
||||
"../ThirdPartyLibs/enet/include",
|
||||
"../ThirdPartyLibs/clsocket/src",
|
||||
}
|
||||
|
||||
if os.is("MacOSX") then
|
||||
-- targetextension {"so"}
|
||||
links{"Cocoa.framework","Python"}
|
||||
end
|
||||
|
||||
|
||||
if not _OPTIONS["no-enet"] then
|
||||
|
||||
includedirs {"../../examples/ThirdPartyLibs/enet/include"}
|
||||
|
||||
if os.is("Windows") then
|
||||
-- targetextension {"dylib"}
|
||||
defines { "WIN32" }
|
||||
links {"Ws2_32","Winmm"}
|
||||
end
|
||||
if os.is("Linux") then
|
||||
end
|
||||
if os.is("MacOSX") then
|
||||
end
|
||||
|
||||
links {"enet"}
|
||||
|
||||
files {
|
||||
"../../examples/SharedMemory/PhysicsClientUDP.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientUDP.h",
|
||||
"../../examples/SharedMemory/PhysicsClientUDP_C_API.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientUDP_C_API.h",
|
||||
}
|
||||
defines {"BT_ENABLE_ENET"}
|
||||
end
|
||||
|
||||
if not _OPTIONS["no-clsocket"] then
|
||||
|
||||
includedirs {"../../examples/ThirdPartyLibs/clsocket/src"}
|
||||
|
||||
if os.is("Windows") then
|
||||
defines { "WIN32" }
|
||||
links {"Ws2_32","Winmm"}
|
||||
end
|
||||
if os.is("Linux") then
|
||||
defines {"_LINUX"}
|
||||
end
|
||||
if os.is("MacOSX") then
|
||||
defines {"_DARWIN"}
|
||||
end
|
||||
|
||||
links {"clsocket"}
|
||||
|
||||
files {
|
||||
"../../examples/SharedMemory/RemoteGUIHelperTCP.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientTCP.cpp",
|
||||
"../../examples/SharedMemory/GraphicsServerExample.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientTCP.h",
|
||||
"../../examples/SharedMemory/PhysicsClientTCP_C_API.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientTCP_C_API.h",
|
||||
}
|
||||
defines {"BT_ENABLE_CLSOCKET"}
|
||||
end
|
||||
|
||||
|
||||
files {
|
||||
"../../examples/SharedMemory/plugins/collisionFilterPlugin/collisionFilterPlugin.cpp",
|
||||
"../../examples/SharedMemory/plugins/pdControlPlugin/pdControlPlugin.cpp",
|
||||
"../../examples/SharedMemory/plugins/pdControlPlugin/pdControlPlugin.h",
|
||||
"../../examples/SharedMemory/b3RobotSimulatorClientAPI_NoGUI.cpp",
|
||||
"../../examples/SharedMemory/b3RobotSimulatorClientAPI_NoGUI.h",
|
||||
"../../examples/SharedMemory/b3RobotSimulatorClientAPI_NoDirect.cpp",
|
||||
"../../examples/SharedMemory/b3RobotSimulatorClientAPI_NoDirect.h",
|
||||
"../../examples/SharedMemory/IKTrajectoryHelper.cpp",
|
||||
"../../examples/SharedMemory/IKTrajectoryHelper.h",
|
||||
"../../examples/SharedMemory/plugins/tinyRendererPlugin/tinyRendererPlugin.cpp",
|
||||
"../../examples/SharedMemory/plugins/tinyRendererPlugin/TinyRendererVisualShapeConverter.cpp",
|
||||
"../../examples/SharedMemory/RemoteGUIHelper.cpp",
|
||||
"../../examples/OpenGLWindow/SimpleCamera.cpp",
|
||||
"../../examples/OpenGLWindow/SimpleCamera.h",
|
||||
"../../examples/TinyRenderer/geometry.cpp",
|
||||
"../../examples/TinyRenderer/model.cpp",
|
||||
"../../examples/TinyRenderer/tgaimage.cpp",
|
||||
"../../examples/TinyRenderer/our_gl.cpp",
|
||||
"../../examples/TinyRenderer/TinyRenderer.cpp",
|
||||
"../../examples/SharedMemory/InProcessMemory.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClient.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClient.h",
|
||||
"../../examples/SharedMemory/PhysicsServer.cpp",
|
||||
"../../examples/SharedMemory/PhysicsServer.h",
|
||||
"../../examples/SharedMemory/PhysicsServerSharedMemory.cpp",
|
||||
"../../examples/SharedMemory/PhysicsServerSharedMemory.h",
|
||||
"../../examples/SharedMemory/PhysicsDirect.cpp",
|
||||
"../../examples/SharedMemory/PhysicsDirect.h",
|
||||
"../../examples/SharedMemory/PhysicsDirectC_API.cpp",
|
||||
"../../examples/SharedMemory/PhysicsDirectC_API.h",
|
||||
"../../examples/SharedMemory/PhysicsServerCommandProcessor.cpp",
|
||||
"../../examples/SharedMemory/PhysicsServerCommandProcessor.h",
|
||||
"../../examples/SharedMemory/b3PluginManager.cpp",
|
||||
"../../examples/SharedMemory/b3PluginManager.h",
|
||||
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory.h",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp",
|
||||
"../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h",
|
||||
"../../examples/SharedMemory/PhysicsClientC_API.cpp",
|
||||
|
||||
"../../examples/SharedMemory/PhysicsClientC_API.h",
|
||||
"../../examples/SharedMemory/SharedMemoryPublic.h",
|
||||
|
||||
"../../examples/SharedMemory/Win32SharedMemory.cpp",
|
||||
"../../examples/SharedMemory/Win32SharedMemory.h",
|
||||
"../../examples/SharedMemory/PosixSharedMemory.cpp",
|
||||
"../../examples/SharedMemory/PosixSharedMemory.h",
|
||||
|
||||
"../../examples/Utils/b3ResourcePath.cpp",
|
||||
"../../examples/Utils/b3ResourcePath.h",
|
||||
"../../examples/Utils/RobotLoggingUtil.cpp",
|
||||
"../../examples/Utils/RobotLoggingUtil.h",
|
||||
"../../examples/Utils/b3Clock.cpp",
|
||||
"../../examples/Utils/b3ResourcePath.cpp",
|
||||
"../../examples/Utils/b3ERPCFMHelper.hpp",
|
||||
"../../examples/Utils/b3ReferenceFrameHelper.hpp",
|
||||
"../../examples/Utils/ChromeTraceUtil.cpp",
|
||||
|
||||
"../../examples/ThirdPartyLibs/tinyxml2/tinyxml2.cpp",
|
||||
|
||||
"../../examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp",
|
||||
"../../examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.h",
|
||||
|
||||
"../../examples/ThirdPartyLibs/stb_image/stb_image.cpp",
|
||||
|
||||
"../../examples/ThirdPartyLibs/BussIK/Jacobian.cpp",
|
||||
"../../examples/ThirdPartyLibs/BussIK/LinearR2.cpp",
|
||||
"../../examples/ThirdPartyLibs/BussIK/LinearR3.cpp",
|
||||
"../../examples/ThirdPartyLibs/BussIK/LinearR4.cpp",
|
||||
"../../examples/ThirdPartyLibs/BussIK/MatrixRmn.cpp",
|
||||
"../../examples/ThirdPartyLibs/BussIK/Misc.cpp",
|
||||
"../../examples/ThirdPartyLibs/BussIK/Node.cpp",
|
||||
"../../examples/ThirdPartyLibs/BussIK/Tree.cpp",
|
||||
"../../examples/ThirdPartyLibs/BussIK/VectorRn.cpp",
|
||||
|
||||
"../../examples/Importers/ImportColladaDemo/LoadMeshFromCollada.cpp",
|
||||
"../../examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp",
|
||||
"../../examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp",
|
||||
"../../examples/Importers/ImportMJCFDemo/BulletMJCFImporter.cpp",
|
||||
"../../examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp",
|
||||
"../../examples/Importers/ImportURDFDemo/MyMultiBodyCreator.cpp",
|
||||
"../../examples/Importers/ImportURDFDemo/URDF2Bullet.cpp",
|
||||
"../../examples/Importers/ImportURDFDemo/UrdfParser.cpp",
|
||||
"../../examples/Importers/ImportURDFDemo/urdfStringSplit.cpp",
|
||||
"../../examples/Importers/ImportMeshUtility/b3ImportMeshUtility.cpp",
|
||||
|
||||
"../../examples/MultiThreading/b3PosixThreadSupport.cpp",
|
||||
"../../examples/MultiThreading/b3Win32ThreadSupport.cpp",
|
||||
"../../examples/MultiThreading/b3ThreadSupportInterface.cpp",
|
||||
}
|
||||
|
||||
if (_OPTIONS["enable_static_vr_plugin"]) then
|
||||
files {"../../examples/SharedMemory/plugins/vrSyncPlugin/vrSyncPlugin.cpp"}
|
||||
end
|
||||
|
||||
|
||||
|
||||
196
Engine/lib/bullet/Extras/BulletRoboticsGUI/CMakeLists.txt
Normal file
196
Engine/lib/bullet/Extras/BulletRoboticsGUI/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples/SharedMemory
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/enet/include
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/clsocket/src
|
||||
)
|
||||
|
||||
SET(BulletRoboticsGUI_INCLUDES
|
||||
../../examples/CommonInterfaces/Common2dCanvasInterface.h
|
||||
../../examples/CommonInterfaces/CommonCallbacks.h
|
||||
../../examples/CommonInterfaces/CommonCameraInterface.h
|
||||
../../examples/CommonInterfaces/CommonExampleInterface.h
|
||||
../../examples/CommonInterfaces/CommonFileIOInterface.h
|
||||
../../examples/CommonInterfaces/CommonGraphicsAppInterface.h
|
||||
../../examples/CommonInterfaces/CommonGUIHelperInterface.h
|
||||
../../examples/CommonInterfaces/CommonMultiBodyBase.h
|
||||
../../examples/CommonInterfaces/CommonParameterInterface.h
|
||||
../../examples/CommonInterfaces/CommonRenderInterface.h
|
||||
../../examples/CommonInterfaces/CommonRigidBodyBase.h
|
||||
../../examples/CommonInterfaces/CommonWindowInterface.h
|
||||
|
||||
../../examples/OpenGLWindow/SimpleCamera.h
|
||||
|
||||
../../examples/TinyRenderer/geometry.h
|
||||
../../examples/TinyRenderer/model.h
|
||||
../../examples/TinyRenderer/tgaimage.h
|
||||
../../examples/TinyRenderer/our_gl.h
|
||||
../../examples/TinyRenderer/TinyRenderer.h
|
||||
|
||||
../../examples/SharedMemory/plugins/collisionFilterPlugin/collisionFilterPlugin.h
|
||||
../../examples/SharedMemory/plugins/pdControlPlugin/pdControlPlugin.h
|
||||
../../examples/SharedMemory/b3RobotSimulatorClientAPI_NoGUI.h
|
||||
../../examples/SharedMemory/b3RobotSimulatorClientAPI_NoDirect.h
|
||||
../../examples/SharedMemory/IKTrajectoryHelper.h
|
||||
../../examples/SharedMemory/plugins/tinyRendererPlugin/tinyRendererPlugin.h
|
||||
../../examples/SharedMemory/plugins/tinyRendererPlugin/TinyRendererVisualShapeConverter.h
|
||||
../../examples/SharedMemory/InProcessMemory.h
|
||||
../../examples/SharedMemory/PhysicsServer.h
|
||||
../../examples/SharedMemory/PhysicsClient.h
|
||||
../../examples/SharedMemory/PhysicsServerSharedMemory.h
|
||||
../../examples/SharedMemory/PhysicsDirect.h
|
||||
../../examples/SharedMemory/PhysicsDirectC_API.h
|
||||
../../examples/SharedMemory/PhysicsServerCommandProcessor.h
|
||||
../../examples/SharedMemory/b3PluginManager.h
|
||||
../../examples/SharedMemory/PhysicsClientSharedMemory.h
|
||||
../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h
|
||||
../../examples/SharedMemory/PhysicsClientC_API.h
|
||||
../../examples/SharedMemory/SharedMemoryPublic.h
|
||||
../../examples/SharedMemory/Win32SharedMemory.h
|
||||
../../examples/SharedMemory/PosixSharedMemory.h
|
||||
|
||||
../../examples/Utils/b3ResourcePath.h
|
||||
../../examples/Utils/RobotLoggingUtil.h
|
||||
../../examples/Utils/b3Clock.h
|
||||
../../examples/Utils/b3ResourcePath.h
|
||||
../../examples/Utils/ChromeTraceUtil.h
|
||||
../../examples/Utils/b3ERPCFMHelper.hpp
|
||||
../../examples/Utils/b3ReferenceFrameHelper.hpp
|
||||
|
||||
../../examples/ThirdPartyLibs/tinyxml2/tinyxml2.h
|
||||
../../examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.h
|
||||
../../examples/ThirdPartyLibs/stb_image/stb_image.h
|
||||
../../examples/ThirdPartyLibs/BussIK/Jacobian.h
|
||||
../../examples/ThirdPartyLibs/BussIK/LinearR2.h
|
||||
../../examples/ThirdPartyLibs/BussIK/LinearR3.h
|
||||
../../examples/ThirdPartyLibs/BussIK/LinearR4.h
|
||||
../../examples/ThirdPartyLibs/BussIK/MatrixRmn.h
|
||||
../../examples/ThirdPartyLibs/BussIK/Node.h
|
||||
../../examples/ThirdPartyLibs/BussIK/Tree.h
|
||||
../../examples/ThirdPartyLibs/BussIK/VectorRn.h
|
||||
|
||||
../../examples/Importers/ImportColladaDemo/LoadMeshFromCollada.h
|
||||
../../examples/Importers/ImportObjDemo/LoadMeshFromObj.h
|
||||
../../examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.h
|
||||
../../examples/Importers/ImportMJCFDemo/BulletMJCFImporter.h
|
||||
../../examples/Importers/ImportURDFDemo/BulletUrdfImporter.h
|
||||
../../examples/Importers/ImportURDFDemo/MyMultiBodyCreator.h
|
||||
../../examples/Importers/ImportURDFDemo/URDF2Bullet.h
|
||||
../../examples/Importers/ImportURDFDemo/UrdfParser.h
|
||||
../../examples/Importers/ImportURDFDemo/urdfStringSplit.h
|
||||
../../examples/Importers/ImportURDFDemo/URDFImporterInterface.h
|
||||
../../examples/Importers/ImportURDFDemo/URDFJointTypes.h
|
||||
../../examples/Importers/ImportURDFDemo/SDFAudioTypes.h
|
||||
../../examples/Importers/ImportURDFDemo/UrdfRenderingInterface.h
|
||||
../../examples/Importers/ImportURDFDemo/MultiBodyCreationInterface.h
|
||||
../../examples/Importers/ImportMeshUtility/b3ImportMeshUtility.h
|
||||
|
||||
../../examples/MultiThreading/b3PosixThreadSupport.h
|
||||
../../examples/MultiThreading/b3Win32ThreadSupport.h
|
||||
../../examples/MultiThreading/b3ThreadSupportInterface.h
|
||||
)
|
||||
|
||||
SET(BulletRoboticsGUI_SRCS ${BulletRoboticsGUI_INCLUDES}
|
||||
../../examples/ExampleBrowser/InProcessExampleBrowser.cpp
|
||||
../../examples/SharedMemory/GraphicsServerExample.cpp
|
||||
../../examples/SharedMemory/GraphicsClientExample.cpp
|
||||
../../examples/SharedMemory/RemoteGUIHelper.cpp
|
||||
../../examples/SharedMemory/RemoteGUIHelperTCP.cpp
|
||||
../../examples/SharedMemory/GraphicsServerExample.h
|
||||
../../examples/SharedMemory/GraphicsClientExample.h
|
||||
../../examples/SharedMemory/RemoteGUIHelper.h
|
||||
../../examples/SharedMemory/GraphicsSharedMemoryCommands.h
|
||||
../../examples/SharedMemory/GraphicsSharedMemoryPublic.h
|
||||
../../examples/SharedMemory/PhysicsServerExample.cpp
|
||||
../../examples/SharedMemory/PhysicsServerExampleBullet2.cpp
|
||||
../../examples/SharedMemory/SharedMemoryInProcessPhysicsC_API.cpp
|
||||
)
|
||||
|
||||
IF(BUILD_CLSOCKET)
|
||||
ADD_DEFINITIONS(-DBT_ENABLE_CLSOCKET)
|
||||
ENDIF(BUILD_CLSOCKET)
|
||||
|
||||
IF(WIN32)
|
||||
IF(BUILD_ENET)
|
||||
ADD_DEFINITIONS(-DWIN32 -DBT_ENABLE_ENET)
|
||||
ENDIF(BUILD_ENET)
|
||||
IF(BUILD_CLSOCKET)
|
||||
ADD_DEFINITIONS(-DWIN32)
|
||||
ENDIF(BUILD_CLSOCKET)
|
||||
|
||||
ELSE(WIN32)
|
||||
IF(BUILD_ENET)
|
||||
ADD_DEFINITIONS(-DHAS_SOCKLEN_T -DBT_ENABLE_ENET)
|
||||
ENDIF(BUILD_ENET)
|
||||
|
||||
IF(BUILD_CLSOCKET)
|
||||
ADD_DEFINITIONS(${OSDEF})
|
||||
ENDIF(BUILD_CLSOCKET)
|
||||
|
||||
IF(NOT APPLE)
|
||||
FIND_PACKAGE(Threads)
|
||||
LINK_LIBRARIES( ${CMAKE_THREAD_LIBS_INIT} ${DL} )
|
||||
ENDIF(NOT APPLE)
|
||||
ENDIF(WIN32)
|
||||
|
||||
IF(BUILD_ENET)
|
||||
set(BulletRoboticsGUI_ENET_INCLUDES
|
||||
../../examples/SharedMemory/PhysicsClientUDP.h
|
||||
../../examples/SharedMemory/PhysicsClientUDP_C_API.h
|
||||
../../examples/ThirdPartyLibs/enet/include/enet/win32.h
|
||||
../../examples/ThirdPartyLibs/enet/include/enet/unix.h
|
||||
../../examples/ThirdPartyLibs/enet/include/enet/callbacks.h
|
||||
../../examples/ThirdPartyLibs/enet/include/enet/list.h
|
||||
../../examples/ThirdPartyLibs/enet/include/enet/protocol.h
|
||||
)
|
||||
|
||||
set(BulletRoboticsGUI_INCLUDES
|
||||
${BulletRoboticsGUI_INCLUDES}
|
||||
${BulletRoboticsGUI_ENET_INCLUDES}
|
||||
)
|
||||
|
||||
|
||||
|
||||
ENDIF(BUILD_ENET)
|
||||
|
||||
|
||||
ADD_DEFINITIONS(-DPHYSICS_SERVER_DIRECT)
|
||||
|
||||
|
||||
ADD_LIBRARY(BulletRoboticsGUI ${BulletRoboticsGUI_SRCS})
|
||||
|
||||
SET_TARGET_PROPERTIES(BulletRoboticsGUI PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(BulletRoboticsGUI PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
TARGET_LINK_LIBRARIES(BulletRoboticsGUI BulletExampleBrowserLib BulletRobotics BulletInverseDynamicsUtils BulletWorldImporter BulletFileLoader BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamics LinearMath Bullet3Common)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
|
||||
|
||||
INSTALL(TARGETS
|
||||
BulletRoboticsGUI
|
||||
LIBRARY DESTINATION lib${LIB_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LIB_SUFFIX}
|
||||
)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(BulletRobotics PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(BulletRobotics PROPERTIES PUBLIC_HEADER "PhysicsClientC_API.h" )
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
|
||||
IF(NOT MSVC)
|
||||
SET(PKGCONFIG_INSTALL_PREFIX "lib${LIB_SUFFIX}/pkgconfig/" CACHE STRING "Base directory for pkgconfig files")
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/bullet_robotics_gui.pc.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/bullet_robotics_gui.pc @ONLY)
|
||||
INSTALL(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/bullet_robotics_gui.pc
|
||||
DESTINATION
|
||||
${PKGCONFIG_INSTALL_PREFIX}
|
||||
)
|
||||
ENDIF(NOT MSVC)
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
Name: bullet_robotics_gui
|
||||
Description: Bullet GUI extras for robotics
|
||||
Requires: bullet
|
||||
Version: @BULLET_VERSION@
|
||||
Libs: -L@CMAKE_INSTALL_PREFIX@/@LIB_DESTINATION@ -lBulletRoboticsGUI
|
||||
Cflags: @BULLET_DOUBLE_DEF@ -I@CMAKE_INSTALL_PREFIX@/@INCLUDE_INSTALL_DIR@ -I@CMAKE_INSTALL_PREFIX@/include/bullet_robotics_gui
|
||||
40
Engine/lib/bullet/Extras/CMakeLists.txt
Normal file
40
Engine/lib/bullet/Extras/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
OPTION(BUILD_INVERSE_DYNAMIC_EXTRA "Build InverseDynamic extra module, only applied when BUILD_EXTRAS is ON" ON)
|
||||
OPTION(BUILD_BULLET_ROBOTICS_GUI_EXTRA "Build BulletRoboticsGUI extra module, only applied when BUILD_EXTRAS is ON" ON)
|
||||
OPTION(BUILD_BULLET_ROBOTICS_EXTRA "Build BulletRobotics extra module, only applied when BUILD_EXTRAS is ON" ON)
|
||||
OPTION(BUILD_OBJ2SDF_EXTRA "Build obj2sdf extra module, only applied when BUILD_EXTRAS is ON" ON)
|
||||
OPTION(BUILD_SERIALIZE_EXTRA "Build Serialize extra module, only applied when BUILD_EXTRAS is ON" ON)
|
||||
OPTION(BUILD_CONVEX_DECOMPOSITION_EXTRA "Build ConvexDecomposition extra module, only applied when BUILD_EXTRAS is ON" ON)
|
||||
OPTION(BUILD_HACD_EXTRA "Build HACD extra module, only applied when BUILD_EXTRAS is ON" ON)
|
||||
OPTION(BUILD_GIMPACTUTILS_EXTRA "Build GIMPACTUtils extra module, only applied when BUILD_EXTRAS is ON" ON)
|
||||
|
||||
IF(BUILD_INVERSE_DYNAMIC_EXTRA)
|
||||
SUBDIRS( InverseDynamics )
|
||||
ENDIF()
|
||||
IF(BUILD_BULLET_ROBOTICS_GUI_EXTRA)
|
||||
SUBDIRS( BulletRoboticsGUI )
|
||||
ENDIF()
|
||||
IF(BUILD_BULLET_ROBOTICS_EXTRA)
|
||||
SUBDIRS( BulletRobotics )
|
||||
ENDIF()
|
||||
IF(BUILD_OBJ2SDF_EXTRA)
|
||||
SUBDIRS( obj2sdf )
|
||||
ENDIF()
|
||||
IF(BUILD_SERIALIZE_EXTRA)
|
||||
SUBDIRS( Serialize )
|
||||
ENDIF()
|
||||
IF(BUILD_CONVEX_DECOMPOSITION_EXTRA)
|
||||
SUBDIRS( ConvexDecomposition )
|
||||
ENDIF()
|
||||
IF(BUILD_HACD_EXTRA)
|
||||
SUBDIRS( HACD )
|
||||
ENDIF()
|
||||
IF(BUILD_GIMPACTUTILS_EXTRA)
|
||||
SUBDIRS( GIMPACTUtils )
|
||||
ENDIF()
|
||||
|
||||
|
||||
#Maya Dynamica plugin is moved to http://dynamica.googlecode.com
|
||||
|
||||
#IF (USE_GLUT AND GLUT_FOUND)
|
||||
# SUBDIRS (glui)
|
||||
#ENDIF ()
|
||||
67
Engine/lib/bullet/Extras/ConvexDecomposition/CMakeLists.txt
Normal file
67
Engine/lib/bullet/Extras/ConvexDecomposition/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexDecomposition ${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
SET(ConvexDecomposition_SRCS
|
||||
bestfitobb.cpp
|
||||
ConvexBuilder.cpp
|
||||
cd_wavefront.cpp
|
||||
fitsphere.cpp
|
||||
meshvolume.cpp
|
||||
raytri.cpp
|
||||
vlookup.cpp
|
||||
bestfit.cpp
|
||||
cd_hull.cpp
|
||||
ConvexDecomposition.cpp
|
||||
concavity.cpp
|
||||
float_math.cpp
|
||||
planetri.cpp
|
||||
splitplane.cpp
|
||||
)
|
||||
|
||||
SET(ConvexDecomposition_HDRS
|
||||
ConvexDecomposition.h
|
||||
cd_vector.h
|
||||
concavity.h
|
||||
bestfitobb.h
|
||||
ConvexBuilder.h
|
||||
cd_wavefront.h
|
||||
fitsphere.h
|
||||
meshvolume.h
|
||||
raytri.h
|
||||
vlookup.h
|
||||
bestfit.h
|
||||
cd_hull.h
|
||||
)
|
||||
|
||||
ADD_LIBRARY(ConvexDecomposition ${ConvexDecomposition_SRCS} ${ConvexDecomposition_HDRS})
|
||||
SET_TARGET_PROPERTIES(ConvexDecomposition PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(ConvexDecomposition PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
TARGET_LINK_LIBRARIES(ConvexDecomposition BulletCollision LinearMath)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
IF (INSTALL_EXTRA_LIBS)
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
#FILES_MATCHING requires CMake 2.6
|
||||
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS ConvexDecomposition DESTINATION .)
|
||||
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS ConvexDecomposition
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib${LIB_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LIB_SUFFIX})
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
|
||||
".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(ConvexDecomposition PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(ConvexDecomposition PROPERTIES PUBLIC_HEADER "${ConvexDecomposition_HDRS}")
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ENDIF (INSTALL_EXTRA_LIBS)
|
||||
350
Engine/lib/bullet/Extras/ConvexDecomposition/ConvexBuilder.cpp
Normal file
350
Engine/lib/bullet/Extras/ConvexDecomposition/ConvexBuilder.cpp
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
#include "float_math.h"
|
||||
#include "ConvexBuilder.h"
|
||||
#include "meshvolume.h"
|
||||
#include "bestfit.h"
|
||||
#include <assert.h>
|
||||
#include "cd_hull.h"
|
||||
|
||||
#include "fitsphere.h"
|
||||
#include "bestfitobb.h"
|
||||
|
||||
unsigned int MAXDEPTH = 8;
|
||||
float CONCAVE_PERCENT = 1.0f;
|
||||
float MERGE_PERCENT = 2.0f;
|
||||
|
||||
CHull::CHull(const ConvexDecomposition::ConvexResult &result)
|
||||
{
|
||||
mResult = new ConvexDecomposition::ConvexResult(result);
|
||||
mVolume = computeMeshVolume(result.mHullVertices, result.mHullTcount, result.mHullIndices);
|
||||
|
||||
mDiagonal = getBoundingRegion(result.mHullVcount, result.mHullVertices, sizeof(float) * 3, mMin, mMax);
|
||||
|
||||
float dx = mMax[0] - mMin[0];
|
||||
float dy = mMax[1] - mMin[1];
|
||||
float dz = mMax[2] - mMin[2];
|
||||
|
||||
dx *= 0.1f; // inflate 1/10th on each edge
|
||||
dy *= 0.1f; // inflate 1/10th on each edge
|
||||
dz *= 0.1f; // inflate 1/10th on each edge
|
||||
|
||||
mMin[0] -= dx;
|
||||
mMin[1] -= dy;
|
||||
mMin[2] -= dz;
|
||||
|
||||
mMax[0] += dx;
|
||||
mMax[1] += dy;
|
||||
mMax[2] += dz;
|
||||
}
|
||||
|
||||
CHull::~CHull(void)
|
||||
{
|
||||
delete mResult;
|
||||
}
|
||||
|
||||
bool CHull::overlap(const CHull &h) const
|
||||
{
|
||||
return overlapAABB(mMin, mMax, h.mMin, h.mMax);
|
||||
}
|
||||
|
||||
ConvexBuilder::ConvexBuilder(ConvexDecompInterface *callback)
|
||||
{
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
ConvexBuilder::~ConvexBuilder(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < mChulls.size(); i++)
|
||||
{
|
||||
CHull *cr = mChulls[i];
|
||||
delete cr;
|
||||
}
|
||||
}
|
||||
|
||||
bool ConvexBuilder::isDuplicate(unsigned int i1, unsigned int i2, unsigned int i3,
|
||||
unsigned int ci1, unsigned int ci2, unsigned int ci3)
|
||||
{
|
||||
unsigned int dcount = 0;
|
||||
|
||||
assert(i1 != i2 && i1 != i3 && i2 != i3);
|
||||
assert(ci1 != ci2 && ci1 != ci3 && ci2 != ci3);
|
||||
|
||||
if (i1 == ci1 || i1 == ci2 || i1 == ci3) dcount++;
|
||||
if (i2 == ci1 || i2 == ci2 || i2 == ci3) dcount++;
|
||||
if (i3 == ci1 || i3 == ci2 || i3 == ci3) dcount++;
|
||||
|
||||
return dcount == 3;
|
||||
}
|
||||
|
||||
void ConvexBuilder::getMesh(const ConvexDecomposition::ConvexResult &cr, VertexLookup vc, UintVector &indices)
|
||||
{
|
||||
unsigned int *src = cr.mHullIndices;
|
||||
|
||||
for (unsigned int i = 0; i < cr.mHullTcount; i++)
|
||||
{
|
||||
unsigned int i1 = *src++;
|
||||
unsigned int i2 = *src++;
|
||||
unsigned int i3 = *src++;
|
||||
|
||||
const float *p1 = &cr.mHullVertices[i1 * 3];
|
||||
const float *p2 = &cr.mHullVertices[i2 * 3];
|
||||
const float *p3 = &cr.mHullVertices[i3 * 3];
|
||||
|
||||
i1 = Vl_getIndex(vc, p1);
|
||||
i2 = Vl_getIndex(vc, p2);
|
||||
i3 = Vl_getIndex(vc, p3);
|
||||
|
||||
#if 0
|
||||
bool duplicate = false;
|
||||
|
||||
unsigned int tcount = indices.size()/3;
|
||||
for (unsigned int j=0; j<tcount; j++)
|
||||
{
|
||||
unsigned int ci1 = indices[j*3+0];
|
||||
unsigned int ci2 = indices[j*3+1];
|
||||
unsigned int ci3 = indices[j*3+2];
|
||||
if ( isDuplicate(i1,i2,i3, ci1, ci2, ci3 ) )
|
||||
{
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !duplicate )
|
||||
{
|
||||
indices.push_back(i1);
|
||||
indices.push_back(i2);
|
||||
indices.push_back(i3);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
CHull *ConvexBuilder::canMerge(CHull *a, CHull *b)
|
||||
{
|
||||
if (!a->overlap(*b)) return 0; // if their AABB's (with a little slop) don't overlap, then return.
|
||||
|
||||
CHull *ret = 0;
|
||||
|
||||
// ok..we are going to combine both meshes into a single mesh
|
||||
// and then we are going to compute the concavity...
|
||||
|
||||
VertexLookup vc = Vl_createVertexLookup();
|
||||
|
||||
UintVector indices;
|
||||
|
||||
getMesh(*a->mResult, vc, indices);
|
||||
getMesh(*b->mResult, vc, indices);
|
||||
|
||||
unsigned int vcount = Vl_getVcount(vc);
|
||||
const float *vertices = Vl_getVertices(vc);
|
||||
unsigned int tcount = indices.size() / 3;
|
||||
|
||||
//don't do anything if hull is empty
|
||||
if (!tcount)
|
||||
{
|
||||
Vl_releaseVertexLookup(vc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ConvexDecomposition::HullResult hresult;
|
||||
ConvexDecomposition::HullLibrary hl;
|
||||
ConvexDecomposition::HullDesc desc;
|
||||
|
||||
desc.SetHullFlag(ConvexDecomposition::QF_TRIANGLES);
|
||||
|
||||
desc.mVcount = vcount;
|
||||
desc.mVertices = vertices;
|
||||
desc.mVertexStride = sizeof(float) * 3;
|
||||
|
||||
ConvexDecomposition::HullError hret = hl.CreateConvexHull(desc, hresult);
|
||||
|
||||
if (hret == ConvexDecomposition::QE_OK)
|
||||
{
|
||||
float combineVolume = computeMeshVolume(hresult.mOutputVertices, hresult.mNumFaces, hresult.mIndices);
|
||||
float sumVolume = a->mVolume + b->mVolume;
|
||||
|
||||
float percent = (sumVolume * 100) / combineVolume;
|
||||
if (percent >= (100.0f - MERGE_PERCENT))
|
||||
{
|
||||
ConvexDecomposition::ConvexResult cr(hresult.mNumOutputVertices, hresult.mOutputVertices, hresult.mNumFaces, hresult.mIndices);
|
||||
ret = new CHull(cr);
|
||||
}
|
||||
}
|
||||
|
||||
Vl_releaseVertexLookup(vc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ConvexBuilder::combineHulls(void)
|
||||
{
|
||||
bool combine = false;
|
||||
|
||||
sortChulls(mChulls); // sort the convex hulls, largest volume to least...
|
||||
|
||||
CHullVector output; // the output hulls...
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mChulls.size() && !combine; ++i)
|
||||
{
|
||||
CHull *cr = mChulls[i];
|
||||
|
||||
int j;
|
||||
for (j = 0; j < mChulls.size(); j++)
|
||||
{
|
||||
CHull *match = mChulls[j];
|
||||
|
||||
if (cr != match) // don't try to merge a hull with itself, that be stoopid
|
||||
{
|
||||
CHull *merge = canMerge(cr, match); // if we can merge these two....
|
||||
|
||||
if (merge)
|
||||
{
|
||||
output.push_back(merge);
|
||||
|
||||
++i;
|
||||
while (i != mChulls.size())
|
||||
{
|
||||
CHull *cr = mChulls[i];
|
||||
if (cr != match)
|
||||
{
|
||||
output.push_back(cr);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
delete cr;
|
||||
delete match;
|
||||
combine = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (combine)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
output.push_back(cr);
|
||||
}
|
||||
}
|
||||
|
||||
if (combine)
|
||||
{
|
||||
mChulls.clear();
|
||||
mChulls.copyFromArray(output);
|
||||
output.clear();
|
||||
}
|
||||
|
||||
return combine;
|
||||
}
|
||||
|
||||
unsigned int ConvexBuilder::process(const ConvexDecomposition::DecompDesc &desc)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
|
||||
MAXDEPTH = desc.mDepth;
|
||||
CONCAVE_PERCENT = desc.mCpercent;
|
||||
MERGE_PERCENT = desc.mPpercent;
|
||||
|
||||
calcConvexDecomposition(desc.mVcount, desc.mVertices, desc.mTcount, desc.mIndices, this, 0, 0);
|
||||
|
||||
while (combineHulls())
|
||||
; // keep combinging hulls until I can't combine any more...
|
||||
|
||||
int i;
|
||||
for (i = 0; i < mChulls.size(); i++)
|
||||
{
|
||||
CHull *cr = mChulls[i];
|
||||
|
||||
// before we hand it back to the application, we need to regenerate the hull based on the
|
||||
// limits given by the user.
|
||||
|
||||
const ConvexDecomposition::ConvexResult &c = *cr->mResult; // the high resolution hull...
|
||||
|
||||
ConvexDecomposition::HullResult result;
|
||||
ConvexDecomposition::HullLibrary hl;
|
||||
ConvexDecomposition::HullDesc hdesc;
|
||||
|
||||
hdesc.SetHullFlag(ConvexDecomposition::QF_TRIANGLES);
|
||||
|
||||
hdesc.mVcount = c.mHullVcount;
|
||||
hdesc.mVertices = c.mHullVertices;
|
||||
hdesc.mVertexStride = sizeof(float) * 3;
|
||||
hdesc.mMaxVertices = desc.mMaxVertices; // maximum number of vertices allowed in the output
|
||||
|
||||
if (desc.mSkinWidth)
|
||||
{
|
||||
hdesc.mSkinWidth = desc.mSkinWidth;
|
||||
hdesc.SetHullFlag(ConvexDecomposition::QF_SKIN_WIDTH); // do skin width computation.
|
||||
}
|
||||
|
||||
ConvexDecomposition::HullError ret = hl.CreateConvexHull(hdesc, result);
|
||||
|
||||
if (ret == ConvexDecomposition::QE_OK)
|
||||
{
|
||||
ConvexDecomposition::ConvexResult r(result.mNumOutputVertices, result.mOutputVertices, result.mNumFaces, result.mIndices);
|
||||
|
||||
r.mHullVolume = computeMeshVolume(result.mOutputVertices, result.mNumFaces, result.mIndices); // the volume of the hull.
|
||||
|
||||
// compute the best fit OBB
|
||||
computeBestFitOBB(result.mNumOutputVertices, result.mOutputVertices, sizeof(float) * 3, r.mOBBSides, r.mOBBTransform);
|
||||
|
||||
r.mOBBVolume = r.mOBBSides[0] * r.mOBBSides[1] * r.mOBBSides[2]; // compute the OBB volume.
|
||||
|
||||
fm_getTranslation(r.mOBBTransform, r.mOBBCenter); // get the translation component of the 4x4 matrix.
|
||||
|
||||
fm_matrixToQuat(r.mOBBTransform, r.mOBBOrientation); // extract the orientation as a quaternion.
|
||||
|
||||
r.mSphereRadius = computeBoundingSphere(result.mNumOutputVertices, result.mOutputVertices, r.mSphereCenter);
|
||||
r.mSphereVolume = fm_sphereVolume(r.mSphereRadius);
|
||||
|
||||
mCallback->ConvexDecompResult(r);
|
||||
}
|
||||
|
||||
hl.ReleaseResult(result);
|
||||
|
||||
delete cr;
|
||||
}
|
||||
|
||||
ret = mChulls.size();
|
||||
|
||||
mChulls.clear();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ConvexBuilder::ConvexDebugTri(const float *p1, const float *p2, const float *p3, unsigned int color)
|
||||
{
|
||||
mCallback->ConvexDebugTri(p1, p2, p3, color);
|
||||
}
|
||||
|
||||
void ConvexBuilder::ConvexDebugOBB(const float *sides, const float *matrix, unsigned int color)
|
||||
{
|
||||
mCallback->ConvexDebugOBB(sides, matrix, color);
|
||||
}
|
||||
void ConvexBuilder::ConvexDebugPoint(const float *p, float dist, unsigned int color)
|
||||
{
|
||||
mCallback->ConvexDebugPoint(p, dist, color);
|
||||
}
|
||||
|
||||
void ConvexBuilder::ConvexDebugBound(const float *bmin, const float *bmax, unsigned int color)
|
||||
{
|
||||
mCallback->ConvexDebugBound(bmin, bmax, color);
|
||||
}
|
||||
|
||||
void ConvexBuilder::ConvexDecompResult(ConvexDecomposition::ConvexResult &result)
|
||||
{
|
||||
CHull *ch = new CHull(result);
|
||||
mChulls.push_back(ch);
|
||||
}
|
||||
|
||||
void ConvexBuilder::sortChulls(CHullVector &hulls)
|
||||
{
|
||||
hulls.quickSort(CHullSort());
|
||||
//hulls.heapSort(CHullSort());
|
||||
}
|
||||
103
Engine/lib/bullet/Extras/ConvexDecomposition/ConvexBuilder.h
Normal file
103
Engine/lib/bullet/Extras/ConvexDecomposition/ConvexBuilder.h
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
#ifndef CONVEX_BUILDER_H
|
||||
#define CONVEX_BUILDER_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
#include "ConvexDecomposition.h"
|
||||
#include "vlookup.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
class CHull
|
||||
{
|
||||
public:
|
||||
CHull(const ConvexDecomposition::ConvexResult &result);
|
||||
|
||||
~CHull(void);
|
||||
|
||||
bool overlap(const CHull &h) const;
|
||||
|
||||
float mMin[3];
|
||||
float mMax[3];
|
||||
float mVolume;
|
||||
float mDiagonal; // long edge..
|
||||
ConvexDecomposition::ConvexResult *mResult;
|
||||
};
|
||||
|
||||
// Usage: std::sort( list.begin(), list.end(), StringSortRef() );
|
||||
class CHullSort
|
||||
{
|
||||
public:
|
||||
inline bool operator()(const CHull *a, const CHull *b) const
|
||||
{
|
||||
return a->mVolume < b->mVolume;
|
||||
}
|
||||
};
|
||||
|
||||
typedef btAlignedObjectArray<CHull *> CHullVector;
|
||||
|
||||
class ConvexBuilder : public ConvexDecomposition::ConvexDecompInterface
|
||||
{
|
||||
public:
|
||||
ConvexBuilder(ConvexDecomposition::ConvexDecompInterface *callback);
|
||||
|
||||
virtual ~ConvexBuilder(void);
|
||||
|
||||
bool isDuplicate(unsigned int i1, unsigned int i2, unsigned int i3,
|
||||
unsigned int ci1, unsigned int ci2, unsigned int ci3);
|
||||
|
||||
void getMesh(const ConvexDecomposition::ConvexResult &cr, VertexLookup vc, UintVector &indices);
|
||||
|
||||
CHull *canMerge(CHull *a, CHull *b);
|
||||
|
||||
bool combineHulls(void);
|
||||
|
||||
unsigned int process(const ConvexDecomposition::DecompDesc &desc);
|
||||
|
||||
virtual void ConvexDebugTri(const float *p1, const float *p2, const float *p3, unsigned int color);
|
||||
|
||||
virtual void ConvexDebugOBB(const float *sides, const float *matrix, unsigned int color);
|
||||
virtual void ConvexDebugPoint(const float *p, float dist, unsigned int color);
|
||||
|
||||
virtual void ConvexDebugBound(const float *bmin, const float *bmax, unsigned int color);
|
||||
|
||||
virtual void ConvexDecompResult(ConvexDecomposition::ConvexResult &result);
|
||||
|
||||
void sortChulls(CHullVector &hulls);
|
||||
|
||||
CHullVector mChulls;
|
||||
ConvexDecompInterface *mCallback;
|
||||
};
|
||||
|
||||
#endif //CONVEX_BUILDER_H
|
||||
|
|
@ -0,0 +1,346 @@
|
|||
#include "float_math.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
#include "ConvexDecomposition.h"
|
||||
#include "cd_vector.h"
|
||||
#include "cd_hull.h"
|
||||
#include "bestfit.h"
|
||||
#include "planetri.h"
|
||||
#include "vlookup.h"
|
||||
#include "splitplane.h"
|
||||
#include "meshvolume.h"
|
||||
#include "concavity.h"
|
||||
#include "bestfitobb.h"
|
||||
#include "float_math.h"
|
||||
#include "fitsphere.h"
|
||||
|
||||
#define SHOW_MESH 0
|
||||
#define MAKE_MESH 1
|
||||
|
||||
using namespace ConvexDecomposition;
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
class FaceTri
|
||||
{
|
||||
public:
|
||||
FaceTri(void){};
|
||||
FaceTri(const float *vertices, unsigned int i1, unsigned int i2, unsigned int i3)
|
||||
{
|
||||
mP1.Set(&vertices[i1 * 3]);
|
||||
mP2.Set(&vertices[i2 * 3]);
|
||||
mP3.Set(&vertices[i3 * 3]);
|
||||
}
|
||||
|
||||
Vector3d mP1;
|
||||
Vector3d mP2;
|
||||
Vector3d mP3;
|
||||
Vector3d mNormal;
|
||||
};
|
||||
|
||||
void addTri(VertexLookup vl, UintVector &list, const Vector3d &p1, const Vector3d &p2, const Vector3d &p3)
|
||||
{
|
||||
unsigned int i1 = Vl_getIndex(vl, p1.Ptr());
|
||||
unsigned int i2 = Vl_getIndex(vl, p2.Ptr());
|
||||
unsigned int i3 = Vl_getIndex(vl, p3.Ptr());
|
||||
|
||||
// do *not* process degenerate triangles!
|
||||
|
||||
if (i1 != i2 && i1 != i3 && i2 != i3)
|
||||
{
|
||||
list.push_back(i1);
|
||||
list.push_back(i2);
|
||||
list.push_back(i3);
|
||||
}
|
||||
}
|
||||
|
||||
void calcConvexDecomposition(unsigned int vcount,
|
||||
const float *vertices,
|
||||
unsigned int tcount,
|
||||
const unsigned int *indices,
|
||||
ConvexDecompInterface *callback,
|
||||
float masterVolume,
|
||||
unsigned int depth)
|
||||
|
||||
{
|
||||
float plane[4];
|
||||
|
||||
bool split = false;
|
||||
|
||||
if (depth < MAXDEPTH)
|
||||
{
|
||||
float volume;
|
||||
float c = computeConcavity(vcount, vertices, tcount, indices, callback, plane, volume);
|
||||
|
||||
if (depth == 0)
|
||||
{
|
||||
masterVolume = volume;
|
||||
}
|
||||
|
||||
float percent = (c * 100.0f) / masterVolume;
|
||||
|
||||
if (percent > CONCAVE_PERCENT) // if great than 5% of the total volume is concave, go ahead and keep splitting.
|
||||
{
|
||||
split = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (depth >= MAXDEPTH || !split)
|
||||
{
|
||||
#if 1
|
||||
|
||||
HullResult result;
|
||||
HullLibrary hl;
|
||||
HullDesc desc;
|
||||
|
||||
desc.SetHullFlag(QF_TRIANGLES);
|
||||
|
||||
desc.mVcount = vcount;
|
||||
desc.mVertices = vertices;
|
||||
desc.mVertexStride = sizeof(float) * 3;
|
||||
|
||||
HullError ret = hl.CreateConvexHull(desc, result);
|
||||
|
||||
if (ret == QE_OK)
|
||||
{
|
||||
ConvexResult r(result.mNumOutputVertices, result.mOutputVertices, result.mNumFaces, result.mIndices);
|
||||
|
||||
callback->ConvexDecompResult(r);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static unsigned int colors[8] =
|
||||
{
|
||||
0xFF0000,
|
||||
0x00FF00,
|
||||
0x0000FF,
|
||||
0xFFFF00,
|
||||
0x00FFFF,
|
||||
0xFF00FF,
|
||||
0xFFFFFF,
|
||||
0xFF8040};
|
||||
|
||||
static int count = 0;
|
||||
|
||||
count++;
|
||||
|
||||
if (count == 8) count = 0;
|
||||
|
||||
assert(count >= 0 && count < 8);
|
||||
|
||||
unsigned int color = colors[count];
|
||||
|
||||
const unsigned int *source = indices;
|
||||
|
||||
for (unsigned int i = 0; i < tcount; i++)
|
||||
{
|
||||
unsigned int i1 = *source++;
|
||||
unsigned int i2 = *source++;
|
||||
unsigned int i3 = *source++;
|
||||
|
||||
FaceTri t(vertices, i1, i2, i3);
|
||||
|
||||
callback->ConvexDebugTri(t.mP1.Ptr(), t.mP2.Ptr(), t.mP3.Ptr(), color);
|
||||
}
|
||||
#endif
|
||||
|
||||
hl.ReleaseResult(result);
|
||||
return;
|
||||
}
|
||||
|
||||
UintVector ifront;
|
||||
UintVector iback;
|
||||
|
||||
VertexLookup vfront = Vl_createVertexLookup();
|
||||
VertexLookup vback = Vl_createVertexLookup();
|
||||
|
||||
bool showmesh = false;
|
||||
#if SHOW_MESH
|
||||
showmesh = true;
|
||||
#endif
|
||||
|
||||
if (0)
|
||||
{
|
||||
showmesh = true;
|
||||
for (float x = -1; x < 1; x += 0.10f)
|
||||
{
|
||||
for (float y = 0; y < 1; y += 0.10f)
|
||||
{
|
||||
for (float z = -1; z < 1; z += 0.04f)
|
||||
{
|
||||
float d = x * plane[0] + y * plane[1] + z * plane[2] + plane[3];
|
||||
Vector3d p(x, y, z);
|
||||
if (d >= 0)
|
||||
callback->ConvexDebugPoint(p.Ptr(), 0.02f, 0x00FF00);
|
||||
else
|
||||
callback->ConvexDebugPoint(p.Ptr(), 0.02f, 0xFF0000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (1)
|
||||
{
|
||||
// ok..now we are going to 'split' all of the input triangles against this plane!
|
||||
const unsigned int *source = indices;
|
||||
for (unsigned int i = 0; i < tcount; i++)
|
||||
{
|
||||
unsigned int i1 = *source++;
|
||||
unsigned int i2 = *source++;
|
||||
unsigned int i3 = *source++;
|
||||
|
||||
FaceTri t(vertices, i1, i2, i3);
|
||||
|
||||
Vector3d front[4];
|
||||
Vector3d back[4];
|
||||
|
||||
unsigned int fcount = 0;
|
||||
unsigned int bcount = 0;
|
||||
|
||||
PlaneTriResult result;
|
||||
|
||||
result = planeTriIntersection(plane, t.mP1.Ptr(), sizeof(Vector3d), 0.00001f, front[0].Ptr(), fcount, back[0].Ptr(), bcount);
|
||||
|
||||
if (fcount > 4 || bcount > 4)
|
||||
{
|
||||
result = planeTriIntersection(plane, t.mP1.Ptr(), sizeof(Vector3d), 0.00001f, front[0].Ptr(), fcount, back[0].Ptr(), bcount);
|
||||
}
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case PTR_FRONT:
|
||||
|
||||
assert(fcount == 3);
|
||||
|
||||
if (showmesh)
|
||||
callback->ConvexDebugTri(front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00FF00);
|
||||
|
||||
#if MAKE_MESH
|
||||
|
||||
addTri(vfront, ifront, front[0], front[1], front[2]);
|
||||
|
||||
#endif
|
||||
|
||||
break;
|
||||
case PTR_BACK:
|
||||
assert(bcount == 3);
|
||||
|
||||
if (showmesh)
|
||||
callback->ConvexDebugTri(back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xFFFF00);
|
||||
|
||||
#if MAKE_MESH
|
||||
|
||||
addTri(vback, iback, back[0], back[1], back[2]);
|
||||
|
||||
#endif
|
||||
|
||||
break;
|
||||
case PTR_SPLIT:
|
||||
|
||||
assert(fcount >= 3 && fcount <= 4);
|
||||
assert(bcount >= 3 && bcount <= 4);
|
||||
|
||||
#if MAKE_MESH
|
||||
|
||||
addTri(vfront, ifront, front[0], front[1], front[2]);
|
||||
addTri(vback, iback, back[0], back[1], back[2]);
|
||||
|
||||
if (fcount == 4)
|
||||
{
|
||||
addTri(vfront, ifront, front[0], front[2], front[3]);
|
||||
}
|
||||
|
||||
if (bcount == 4)
|
||||
{
|
||||
addTri(vback, iback, back[0], back[2], back[3]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (showmesh)
|
||||
{
|
||||
callback->ConvexDebugTri(front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00D000);
|
||||
callback->ConvexDebugTri(back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xD0D000);
|
||||
|
||||
if (fcount == 4)
|
||||
{
|
||||
callback->ConvexDebugTri(front[0].Ptr(), front[2].Ptr(), front[3].Ptr(), 0x00D000);
|
||||
}
|
||||
if (bcount == 4)
|
||||
{
|
||||
callback->ConvexDebugTri(back[0].Ptr(), back[2].Ptr(), back[3].Ptr(), 0xD0D000);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ok... here we recursively call
|
||||
if (ifront.size())
|
||||
{
|
||||
unsigned int vcount = Vl_getVcount(vfront);
|
||||
const float *vertices = Vl_getVertices(vfront);
|
||||
unsigned int tcount = ifront.size() / 3;
|
||||
|
||||
calcConvexDecomposition(vcount, vertices, tcount, &ifront[0], callback, masterVolume, depth + 1);
|
||||
}
|
||||
|
||||
ifront.clear();
|
||||
|
||||
Vl_releaseVertexLookup(vfront);
|
||||
|
||||
if (iback.size())
|
||||
{
|
||||
unsigned int vcount = Vl_getVcount(vback);
|
||||
const float *vertices = Vl_getVertices(vback);
|
||||
unsigned int tcount = iback.size() / 3;
|
||||
|
||||
calcConvexDecomposition(vcount, vertices, tcount, &iback[0], callback, masterVolume, depth + 1);
|
||||
}
|
||||
|
||||
iback.clear();
|
||||
Vl_releaseVertexLookup(vback);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ConvexDecomposition
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
#ifndef CONVEX_DECOMPOSITION_H
|
||||
|
||||
#define CONVEX_DECOMPOSITION_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <memory.h> //memcpy
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
extern unsigned int MAXDEPTH;
|
||||
extern float CONCAVE_PERCENT;
|
||||
extern float MERGE_PERCENT;
|
||||
|
||||
typedef btAlignedObjectArray<unsigned int> UintVector;
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
class ConvexResult
|
||||
{
|
||||
public:
|
||||
ConvexResult(void)
|
||||
{
|
||||
mHullVcount = 0;
|
||||
mHullVertices = 0;
|
||||
mHullTcount = 0;
|
||||
mHullIndices = 0;
|
||||
}
|
||||
|
||||
ConvexResult(unsigned int hvcount, const float *hvertices, unsigned int htcount, const unsigned int *hindices)
|
||||
{
|
||||
mHullVcount = hvcount;
|
||||
if (mHullVcount)
|
||||
{
|
||||
mHullVertices = new float[mHullVcount * sizeof(float) * 3];
|
||||
memcpy(mHullVertices, hvertices, sizeof(float) * 3 * mHullVcount);
|
||||
}
|
||||
else
|
||||
{
|
||||
mHullVertices = 0;
|
||||
}
|
||||
|
||||
mHullTcount = htcount;
|
||||
|
||||
if (mHullTcount)
|
||||
{
|
||||
mHullIndices = new unsigned int[sizeof(unsigned int) * mHullTcount * 3];
|
||||
memcpy(mHullIndices, hindices, sizeof(unsigned int) * mHullTcount * 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
mHullIndices = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ConvexResult(const ConvexResult &r)
|
||||
{
|
||||
mHullVcount = r.mHullVcount;
|
||||
if (mHullVcount)
|
||||
{
|
||||
mHullVertices = new float[mHullVcount * sizeof(float) * 3];
|
||||
memcpy(mHullVertices, r.mHullVertices, sizeof(float) * 3 * mHullVcount);
|
||||
}
|
||||
else
|
||||
{
|
||||
mHullVertices = 0;
|
||||
}
|
||||
mHullTcount = r.mHullTcount;
|
||||
if (mHullTcount)
|
||||
{
|
||||
mHullIndices = new unsigned int[sizeof(unsigned int) * mHullTcount * 3];
|
||||
memcpy(mHullIndices, r.mHullIndices, sizeof(unsigned int) * mHullTcount * 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
mHullIndices = 0;
|
||||
}
|
||||
}
|
||||
|
||||
~ConvexResult(void)
|
||||
{
|
||||
delete[] mHullVertices;
|
||||
delete[] mHullIndices;
|
||||
}
|
||||
|
||||
// the convex hull.
|
||||
unsigned int mHullVcount;
|
||||
float *mHullVertices;
|
||||
unsigned int mHullTcount;
|
||||
unsigned int *mHullIndices;
|
||||
|
||||
float mHullVolume; // the volume of the convex hull.
|
||||
|
||||
float mOBBSides[3]; // the width, height and breadth of the best fit OBB
|
||||
float mOBBCenter[3]; // the center of the OBB
|
||||
float mOBBOrientation[4]; // the quaternion rotation of the OBB.
|
||||
float mOBBTransform[16]; // the 4x4 transform of the OBB.
|
||||
float mOBBVolume; // the volume of the OBB
|
||||
|
||||
float mSphereRadius; // radius and center of best fit sphere
|
||||
float mSphereCenter[3];
|
||||
float mSphereVolume; // volume of the best fit sphere
|
||||
};
|
||||
|
||||
class ConvexDecompInterface
|
||||
{
|
||||
public:
|
||||
virtual ~ConvexDecompInterface(){};
|
||||
virtual void ConvexDebugTri(const float *p1, const float *p2, const float *p3, unsigned int color){};
|
||||
virtual void ConvexDebugPoint(const float *p, float dist, unsigned int color){};
|
||||
virtual void ConvexDebugBound(const float *bmin, const float *bmax, unsigned int color){};
|
||||
virtual void ConvexDebugOBB(const float *sides, const float *matrix, unsigned int color){};
|
||||
|
||||
virtual void ConvexDecompResult(ConvexResult &result) = 0;
|
||||
};
|
||||
|
||||
// just to avoid passing a zillion parameters to the method the
|
||||
// options are packed into this descriptor.
|
||||
class DecompDesc
|
||||
{
|
||||
public:
|
||||
DecompDesc(void)
|
||||
{
|
||||
mVcount = 0;
|
||||
mVertices = 0;
|
||||
mTcount = 0;
|
||||
mIndices = 0;
|
||||
mDepth = 5;
|
||||
mCpercent = 5;
|
||||
mPpercent = 5;
|
||||
mMaxVertices = 32;
|
||||
mSkinWidth = 0;
|
||||
mCallback = 0;
|
||||
}
|
||||
|
||||
// describes the input triangle.
|
||||
unsigned int mVcount; // the number of vertices in the source mesh.
|
||||
const float *mVertices; // start of the vertex position array. Assumes a stride of 3 floats.
|
||||
unsigned int mTcount; // the number of triangles in the source mesh.
|
||||
unsigned int *mIndices; // the indexed triangle list array (zero index based)
|
||||
|
||||
// options
|
||||
unsigned int mDepth; // depth to split, a maximum of 10, generally not over 7.
|
||||
float mCpercent; // the concavity threshold percentage. 0=20 is reasonable.
|
||||
float mPpercent; // the percentage volume conservation threshold to collapse hulls. 0-30 is reasonable.
|
||||
|
||||
// hull output limits.
|
||||
unsigned int mMaxVertices; // maximum number of vertices in the output hull. Recommended 32 or less.
|
||||
float mSkinWidth; // a skin width to apply to the output hulls.
|
||||
|
||||
ConvexDecompInterface *mCallback; // the interface to receive back the results.
|
||||
};
|
||||
|
||||
// perform approximate convex decomposition on a mesh.
|
||||
unsigned int performConvexDecomposition(const DecompDesc &desc); // returns the number of hulls produced.
|
||||
|
||||
void calcConvexDecomposition(unsigned int vcount,
|
||||
const float *vertices,
|
||||
unsigned int tcount,
|
||||
const unsigned int *indices,
|
||||
ConvexDecompInterface *callback,
|
||||
float masterVolume,
|
||||
unsigned int depth);
|
||||
|
||||
} // namespace ConvexDecomposition
|
||||
|
||||
#endif
|
||||
19
Engine/lib/bullet/Extras/ConvexDecomposition/LICENSE.txt
Normal file
19
Engine/lib/bullet/Extras/ConvexDecomposition/LICENSE.txt
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
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.
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
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 INTEL 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.
|
||||
448
Engine/lib/bullet/Extras/ConvexDecomposition/bestfit.cpp
Normal file
448
Engine/lib/bullet/Extras/ConvexDecomposition/bestfit.cpp
Normal file
|
|
@ -0,0 +1,448 @@
|
|||
#include "float_math.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
// Geometric Tools, Inc.
|
||||
// http://www.geometrictools.com
|
||||
// Copyright (c) 1998-2006. All Rights Reserved
|
||||
//
|
||||
// The Wild Magic Library (WM3) source code is supplied under the terms of
|
||||
// the license agreement
|
||||
// http://www.geometrictools.com/License/WildMagic3License.pdf
|
||||
// and may not be copied or disclosed except in accordance with the terms
|
||||
// of that agreement.
|
||||
|
||||
#include "bestfit.h"
|
||||
|
||||
namespace BestFit
|
||||
{
|
||||
class Vec3
|
||||
{
|
||||
public:
|
||||
Vec3(void){};
|
||||
Vec3(float _x, float _y, float _z)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
};
|
||||
|
||||
float dot(const Vec3 &v)
|
||||
{
|
||||
return x * v.x + y * v.y + z * v.z; // the dot product
|
||||
}
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
class Eigen
|
||||
{
|
||||
public:
|
||||
void DecrSortEigenStuff(void)
|
||||
{
|
||||
Tridiagonal(); //diagonalize the matrix.
|
||||
QLAlgorithm(); //
|
||||
DecreasingSort();
|
||||
GuaranteeRotation();
|
||||
}
|
||||
|
||||
void Tridiagonal(void)
|
||||
{
|
||||
float fM00 = mElement[0][0];
|
||||
float fM01 = mElement[0][1];
|
||||
float fM02 = mElement[0][2];
|
||||
float fM11 = mElement[1][1];
|
||||
float fM12 = mElement[1][2];
|
||||
float fM22 = mElement[2][2];
|
||||
|
||||
m_afDiag[0] = fM00;
|
||||
m_afSubd[2] = 0;
|
||||
if (fM02 != (float)0.0)
|
||||
{
|
||||
float fLength = sqrtf(fM01 * fM01 + fM02 * fM02);
|
||||
float fInvLength = ((float)1.0) / fLength;
|
||||
fM01 *= fInvLength;
|
||||
fM02 *= fInvLength;
|
||||
float fQ = ((float)2.0) * fM01 * fM12 + fM02 * (fM22 - fM11);
|
||||
m_afDiag[1] = fM11 + fM02 * fQ;
|
||||
m_afDiag[2] = fM22 - fM02 * fQ;
|
||||
m_afSubd[0] = fLength;
|
||||
m_afSubd[1] = fM12 - fM01 * fQ;
|
||||
mElement[0][0] = (float)1.0;
|
||||
mElement[0][1] = (float)0.0;
|
||||
mElement[0][2] = (float)0.0;
|
||||
mElement[1][0] = (float)0.0;
|
||||
mElement[1][1] = fM01;
|
||||
mElement[1][2] = fM02;
|
||||
mElement[2][0] = (float)0.0;
|
||||
mElement[2][1] = fM02;
|
||||
mElement[2][2] = -fM01;
|
||||
m_bIsRotation = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_afDiag[1] = fM11;
|
||||
m_afDiag[2] = fM22;
|
||||
m_afSubd[0] = fM01;
|
||||
m_afSubd[1] = fM12;
|
||||
mElement[0][0] = (float)1.0;
|
||||
mElement[0][1] = (float)0.0;
|
||||
mElement[0][2] = (float)0.0;
|
||||
mElement[1][0] = (float)0.0;
|
||||
mElement[1][1] = (float)1.0;
|
||||
mElement[1][2] = (float)0.0;
|
||||
mElement[2][0] = (float)0.0;
|
||||
mElement[2][1] = (float)0.0;
|
||||
mElement[2][2] = (float)1.0;
|
||||
m_bIsRotation = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool QLAlgorithm(void)
|
||||
{
|
||||
const int iMaxIter = 32;
|
||||
|
||||
for (int i0 = 0; i0 < 3; i0++)
|
||||
{
|
||||
int i1;
|
||||
for (i1 = 0; i1 < iMaxIter; i1++)
|
||||
{
|
||||
int i2;
|
||||
for (i2 = i0; i2 <= (3 - 2); i2++)
|
||||
{
|
||||
float fTmp = fabsf(m_afDiag[i2]) + fabsf(m_afDiag[i2 + 1]);
|
||||
if (fabsf(m_afSubd[i2]) + fTmp == fTmp)
|
||||
break;
|
||||
}
|
||||
if (i2 == i0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
float fG = (m_afDiag[i0 + 1] - m_afDiag[i0]) / (((float)2.0) * m_afSubd[i0]);
|
||||
float fR = sqrtf(fG * fG + (float)1.0);
|
||||
if (fG < (float)0.0)
|
||||
{
|
||||
fG = m_afDiag[i2] - m_afDiag[i0] + m_afSubd[i0] / (fG - fR);
|
||||
}
|
||||
else
|
||||
{
|
||||
fG = m_afDiag[i2] - m_afDiag[i0] + m_afSubd[i0] / (fG + fR);
|
||||
}
|
||||
float fSin = (float)1.0, fCos = (float)1.0, fP = (float)0.0;
|
||||
for (int i3 = i2 - 1; i3 >= i0; i3--)
|
||||
{
|
||||
float fF = fSin * m_afSubd[i3];
|
||||
float fB = fCos * m_afSubd[i3];
|
||||
if (fabsf(fF) >= fabsf(fG))
|
||||
{
|
||||
fCos = fG / fF;
|
||||
fR = sqrtf(fCos * fCos + (float)1.0);
|
||||
m_afSubd[i3 + 1] = fF * fR;
|
||||
fSin = ((float)1.0) / fR;
|
||||
fCos *= fSin;
|
||||
}
|
||||
else
|
||||
{
|
||||
fSin = fF / fG;
|
||||
fR = sqrtf(fSin * fSin + (float)1.0);
|
||||
m_afSubd[i3 + 1] = fG * fR;
|
||||
fCos = ((float)1.0) / fR;
|
||||
fSin *= fCos;
|
||||
}
|
||||
fG = m_afDiag[i3 + 1] - fP;
|
||||
fR = (m_afDiag[i3] - fG) * fSin + ((float)2.0) * fB * fCos;
|
||||
fP = fSin * fR;
|
||||
m_afDiag[i3 + 1] = fG + fP;
|
||||
fG = fCos * fR - fB;
|
||||
for (int i4 = 0; i4 < 3; i4++)
|
||||
{
|
||||
fF = mElement[i4][i3 + 1];
|
||||
mElement[i4][i3 + 1] = fSin * mElement[i4][i3] + fCos * fF;
|
||||
mElement[i4][i3] = fCos * mElement[i4][i3] - fSin * fF;
|
||||
}
|
||||
}
|
||||
m_afDiag[i0] -= fP;
|
||||
m_afSubd[i0] = fG;
|
||||
m_afSubd[i2] = (float)0.0;
|
||||
}
|
||||
if (i1 == iMaxIter)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DecreasingSort(void)
|
||||
{
|
||||
//sort eigenvalues in decreasing order, e[0] >= ... >= e[iSize-1]
|
||||
for (int i0 = 0, i1; i0 <= 3 - 2; i0++)
|
||||
{
|
||||
// locate maximum eigenvalue
|
||||
i1 = i0;
|
||||
float fMax = m_afDiag[i1];
|
||||
int i2;
|
||||
for (i2 = i0 + 1; i2 < 3; i2++)
|
||||
{
|
||||
if (m_afDiag[i2] > fMax)
|
||||
{
|
||||
i1 = i2;
|
||||
fMax = m_afDiag[i1];
|
||||
}
|
||||
}
|
||||
|
||||
if (i1 != i0)
|
||||
{
|
||||
// swap eigenvalues
|
||||
m_afDiag[i1] = m_afDiag[i0];
|
||||
m_afDiag[i0] = fMax;
|
||||
// swap eigenvectors
|
||||
for (i2 = 0; i2 < 3; i2++)
|
||||
{
|
||||
float fTmp = mElement[i2][i0];
|
||||
mElement[i2][i0] = mElement[i2][i1];
|
||||
mElement[i2][i1] = fTmp;
|
||||
m_bIsRotation = !m_bIsRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuaranteeRotation(void)
|
||||
{
|
||||
if (!m_bIsRotation)
|
||||
{
|
||||
// change sign on the first column
|
||||
for (int iRow = 0; iRow < 3; iRow++)
|
||||
{
|
||||
mElement[iRow][0] = -mElement[iRow][0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float mElement[3][3];
|
||||
float m_afDiag[3];
|
||||
float m_afSubd[3];
|
||||
bool m_bIsRotation;
|
||||
};
|
||||
|
||||
} // namespace BestFit
|
||||
|
||||
using namespace BestFit;
|
||||
|
||||
bool getBestFitPlane(unsigned int vcount,
|
||||
const float *points,
|
||||
unsigned int vstride,
|
||||
const float *weights,
|
||||
unsigned int wstride,
|
||||
float *plane)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
Vec3 kOrigin(0, 0, 0);
|
||||
|
||||
float wtotal = 0;
|
||||
|
||||
if (1)
|
||||
{
|
||||
const char *source = (const char *)points;
|
||||
const char *wsource = (const char *)weights;
|
||||
|
||||
for (unsigned int i = 0; i < vcount; i++)
|
||||
{
|
||||
const float *p = (const float *)source;
|
||||
|
||||
float w = 1;
|
||||
|
||||
if (wsource)
|
||||
{
|
||||
const float *ws = (const float *)wsource;
|
||||
w = *ws; //
|
||||
wsource += wstride;
|
||||
}
|
||||
|
||||
kOrigin.x += p[0] * w;
|
||||
kOrigin.y += p[1] * w;
|
||||
kOrigin.z += p[2] * w;
|
||||
|
||||
wtotal += w;
|
||||
|
||||
source += vstride;
|
||||
}
|
||||
}
|
||||
|
||||
float recip = 1.0f / wtotal; // reciprocol of total weighting
|
||||
|
||||
kOrigin.x *= recip;
|
||||
kOrigin.y *= recip;
|
||||
kOrigin.z *= recip;
|
||||
|
||||
float fSumXX = 0;
|
||||
float fSumXY = 0;
|
||||
float fSumXZ = 0;
|
||||
|
||||
float fSumYY = 0;
|
||||
float fSumYZ = 0;
|
||||
float fSumZZ = 0;
|
||||
|
||||
if (1)
|
||||
{
|
||||
const char *source = (const char *)points;
|
||||
const char *wsource = (const char *)weights;
|
||||
|
||||
for (unsigned int i = 0; i < vcount; i++)
|
||||
{
|
||||
const float *p = (const float *)source;
|
||||
|
||||
float w = 1;
|
||||
|
||||
if (wsource)
|
||||
{
|
||||
const float *ws = (const float *)wsource;
|
||||
w = *ws; //
|
||||
wsource += wstride;
|
||||
}
|
||||
|
||||
Vec3 kDiff;
|
||||
|
||||
kDiff.x = w * (p[0] - kOrigin.x); // apply vertex weighting!
|
||||
kDiff.y = w * (p[1] - kOrigin.y);
|
||||
kDiff.z = w * (p[2] - kOrigin.z);
|
||||
|
||||
fSumXX += kDiff.x * kDiff.x; // sume of the squares of the differences.
|
||||
fSumXY += kDiff.x * kDiff.y; // sume of the squares of the differences.
|
||||
fSumXZ += kDiff.x * kDiff.z; // sume of the squares of the differences.
|
||||
|
||||
fSumYY += kDiff.y * kDiff.y;
|
||||
fSumYZ += kDiff.y * kDiff.z;
|
||||
fSumZZ += kDiff.z * kDiff.z;
|
||||
|
||||
source += vstride;
|
||||
}
|
||||
}
|
||||
|
||||
fSumXX *= recip;
|
||||
fSumXY *= recip;
|
||||
fSumXZ *= recip;
|
||||
fSumYY *= recip;
|
||||
fSumYZ *= recip;
|
||||
fSumZZ *= recip;
|
||||
|
||||
// setup the eigensolver
|
||||
Eigen kES;
|
||||
|
||||
kES.mElement[0][0] = fSumXX;
|
||||
kES.mElement[0][1] = fSumXY;
|
||||
kES.mElement[0][2] = fSumXZ;
|
||||
|
||||
kES.mElement[1][0] = fSumXY;
|
||||
kES.mElement[1][1] = fSumYY;
|
||||
kES.mElement[1][2] = fSumYZ;
|
||||
|
||||
kES.mElement[2][0] = fSumXZ;
|
||||
kES.mElement[2][1] = fSumYZ;
|
||||
kES.mElement[2][2] = fSumZZ;
|
||||
|
||||
// compute eigenstuff, smallest eigenvalue is in last position
|
||||
kES.DecrSortEigenStuff();
|
||||
|
||||
Vec3 kNormal;
|
||||
|
||||
kNormal.x = kES.mElement[0][2];
|
||||
kNormal.y = kES.mElement[1][2];
|
||||
kNormal.z = kES.mElement[2][2];
|
||||
|
||||
// the minimum energy
|
||||
plane[0] = kNormal.x;
|
||||
plane[1] = kNormal.y;
|
||||
plane[2] = kNormal.z;
|
||||
|
||||
plane[3] = 0 - kNormal.dot(kOrigin);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
float getBoundingRegion(unsigned int vcount, const float *points, unsigned int pstride, float *bmin, float *bmax) // returns the diagonal distance
|
||||
{
|
||||
const unsigned char *source = (const unsigned char *)points;
|
||||
|
||||
bmin[0] = points[0];
|
||||
bmin[1] = points[1];
|
||||
bmin[2] = points[2];
|
||||
|
||||
bmax[0] = points[0];
|
||||
bmax[1] = points[1];
|
||||
bmax[2] = points[2];
|
||||
|
||||
for (unsigned int i = 1; i < vcount; i++)
|
||||
{
|
||||
source += pstride;
|
||||
const float *p = (const float *)source;
|
||||
|
||||
if (p[0] < bmin[0]) bmin[0] = p[0];
|
||||
if (p[1] < bmin[1]) bmin[1] = p[1];
|
||||
if (p[2] < bmin[2]) bmin[2] = p[2];
|
||||
|
||||
if (p[0] > bmax[0]) bmax[0] = p[0];
|
||||
if (p[1] > bmax[1]) bmax[1] = p[1];
|
||||
if (p[2] > bmax[2]) bmax[2] = p[2];
|
||||
}
|
||||
|
||||
float dx = bmax[0] - bmin[0];
|
||||
float dy = bmax[1] - bmin[1];
|
||||
float dz = bmax[2] - bmin[2];
|
||||
|
||||
return sqrtf(dx * dx + dy * dy + dz * dz);
|
||||
}
|
||||
|
||||
bool overlapAABB(const float *bmin1, const float *bmax1, const float *bmin2, const float *bmax2) // return true if the two AABB's overlap.
|
||||
{
|
||||
if (bmax2[0] < bmin1[0]) return false; // if the maximum is less than our minimum on any axis
|
||||
if (bmax2[1] < bmin1[1]) return false;
|
||||
if (bmax2[2] < bmin1[2]) return false;
|
||||
|
||||
if (bmin2[0] > bmax1[0]) return false; // if the minimum is greater than our maximum on any axis
|
||||
if (bmin2[1] > bmax1[1]) return false; // if the minimum is greater than our maximum on any axis
|
||||
if (bmin2[2] > bmax1[2]) return false; // if the minimum is greater than our maximum on any axis
|
||||
|
||||
return true; // the extents overlap
|
||||
}
|
||||
63
Engine/lib/bullet/Extras/ConvexDecomposition/bestfit.h
Normal file
63
Engine/lib/bullet/Extras/ConvexDecomposition/bestfit.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#ifndef BEST_FIT_H
|
||||
|
||||
#define BEST_FIT_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
// This routine was released in 'snippet' form
|
||||
// by John W. Ratcliff mailto:jratcliff@infiniplex.net
|
||||
// on March 22, 2006.
|
||||
//
|
||||
// This routine computes the 'best fit' plane equation to
|
||||
// a set of input data points with an optional per vertex
|
||||
// weighting component.
|
||||
//
|
||||
// The implementation for this was lifted directly from
|
||||
// David Eberly's Magic Software implementation.
|
||||
|
||||
// computes the best fit plane to a collection of data points.
|
||||
// returns the plane equation as A,B,C,D format. (Ax+By+Cz+D)
|
||||
|
||||
bool getBestFitPlane(unsigned int vcount, // number of input data points
|
||||
const float *points, // starting address of points array.
|
||||
unsigned int vstride, // stride between input points.
|
||||
const float *weights, // *optional point weighting values.
|
||||
unsigned int wstride, // weight stride for each vertex.
|
||||
float *plane);
|
||||
|
||||
float getBoundingRegion(unsigned int vcount, const float *points, unsigned int pstride, float *bmin, float *bmax); // returns the diagonal distance
|
||||
bool overlapAABB(const float *bmin1, const float *bmax1, const float *bmin2, const float *bmax2); // return true if the two AABB's overlap.
|
||||
|
||||
#endif
|
||||
166
Engine/lib/bullet/Extras/ConvexDecomposition/bestfitobb.cpp
Normal file
166
Engine/lib/bullet/Extras/ConvexDecomposition/bestfitobb.cpp
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
#include "float_math.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
#include "bestfitobb.h"
|
||||
#include "float_math.h"
|
||||
|
||||
// computes the OBB for this set of points relative to this transform matrix.
|
||||
void computeOBB(unsigned int vcount, const float *points, unsigned int pstride, float *sides, const float *matrix)
|
||||
{
|
||||
const char *src = (const char *)points;
|
||||
|
||||
float bmin[3] = {1e9, 1e9, 1e9};
|
||||
float bmax[3] = {-1e9, -1e9, -1e9};
|
||||
|
||||
for (unsigned int i = 0; i < vcount; i++)
|
||||
{
|
||||
const float *p = (const float *)src;
|
||||
float t[3];
|
||||
|
||||
fm_inverseRT(matrix, p, t); // inverse rotate translate
|
||||
|
||||
if (t[0] < bmin[0]) bmin[0] = t[0];
|
||||
if (t[1] < bmin[1]) bmin[1] = t[1];
|
||||
if (t[2] < bmin[2]) bmin[2] = t[2];
|
||||
|
||||
if (t[0] > bmax[0]) bmax[0] = t[0];
|
||||
if (t[1] > bmax[1]) bmax[1] = t[1];
|
||||
if (t[2] > bmax[2]) bmax[2] = t[2];
|
||||
|
||||
src += pstride;
|
||||
}
|
||||
|
||||
sides[0] = bmax[0];
|
||||
sides[1] = bmax[1];
|
||||
sides[2] = bmax[2];
|
||||
|
||||
if (fabsf(bmin[0]) > sides[0]) sides[0] = fabsf(bmin[0]);
|
||||
if (fabsf(bmin[1]) > sides[1]) sides[1] = fabsf(bmin[1]);
|
||||
if (fabsf(bmin[2]) > sides[2]) sides[2] = fabsf(bmin[2]);
|
||||
|
||||
sides[0] *= 2.0f;
|
||||
sides[1] *= 2.0f;
|
||||
sides[2] *= 2.0f;
|
||||
}
|
||||
|
||||
void computeBestFitOBB(unsigned int vcount, const float *points, unsigned int pstride, float *sides, float *matrix)
|
||||
{
|
||||
float bmin[3];
|
||||
float bmax[3];
|
||||
|
||||
fm_getAABB(vcount, points, pstride, bmin, bmax);
|
||||
|
||||
float center[3];
|
||||
|
||||
center[0] = (bmax[0] - bmin[0]) * 0.5f + bmin[0];
|
||||
center[1] = (bmax[1] - bmin[1]) * 0.5f + bmin[1];
|
||||
center[2] = (bmax[2] - bmin[2]) * 0.5f + bmin[2];
|
||||
|
||||
float ax = 0;
|
||||
float ay = 0;
|
||||
float az = 0;
|
||||
|
||||
float sweep = 45.0f; // 180 degree sweep on all three axes.
|
||||
float steps = 8.0f; // 16 steps on each axis.
|
||||
|
||||
float bestVolume = 1e9;
|
||||
float angle[3] = {0.f, 0.f, 0.f};
|
||||
|
||||
while (sweep >= 1)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
float stepsize = sweep / steps;
|
||||
|
||||
for (float x = ax - sweep; x <= ax + sweep; x += stepsize)
|
||||
{
|
||||
for (float y = ay - sweep; y <= ay + sweep; y += stepsize)
|
||||
{
|
||||
for (float z = az - sweep; z <= az + sweep; z += stepsize)
|
||||
{
|
||||
float pmatrix[16];
|
||||
|
||||
fm_eulerMatrix(x * FM_DEG_TO_RAD, y * FM_DEG_TO_RAD, z * FM_DEG_TO_RAD, pmatrix);
|
||||
|
||||
pmatrix[3 * 4 + 0] = center[0];
|
||||
pmatrix[3 * 4 + 1] = center[1];
|
||||
pmatrix[3 * 4 + 2] = center[2];
|
||||
|
||||
float psides[3];
|
||||
|
||||
computeOBB(vcount, points, pstride, psides, pmatrix);
|
||||
|
||||
float volume = psides[0] * psides[1] * psides[2]; // the volume of the cube
|
||||
|
||||
if (volume <= bestVolume)
|
||||
{
|
||||
bestVolume = volume;
|
||||
|
||||
sides[0] = psides[0];
|
||||
sides[1] = psides[1];
|
||||
sides[2] = psides[2];
|
||||
|
||||
angle[0] = ax;
|
||||
angle[1] = ay;
|
||||
angle[2] = az;
|
||||
|
||||
memcpy(matrix, pmatrix, sizeof(float) * 16);
|
||||
found = true; // yes, we found an improvement.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
ax = angle[0];
|
||||
ay = angle[1];
|
||||
az = angle[2];
|
||||
|
||||
sweep *= 0.5f; // sweep 1/2 the distance as the last time.
|
||||
}
|
||||
else
|
||||
{
|
||||
break; // no improvement, so just
|
||||
}
|
||||
}
|
||||
}
|
||||
41
Engine/lib/bullet/Extras/ConvexDecomposition/bestfitobb.h
Normal file
41
Engine/lib/bullet/Extras/ConvexDecomposition/bestfitobb.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef BEST_FIT_OBB_H
|
||||
|
||||
#define BEST_FIT_OBB_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
void computeBestFitOBB(unsigned int vcount, const float *points, unsigned int pstride, float *sides, float *matrix);
|
||||
|
||||
#endif
|
||||
3370
Engine/lib/bullet/Extras/ConvexDecomposition/cd_hull.cpp
Normal file
3370
Engine/lib/bullet/Extras/ConvexDecomposition/cd_hull.cpp
Normal file
File diff suppressed because it is too large
Load diff
148
Engine/lib/bullet/Extras/ConvexDecomposition/cd_hull.h
Normal file
148
Engine/lib/bullet/Extras/ConvexDecomposition/cd_hull.h
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
#ifndef CD_HULL_H
|
||||
|
||||
#define CD_HULL_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
class HullResult
|
||||
{
|
||||
public:
|
||||
HullResult(void)
|
||||
{
|
||||
mPolygons = true;
|
||||
mNumOutputVertices = 0;
|
||||
mOutputVertices = 0;
|
||||
mNumFaces = 0;
|
||||
mNumIndices = 0;
|
||||
mIndices = 0;
|
||||
}
|
||||
bool mPolygons; // true if indices represents polygons, false indices are triangles
|
||||
unsigned int mNumOutputVertices; // number of vertices in the output hull
|
||||
float *mOutputVertices; // array of vertices, 3 floats each x,y,z
|
||||
unsigned int mNumFaces; // the number of faces produced
|
||||
unsigned int mNumIndices; // the total number of indices
|
||||
unsigned int *mIndices; // pointer to indices.
|
||||
|
||||
// If triangles, then indices are array indexes into the vertex list.
|
||||
// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
|
||||
};
|
||||
|
||||
enum HullFlag
|
||||
{
|
||||
QF_TRIANGLES = (1 << 0), // report results as triangles, not polygons.
|
||||
QF_REVERSE_ORDER = (1 << 1), // reverse order of the triangle indices.
|
||||
QF_SKIN_WIDTH = (1 << 2), // extrude hull based on this skin width
|
||||
QF_DEFAULT = 0
|
||||
};
|
||||
|
||||
class HullDesc
|
||||
{
|
||||
public:
|
||||
HullDesc(void)
|
||||
{
|
||||
mFlags = QF_DEFAULT;
|
||||
mVcount = 0;
|
||||
mVertices = 0;
|
||||
mVertexStride = sizeof(float) * 3;
|
||||
mNormalEpsilon = 0.001f;
|
||||
mMaxVertices = 4096; // maximum number of points to be considered for a convex hull.
|
||||
mMaxFaces = 4096;
|
||||
mSkinWidth = 0.01f; // default is one centimeter
|
||||
};
|
||||
|
||||
HullDesc(HullFlag flag,
|
||||
unsigned int vcount,
|
||||
const float *vertices,
|
||||
unsigned int stride)
|
||||
{
|
||||
mFlags = flag;
|
||||
mVcount = vcount;
|
||||
mVertices = vertices;
|
||||
mVertexStride = stride;
|
||||
mNormalEpsilon = 0.001f;
|
||||
mMaxVertices = 4096;
|
||||
mSkinWidth = 0.01f; // default is one centimeter
|
||||
}
|
||||
|
||||
bool HasHullFlag(HullFlag flag) const
|
||||
{
|
||||
if (mFlags & flag) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetHullFlag(HullFlag flag)
|
||||
{
|
||||
mFlags |= flag;
|
||||
}
|
||||
|
||||
void ClearHullFlag(HullFlag flag)
|
||||
{
|
||||
mFlags &= ~flag;
|
||||
}
|
||||
|
||||
unsigned int mFlags; // flags to use when generating the convex hull.
|
||||
unsigned int mVcount; // number of vertices in the input point cloud
|
||||
const float *mVertices; // the array of vertices.
|
||||
unsigned int mVertexStride; // the stride of each vertex, in bytes.
|
||||
float mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
|
||||
float mSkinWidth;
|
||||
unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull!
|
||||
unsigned int mMaxFaces;
|
||||
};
|
||||
|
||||
enum HullError
|
||||
{
|
||||
QE_OK, // success!
|
||||
QE_FAIL // failed.
|
||||
};
|
||||
|
||||
class HullLibrary
|
||||
{
|
||||
public:
|
||||
HullError CreateConvexHull(const HullDesc &desc, // describes the input request
|
||||
HullResult &result); // contains the resulst
|
||||
|
||||
HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it.
|
||||
|
||||
private:
|
||||
void BringOutYourDead(const float *verts, unsigned int vcount, float *overts, unsigned int &ocount, unsigned int *indices, unsigned indexcount);
|
||||
|
||||
bool CleanupVertices(unsigned int svcount,
|
||||
const float *svertices,
|
||||
unsigned int stride,
|
||||
unsigned int &vcount, // output number of vertices
|
||||
float *vertices, // location to store the results.
|
||||
float normalepsilon,
|
||||
float *scale);
|
||||
};
|
||||
|
||||
} // namespace ConvexDecomposition
|
||||
|
||||
#endif
|
||||
1192
Engine/lib/bullet/Extras/ConvexDecomposition/cd_vector.h
Normal file
1192
Engine/lib/bullet/Extras/ConvexDecomposition/cd_vector.h
Normal file
File diff suppressed because it is too large
Load diff
824
Engine/lib/bullet/Extras/ConvexDecomposition/cd_wavefront.cpp
Normal file
824
Engine/lib/bullet/Extras/ConvexDecomposition/cd_wavefront.cpp
Normal file
|
|
@ -0,0 +1,824 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
#include "float_math.h"
|
||||
|
||||
#include "cd_wavefront.h"
|
||||
|
||||
using namespace ConvexDecomposition;
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
typedef std::vector<int> IntVector;
|
||||
typedef std::vector<float> FloatVector;
|
||||
|
||||
#if defined(__APPLE__) || defined(__CELLOS_LV2__)
|
||||
#define stricmp(a, b) strcasecmp((a), (b))
|
||||
#endif
|
||||
|
||||
/*******************************************************************/
|
||||
/******************** InParser.h ********************************/
|
||||
/*******************************************************************/
|
||||
class InPlaceParserInterface
|
||||
{
|
||||
public:
|
||||
virtual ~InPlaceParserInterface(){};
|
||||
|
||||
virtual int ParseLine(int lineno, int argc, const char **argv) = 0; // return TRUE to continue parsing, return FALSE to abort parsing process
|
||||
};
|
||||
|
||||
enum SeparatorType
|
||||
{
|
||||
ST_DATA, // is data
|
||||
ST_HARD, // is a hard separator
|
||||
ST_SOFT, // is a soft separator
|
||||
ST_EOS // is a comment symbol, and everything past this character should be ignored
|
||||
};
|
||||
|
||||
class InPlaceParser
|
||||
{
|
||||
public:
|
||||
InPlaceParser(void)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
InPlaceParser(char *data, int len)
|
||||
{
|
||||
Init();
|
||||
SetSourceData(data, len);
|
||||
}
|
||||
|
||||
InPlaceParser(const char *fname)
|
||||
{
|
||||
Init();
|
||||
SetFile(fname);
|
||||
}
|
||||
|
||||
~InPlaceParser(void);
|
||||
|
||||
void Init(void)
|
||||
{
|
||||
mQuoteChar = 34;
|
||||
mData = 0;
|
||||
mLen = 0;
|
||||
mMyAlloc = false;
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
mHard[i] = ST_DATA;
|
||||
mHardString[i * 2] = i;
|
||||
mHardString[i * 2 + 1] = 0;
|
||||
}
|
||||
mHard[0] = ST_EOS;
|
||||
mHard[32] = ST_SOFT;
|
||||
mHard[9] = ST_SOFT;
|
||||
mHard[13] = ST_SOFT;
|
||||
mHard[10] = ST_SOFT;
|
||||
}
|
||||
|
||||
void SetFile(const char *fname); // use this file as source data to parse.
|
||||
|
||||
void SetSourceData(char *data, int len)
|
||||
{
|
||||
mData = data;
|
||||
mLen = len;
|
||||
mMyAlloc = false;
|
||||
};
|
||||
|
||||
int Parse(InPlaceParserInterface *callback); // returns true if entire file was parsed, false if it aborted for some reason
|
||||
|
||||
int ProcessLine(int lineno, char *line, InPlaceParserInterface *callback);
|
||||
|
||||
const char **GetArglist(char *source, int &count); // convert source string into an arg list, this is a destructive parse.
|
||||
|
||||
void SetHardSeparator(char c) // add a hard separator
|
||||
{
|
||||
mHard[(int)c] = ST_HARD;
|
||||
}
|
||||
|
||||
void SetHard(char c) // add a hard separator
|
||||
{
|
||||
mHard[(int)c] = ST_HARD;
|
||||
}
|
||||
|
||||
void SetCommentSymbol(char c) // comment character, treated as 'end of string'
|
||||
{
|
||||
mHard[(int)c] = ST_EOS;
|
||||
}
|
||||
|
||||
void ClearHardSeparator(char c)
|
||||
{
|
||||
mHard[(int)c] = ST_DATA;
|
||||
}
|
||||
|
||||
void DefaultSymbols(void); // set up default symbols for hard separator and comment symbol of the '#' character.
|
||||
|
||||
bool EOS(char c)
|
||||
{
|
||||
if (mHard[(int)c] == ST_EOS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetQuoteChar(char c)
|
||||
{
|
||||
mQuoteChar = c;
|
||||
}
|
||||
|
||||
private:
|
||||
inline char *AddHard(int &argc, const char **argv, char *foo);
|
||||
inline bool IsHard(char c);
|
||||
inline char *SkipSpaces(char *foo);
|
||||
inline bool IsWhiteSpace(char c);
|
||||
inline bool IsNonSeparator(char c); // non separator, neither hard nor soft
|
||||
|
||||
bool mMyAlloc; // whether or not *I* allocated the buffer and am responsible for deleting it.
|
||||
char *mData; // ascii data to parse.
|
||||
int mLen; // length of data
|
||||
SeparatorType mHard[256];
|
||||
char mHardString[256 * 2];
|
||||
char mQuoteChar;
|
||||
};
|
||||
|
||||
/*******************************************************************/
|
||||
/******************** InParser.cpp ********************************/
|
||||
/*******************************************************************/
|
||||
void InPlaceParser::SetFile(const char *fname)
|
||||
{
|
||||
if (mMyAlloc)
|
||||
{
|
||||
free(mData);
|
||||
}
|
||||
mData = 0;
|
||||
mLen = 0;
|
||||
mMyAlloc = false;
|
||||
|
||||
FILE *fph = fopen(fname, "rb");
|
||||
if (fph)
|
||||
{
|
||||
fseek(fph, 0L, SEEK_END);
|
||||
mLen = ftell(fph);
|
||||
fseek(fph, 0L, SEEK_SET);
|
||||
if (mLen)
|
||||
{
|
||||
mData = (char *)malloc(sizeof(char) * (mLen + 1));
|
||||
int ok = fread(mData, mLen, 1, fph);
|
||||
if (!ok)
|
||||
{
|
||||
free(mData);
|
||||
mData = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mData[mLen] = 0; // zero byte terminate end of file marker.
|
||||
mMyAlloc = true;
|
||||
}
|
||||
}
|
||||
fclose(fph);
|
||||
}
|
||||
}
|
||||
|
||||
InPlaceParser::~InPlaceParser(void)
|
||||
{
|
||||
if (mMyAlloc)
|
||||
{
|
||||
free(mData);
|
||||
}
|
||||
}
|
||||
|
||||
#define MAXARGS 512
|
||||
|
||||
bool InPlaceParser::IsHard(char c)
|
||||
{
|
||||
return mHard[(int)c] == ST_HARD;
|
||||
}
|
||||
|
||||
char *InPlaceParser::AddHard(int &argc, const char **argv, char *foo)
|
||||
{
|
||||
while (IsHard(*foo))
|
||||
{
|
||||
const char *hard = &mHardString[*foo * 2];
|
||||
if (argc < MAXARGS)
|
||||
{
|
||||
argv[argc++] = hard;
|
||||
}
|
||||
foo++;
|
||||
}
|
||||
return foo;
|
||||
}
|
||||
|
||||
bool InPlaceParser::IsWhiteSpace(char c)
|
||||
{
|
||||
return mHard[(int)c] == ST_SOFT;
|
||||
}
|
||||
|
||||
char *InPlaceParser::SkipSpaces(char *foo)
|
||||
{
|
||||
while (!EOS(*foo) && IsWhiteSpace(*foo)) foo++;
|
||||
return foo;
|
||||
}
|
||||
|
||||
bool InPlaceParser::IsNonSeparator(char c)
|
||||
{
|
||||
if (!IsHard(c) && !IsWhiteSpace(c) && c != 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int InPlaceParser::ProcessLine(int lineno, char *line, InPlaceParserInterface *callback)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
const char *argv[MAXARGS];
|
||||
int argc = 0;
|
||||
|
||||
char *foo = line;
|
||||
|
||||
while (!EOS(*foo) && argc < MAXARGS)
|
||||
{
|
||||
foo = SkipSpaces(foo); // skip any leading spaces
|
||||
|
||||
if (EOS(*foo)) break;
|
||||
|
||||
if (*foo == mQuoteChar) // if it is an open quote
|
||||
{
|
||||
foo++;
|
||||
if (argc < MAXARGS)
|
||||
{
|
||||
argv[argc++] = foo;
|
||||
}
|
||||
while (!EOS(*foo) && *foo != mQuoteChar) foo++;
|
||||
if (!EOS(*foo))
|
||||
{
|
||||
*foo = 0; // replace close quote with zero byte EOS
|
||||
foo++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foo = AddHard(argc, argv, foo); // add any hard separators, skip any spaces
|
||||
|
||||
if (IsNonSeparator(*foo)) // add non-hard argument.
|
||||
{
|
||||
bool quote = false;
|
||||
if (*foo == mQuoteChar)
|
||||
{
|
||||
foo++;
|
||||
quote = true;
|
||||
}
|
||||
|
||||
if (argc < MAXARGS)
|
||||
{
|
||||
argv[argc++] = foo;
|
||||
}
|
||||
|
||||
if (quote)
|
||||
{
|
||||
while (*foo && *foo != mQuoteChar) foo++;
|
||||
if (*foo) *foo = 32;
|
||||
}
|
||||
|
||||
// continue..until we hit an eos ..
|
||||
while (!EOS(*foo)) // until we hit EOS
|
||||
{
|
||||
if (IsWhiteSpace(*foo)) // if we hit a space, stomp a zero byte, and exit
|
||||
{
|
||||
*foo = 0;
|
||||
foo++;
|
||||
break;
|
||||
}
|
||||
else if (IsHard(*foo)) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
|
||||
{
|
||||
const char *hard = &mHardString[*foo * 2];
|
||||
*foo = 0;
|
||||
if (argc < MAXARGS)
|
||||
{
|
||||
argv[argc++] = hard;
|
||||
}
|
||||
foo++;
|
||||
break;
|
||||
}
|
||||
foo++;
|
||||
} // end of while loop...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argc)
|
||||
{
|
||||
ret = callback->ParseLine(lineno, argc, argv);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int InPlaceParser::Parse(InPlaceParserInterface *callback) // returns true if entire file was parsed, false if it aborted for some reason
|
||||
{
|
||||
assert(callback);
|
||||
if (!mData) return 0;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
int lineno = 0;
|
||||
|
||||
char *foo = mData;
|
||||
char *begin = foo;
|
||||
|
||||
while (*foo)
|
||||
{
|
||||
if (*foo == 10 || *foo == 13)
|
||||
{
|
||||
lineno++;
|
||||
*foo = 0;
|
||||
|
||||
if (*begin) // if there is any data to parse at all...
|
||||
{
|
||||
int v = ProcessLine(lineno, begin, callback);
|
||||
if (v) ret = v;
|
||||
}
|
||||
|
||||
foo++;
|
||||
if (*foo == 10) foo++; // skip line feed, if it is in the carraige-return line-feed format...
|
||||
begin = foo;
|
||||
}
|
||||
else
|
||||
{
|
||||
foo++;
|
||||
}
|
||||
}
|
||||
|
||||
lineno++; // lasst line.
|
||||
|
||||
int v = ProcessLine(lineno, begin, callback);
|
||||
if (v) ret = v;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void InPlaceParser::DefaultSymbols(void)
|
||||
{
|
||||
SetHardSeparator(',');
|
||||
SetHardSeparator('(');
|
||||
SetHardSeparator(')');
|
||||
SetHardSeparator('=');
|
||||
SetHardSeparator('[');
|
||||
SetHardSeparator(']');
|
||||
SetHardSeparator('{');
|
||||
SetHardSeparator('}');
|
||||
SetCommentSymbol('#');
|
||||
}
|
||||
|
||||
const char **InPlaceParser::GetArglist(char *line, int &count) // convert source string into an arg list, this is a destructive parse.
|
||||
{
|
||||
const char **ret = 0;
|
||||
|
||||
static const char *argv[MAXARGS];
|
||||
int argc = 0;
|
||||
|
||||
char *foo = line;
|
||||
|
||||
while (!EOS(*foo) && argc < MAXARGS)
|
||||
{
|
||||
foo = SkipSpaces(foo); // skip any leading spaces
|
||||
|
||||
if (EOS(*foo)) break;
|
||||
|
||||
if (*foo == mQuoteChar) // if it is an open quote
|
||||
{
|
||||
foo++;
|
||||
if (argc < MAXARGS)
|
||||
{
|
||||
argv[argc++] = foo;
|
||||
}
|
||||
while (!EOS(*foo) && *foo != mQuoteChar) foo++;
|
||||
if (!EOS(*foo))
|
||||
{
|
||||
*foo = 0; // replace close quote with zero byte EOS
|
||||
foo++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foo = AddHard(argc, argv, foo); // add any hard separators, skip any spaces
|
||||
|
||||
if (IsNonSeparator(*foo)) // add non-hard argument.
|
||||
{
|
||||
bool quote = false;
|
||||
if (*foo == mQuoteChar)
|
||||
{
|
||||
foo++;
|
||||
quote = true;
|
||||
}
|
||||
|
||||
if (argc < MAXARGS)
|
||||
{
|
||||
argv[argc++] = foo;
|
||||
}
|
||||
|
||||
if (quote)
|
||||
{
|
||||
while (*foo && *foo != mQuoteChar) foo++;
|
||||
if (*foo) *foo = 32;
|
||||
}
|
||||
|
||||
// continue..until we hit an eos ..
|
||||
while (!EOS(*foo)) // until we hit EOS
|
||||
{
|
||||
if (IsWhiteSpace(*foo)) // if we hit a space, stomp a zero byte, and exit
|
||||
{
|
||||
*foo = 0;
|
||||
foo++;
|
||||
break;
|
||||
}
|
||||
else if (IsHard(*foo)) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
|
||||
{
|
||||
const char *hard = &mHardString[*foo * 2];
|
||||
*foo = 0;
|
||||
if (argc < MAXARGS)
|
||||
{
|
||||
argv[argc++] = hard;
|
||||
}
|
||||
foo++;
|
||||
break;
|
||||
}
|
||||
foo++;
|
||||
} // end of while loop...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count = argc;
|
||||
if (argc)
|
||||
{
|
||||
ret = argv;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
/******************** Geometry.h ********************************/
|
||||
/*******************************************************************/
|
||||
|
||||
class GeometryVertex
|
||||
{
|
||||
public:
|
||||
float mPos[3];
|
||||
float mNormal[3];
|
||||
float mTexel[2];
|
||||
};
|
||||
|
||||
class GeometryInterface
|
||||
{
|
||||
public:
|
||||
virtual void NodeTriangle(const GeometryVertex *v1, const GeometryVertex *v2, const GeometryVertex *v3) {}
|
||||
|
||||
virtual ~GeometryInterface() {}
|
||||
};
|
||||
|
||||
/*******************************************************************/
|
||||
/******************** Obj.h ********************************/
|
||||
/*******************************************************************/
|
||||
|
||||
class OBJ : public InPlaceParserInterface
|
||||
{
|
||||
public:
|
||||
int LoadMesh(const char *fname, GeometryInterface *callback);
|
||||
int ParseLine(int lineno, int argc, const char **argv); // return TRUE to continue parsing, return FALSE to abort parsing process
|
||||
private:
|
||||
void getVertex(GeometryVertex &v, const char *face) const;
|
||||
|
||||
FloatVector mVerts;
|
||||
FloatVector mTexels;
|
||||
FloatVector mNormals;
|
||||
|
||||
GeometryInterface *mCallback;
|
||||
};
|
||||
|
||||
/*******************************************************************/
|
||||
/******************** Obj.cpp ********************************/
|
||||
/*******************************************************************/
|
||||
|
||||
int OBJ::LoadMesh(const char *fname, GeometryInterface *iface)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mVerts.clear();
|
||||
mTexels.clear();
|
||||
mNormals.clear();
|
||||
|
||||
mCallback = iface;
|
||||
|
||||
InPlaceParser ipp(fname);
|
||||
|
||||
ipp.Parse(this);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//static const char * GetArg(const char **argv,int i,int argc)
|
||||
//{
|
||||
// const char * ret = 0;
|
||||
// if ( i < argc ) ret = argv[i];
|
||||
// return ret;
|
||||
//}
|
||||
|
||||
void OBJ::getVertex(GeometryVertex &v, const char *face) const
|
||||
{
|
||||
v.mPos[0] = 0;
|
||||
v.mPos[1] = 0;
|
||||
v.mPos[2] = 0;
|
||||
|
||||
v.mTexel[0] = 0;
|
||||
v.mTexel[1] = 0;
|
||||
|
||||
v.mNormal[0] = 0;
|
||||
v.mNormal[1] = 1;
|
||||
v.mNormal[2] = 0;
|
||||
|
||||
int index = atoi(face) - 1;
|
||||
|
||||
const char *texel = strstr(face, "/");
|
||||
|
||||
if (texel)
|
||||
{
|
||||
int tindex = atoi(texel + 1) - 1;
|
||||
|
||||
if (tindex >= 0 && tindex < (int)(mTexels.size() / 2))
|
||||
{
|
||||
const float *t = &mTexels[tindex * 2];
|
||||
|
||||
v.mTexel[0] = t[0];
|
||||
v.mTexel[1] = t[1];
|
||||
}
|
||||
|
||||
const char *normal = strstr(texel + 1, "/");
|
||||
if (normal)
|
||||
{
|
||||
int nindex = atoi(normal + 1) - 1;
|
||||
|
||||
if (nindex >= 0 && nindex < (int)(mNormals.size() / 3))
|
||||
{
|
||||
const float *n = &mNormals[nindex * 3];
|
||||
|
||||
v.mNormal[0] = n[0];
|
||||
v.mNormal[1] = n[1];
|
||||
v.mNormal[2] = n[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index >= 0 && index < (int)(mVerts.size() / 3))
|
||||
{
|
||||
const float *p = &mVerts[index * 3];
|
||||
|
||||
v.mPos[0] = p[0];
|
||||
v.mPos[1] = p[1];
|
||||
v.mPos[2] = p[2];
|
||||
}
|
||||
}
|
||||
|
||||
int OBJ::ParseLine(int lineno, int argc, const char **argv) // return TRUE to continue parsing, return FALSE to abort parsing process
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (argc >= 1)
|
||||
{
|
||||
const char *foo = argv[0];
|
||||
if (*foo != '#')
|
||||
{
|
||||
if (strcmp(argv[0], "v") == 0 && argc == 4)
|
||||
|
||||
//if ( stricmp(argv[0],"v") == 0 && argc == 4 )
|
||||
{
|
||||
float vx = (float)atof(argv[1]);
|
||||
float vy = (float)atof(argv[2]);
|
||||
float vz = (float)atof(argv[3]);
|
||||
mVerts.push_back(vx);
|
||||
mVerts.push_back(vy);
|
||||
mVerts.push_back(vz);
|
||||
}
|
||||
else if (strcmp(argv[0], "vt") == 0 && argc == 3)
|
||||
|
||||
// else if ( stricmp(argv[0],"vt") == 0 && argc == 3 )
|
||||
{
|
||||
float tx = (float)atof(argv[1]);
|
||||
float ty = (float)atof(argv[2]);
|
||||
mTexels.push_back(tx);
|
||||
mTexels.push_back(ty);
|
||||
}
|
||||
// else if ( stricmp(argv[0],"vn") == 0 && argc == 4 )
|
||||
|
||||
else if (strcmp(argv[0], "vn") == 0 && argc == 4)
|
||||
{
|
||||
float normalx = (float)atof(argv[1]);
|
||||
float normaly = (float)atof(argv[2]);
|
||||
float normalz = (float)atof(argv[3]);
|
||||
mNormals.push_back(normalx);
|
||||
mNormals.push_back(normaly);
|
||||
mNormals.push_back(normalz);
|
||||
}
|
||||
// else if ( stricmp(argv[0],"f") == 0 && argc >= 4 )
|
||||
|
||||
else if (strcmp(argv[0], "f") == 0 && argc >= 4)
|
||||
{
|
||||
GeometryVertex v[32];
|
||||
|
||||
int vcount = argc - 1;
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
getVertex(v[i - 1], argv[i]);
|
||||
}
|
||||
|
||||
// need to generate a normal!
|
||||
#if 0 // not currently implemented
|
||||
if ( mNormals.empty() )
|
||||
{
|
||||
Vector3d<float> p1( v[0].mPos );
|
||||
Vector3d<float> p2( v[1].mPos );
|
||||
Vector3d<float> p3( v[2].mPos );
|
||||
|
||||
Vector3d<float> n;
|
||||
n.ComputeNormal(p3,p2,p1);
|
||||
|
||||
for (int i=0; i<vcount; i++)
|
||||
{
|
||||
v[i].mNormal[0] = n.x;
|
||||
v[i].mNormal[1] = n.y;
|
||||
v[i].mNormal[2] = n.z;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
mCallback->NodeTriangle(&v[0], &v[1], &v[2]);
|
||||
|
||||
if (vcount >= 3) // do the fan
|
||||
{
|
||||
for (int i = 2; i < (vcount - 1); i++)
|
||||
{
|
||||
mCallback->NodeTriangle(&v[0], &v[i], &v[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
class BuildMesh : public GeometryInterface
|
||||
{
|
||||
public:
|
||||
int getIndex(const float *p)
|
||||
{
|
||||
int vcount = mVertices.size() / 3;
|
||||
|
||||
if (vcount > 0)
|
||||
{
|
||||
//New MS STL library checks indices in debug build, so zero causes an assert if it is empty.
|
||||
const float *v = &mVertices[0];
|
||||
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
if (v[0] == p[0] && v[1] == p[1] && v[2] == p[2]) return i;
|
||||
v += 3;
|
||||
}
|
||||
}
|
||||
|
||||
mVertices.push_back(p[0]);
|
||||
mVertices.push_back(p[1]);
|
||||
mVertices.push_back(p[2]);
|
||||
|
||||
return vcount;
|
||||
}
|
||||
|
||||
virtual void NodeTriangle(const GeometryVertex *v1, const GeometryVertex *v2, const GeometryVertex *v3)
|
||||
{
|
||||
mIndices.push_back(getIndex(v1->mPos));
|
||||
mIndices.push_back(getIndex(v2->mPos));
|
||||
mIndices.push_back(getIndex(v3->mPos));
|
||||
}
|
||||
|
||||
const FloatVector &GetVertices(void) const { return mVertices; };
|
||||
const IntVector &GetIndices(void) const { return mIndices; };
|
||||
|
||||
private:
|
||||
FloatVector mVertices;
|
||||
IntVector mIndices;
|
||||
};
|
||||
|
||||
WavefrontObj::WavefrontObj(void)
|
||||
{
|
||||
mVertexCount = 0;
|
||||
mTriCount = 0;
|
||||
mIndices = 0;
|
||||
mVertices = 0;
|
||||
}
|
||||
|
||||
WavefrontObj::~WavefrontObj(void)
|
||||
{
|
||||
delete[] mIndices;
|
||||
delete[] mVertices;
|
||||
}
|
||||
|
||||
unsigned int WavefrontObj::loadObj(const char *fname) // load a wavefront obj returns number of triangles that were loaded. Data is persists until the class is destructed.
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
|
||||
delete[] mVertices;
|
||||
mVertices = 0;
|
||||
delete[] mIndices;
|
||||
mIndices = 0;
|
||||
mVertexCount = 0;
|
||||
mTriCount = 0;
|
||||
|
||||
BuildMesh bm;
|
||||
|
||||
OBJ obj;
|
||||
|
||||
obj.LoadMesh(fname, &bm);
|
||||
|
||||
const FloatVector &vlist = bm.GetVertices();
|
||||
const IntVector &indices = bm.GetIndices();
|
||||
if (vlist.size())
|
||||
{
|
||||
mVertexCount = vlist.size() / 3;
|
||||
mVertices = new float[mVertexCount * 3];
|
||||
memcpy(mVertices, &vlist[0], sizeof(float) * mVertexCount * 3);
|
||||
mTriCount = indices.size() / 3;
|
||||
mIndices = new int[mTriCount * 3 * sizeof(int)];
|
||||
memcpy(mIndices, &indices[0], sizeof(int) * mTriCount * 3);
|
||||
ret = mTriCount;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace ConvexDecomposition
|
||||
57
Engine/lib/bullet/Extras/ConvexDecomposition/cd_wavefront.h
Normal file
57
Engine/lib/bullet/Extras/ConvexDecomposition/cd_wavefront.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef CD_WAVEFRONT_OBJ_H
|
||||
|
||||
#define CD_WAVEFRONT_OBJ_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
class WavefrontObj
|
||||
{
|
||||
public:
|
||||
WavefrontObj(void);
|
||||
~WavefrontObj(void);
|
||||
|
||||
unsigned int loadObj(const char *fname); // load a wavefront obj returns number of triangles that were loaded. Data is persists until the class is destructed.
|
||||
|
||||
int mVertexCount;
|
||||
int mTriCount;
|
||||
int *mIndices;
|
||||
float *mVertices;
|
||||
};
|
||||
|
||||
} // namespace ConvexDecomposition
|
||||
|
||||
#endif
|
||||
761
Engine/lib/bullet/Extras/ConvexDecomposition/concavity.cpp
Normal file
761
Engine/lib/bullet/Extras/ConvexDecomposition/concavity.cpp
Normal file
|
|
@ -0,0 +1,761 @@
|
|||
#include "float_math.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
#include "concavity.h"
|
||||
#include "raytri.h"
|
||||
#include "bestfit.h"
|
||||
#include "cd_hull.h"
|
||||
#include "meshvolume.h"
|
||||
#include "cd_vector.h"
|
||||
#include "splitplane.h"
|
||||
#include "ConvexDecomposition.h"
|
||||
|
||||
#define WSCALE 4
|
||||
#define CONCAVE_THRESH 0.05f
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
unsigned int getDebugColor(void)
|
||||
{
|
||||
static unsigned int colors[8] =
|
||||
{
|
||||
0xFF0000,
|
||||
0x00FF00,
|
||||
0x0000FF,
|
||||
0xFFFF00,
|
||||
0x00FFFF,
|
||||
0xFF00FF,
|
||||
0xFFFFFF,
|
||||
0xFF8040};
|
||||
|
||||
static int count = 0;
|
||||
|
||||
count++;
|
||||
|
||||
if (count == 8) count = 0;
|
||||
|
||||
assert(count >= 0 && count < 8);
|
||||
|
||||
unsigned int color = colors[count];
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
class Wpoint
|
||||
{
|
||||
public:
|
||||
Wpoint(const Vector3d &p, float w)
|
||||
{
|
||||
mPoint = p;
|
||||
mWeight = w;
|
||||
}
|
||||
|
||||
Vector3d mPoint;
|
||||
float mWeight;
|
||||
};
|
||||
|
||||
typedef std::vector<Wpoint> WpointVector;
|
||||
|
||||
static inline float DistToPt(const float *p, const float *plane)
|
||||
{
|
||||
float x = p[0];
|
||||
float y = p[1];
|
||||
float z = p[2];
|
||||
float d = x * plane[0] + y * plane[1] + z * plane[2] + plane[3];
|
||||
return d;
|
||||
}
|
||||
|
||||
static void intersect(const float *p1, const float *p2, float *split, const float *plane)
|
||||
{
|
||||
float dp1 = DistToPt(p1, plane);
|
||||
|
||||
float dir[3];
|
||||
|
||||
dir[0] = p2[0] - p1[0];
|
||||
dir[1] = p2[1] - p1[1];
|
||||
dir[2] = p2[2] - p1[2];
|
||||
|
||||
float dot1 = dir[0] * plane[0] + dir[1] * plane[1] + dir[2] * plane[2];
|
||||
float dot2 = dp1 - plane[3];
|
||||
|
||||
float t = -(plane[3] + dot2) / dot1;
|
||||
|
||||
split[0] = (dir[0] * t) + p1[0];
|
||||
split[1] = (dir[1] * t) + p1[1];
|
||||
split[2] = (dir[2] * t) + p1[2];
|
||||
}
|
||||
|
||||
class CTri
|
||||
{
|
||||
public:
|
||||
CTri(void){};
|
||||
|
||||
CTri(const float *p1, const float *p2, const float *p3, unsigned int i1, unsigned int i2, unsigned int i3)
|
||||
{
|
||||
mProcessed = 0;
|
||||
mI1 = i1;
|
||||
mI2 = i2;
|
||||
mI3 = i3;
|
||||
|
||||
mP1.Set(p1);
|
||||
mP2.Set(p2);
|
||||
mP3.Set(p3);
|
||||
|
||||
mPlaneD = mNormal.ComputePlane(mP1, mP2, mP3);
|
||||
}
|
||||
|
||||
float Facing(const CTri &t)
|
||||
{
|
||||
float d = mNormal.Dot(t.mNormal);
|
||||
return d;
|
||||
}
|
||||
|
||||
// clip this line segment against this triangle.
|
||||
bool clip(const Vector3d &start, Vector3d &end) const
|
||||
{
|
||||
Vector3d sect;
|
||||
|
||||
bool hit = lineIntersectsTriangle(start.Ptr(), end.Ptr(), mP1.Ptr(), mP2.Ptr(), mP3.Ptr(), sect.Ptr());
|
||||
|
||||
if (hit)
|
||||
{
|
||||
end = sect;
|
||||
}
|
||||
return hit;
|
||||
}
|
||||
|
||||
bool Concave(const Vector3d &p, float &distance, Vector3d &n) const
|
||||
{
|
||||
n.NearestPointInTriangle(p, mP1, mP2, mP3);
|
||||
distance = p.Distance(n);
|
||||
return true;
|
||||
}
|
||||
|
||||
void addTri(unsigned int *indices, unsigned int i1, unsigned int i2, unsigned int i3, unsigned int &tcount) const
|
||||
{
|
||||
indices[tcount * 3 + 0] = i1;
|
||||
indices[tcount * 3 + 1] = i2;
|
||||
indices[tcount * 3 + 2] = i3;
|
||||
tcount++;
|
||||
}
|
||||
|
||||
float getVolume(ConvexDecompInterface *callback) const
|
||||
{
|
||||
unsigned int indices[8 * 3];
|
||||
|
||||
unsigned int tcount = 0;
|
||||
|
||||
addTri(indices, 0, 1, 2, tcount);
|
||||
addTri(indices, 3, 4, 5, tcount);
|
||||
|
||||
addTri(indices, 0, 3, 4, tcount);
|
||||
addTri(indices, 0, 4, 1, tcount);
|
||||
|
||||
addTri(indices, 1, 4, 5, tcount);
|
||||
addTri(indices, 1, 5, 2, tcount);
|
||||
|
||||
addTri(indices, 0, 3, 5, tcount);
|
||||
addTri(indices, 0, 5, 2, tcount);
|
||||
|
||||
const float *vertices = mP1.Ptr();
|
||||
|
||||
if (callback)
|
||||
{
|
||||
unsigned int color = getDebugColor();
|
||||
|
||||
#if 0
|
||||
Vector3d d1 = mNear1;
|
||||
Vector3d d2 = mNear2;
|
||||
Vector3d d3 = mNear3;
|
||||
|
||||
callback->ConvexDebugPoint(mP1.Ptr(),0.01f,0x00FF00);
|
||||
callback->ConvexDebugPoint(mP2.Ptr(),0.01f,0x00FF00);
|
||||
callback->ConvexDebugPoint(mP3.Ptr(),0.01f,0x00FF00);
|
||||
callback->ConvexDebugPoint(d1.Ptr(),0.01f,0xFF0000);
|
||||
callback->ConvexDebugPoint(d2.Ptr(),0.01f,0xFF0000);
|
||||
callback->ConvexDebugPoint(d3.Ptr(),0.01f,0xFF0000);
|
||||
|
||||
callback->ConvexDebugTri(mP1.Ptr(), d1.Ptr(), d1.Ptr(),0x00FF00);
|
||||
callback->ConvexDebugTri(mP2.Ptr(), d2.Ptr(), d2.Ptr(),0x00FF00);
|
||||
callback->ConvexDebugTri(mP3.Ptr(), d3.Ptr(), d3.Ptr(),0x00FF00);
|
||||
|
||||
#else
|
||||
for (unsigned int i = 0; i < tcount; i++)
|
||||
{
|
||||
unsigned int i1 = indices[i * 3 + 0];
|
||||
unsigned int i2 = indices[i * 3 + 1];
|
||||
unsigned int i3 = indices[i * 3 + 2];
|
||||
|
||||
const float *p1 = &vertices[i1 * 3];
|
||||
const float *p2 = &vertices[i2 * 3];
|
||||
const float *p3 = &vertices[i3 * 3];
|
||||
|
||||
callback->ConvexDebugTri(p1, p2, p3, color);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float v = computeMeshVolume(mP1.Ptr(), tcount, indices);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
float raySect(const Vector3d &p, const Vector3d &dir, Vector3d §) const
|
||||
{
|
||||
float plane[4];
|
||||
|
||||
plane[0] = mNormal.x;
|
||||
plane[1] = mNormal.y;
|
||||
plane[2] = mNormal.z;
|
||||
plane[3] = mPlaneD;
|
||||
|
||||
Vector3d dest = p + dir * 100000;
|
||||
|
||||
intersect(p.Ptr(), dest.Ptr(), sect.Ptr(), plane);
|
||||
|
||||
return sect.Distance(p); // return the intersection distance.
|
||||
}
|
||||
|
||||
float planeDistance(const Vector3d &p) const
|
||||
{
|
||||
float plane[4];
|
||||
|
||||
plane[0] = mNormal.x;
|
||||
plane[1] = mNormal.y;
|
||||
plane[2] = mNormal.z;
|
||||
plane[3] = mPlaneD;
|
||||
|
||||
return DistToPt(p.Ptr(), plane);
|
||||
}
|
||||
|
||||
bool samePlane(const CTri &t) const
|
||||
{
|
||||
const float THRESH = 0.001f;
|
||||
float dd = fabsf(t.mPlaneD - mPlaneD);
|
||||
if (dd > THRESH) return false;
|
||||
dd = fabsf(t.mNormal.x - mNormal.x);
|
||||
if (dd > THRESH) return false;
|
||||
dd = fabsf(t.mNormal.y - mNormal.y);
|
||||
if (dd > THRESH) return false;
|
||||
dd = fabsf(t.mNormal.z - mNormal.z);
|
||||
if (dd > THRESH) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasIndex(unsigned int i) const
|
||||
{
|
||||
if (i == mI1 || i == mI2 || i == mI3) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sharesEdge(const CTri &t) const
|
||||
{
|
||||
bool ret = false;
|
||||
unsigned int count = 0;
|
||||
|
||||
if (t.hasIndex(mI1)) count++;
|
||||
if (t.hasIndex(mI2)) count++;
|
||||
if (t.hasIndex(mI3)) count++;
|
||||
|
||||
if (count >= 2) ret = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void debug(unsigned int color, ConvexDecompInterface *callback)
|
||||
{
|
||||
callback->ConvexDebugTri(mP1.Ptr(), mP2.Ptr(), mP3.Ptr(), color);
|
||||
callback->ConvexDebugTri(mP1.Ptr(), mP1.Ptr(), mNear1.Ptr(), 0xFF0000);
|
||||
callback->ConvexDebugTri(mP2.Ptr(), mP2.Ptr(), mNear2.Ptr(), 0xFF0000);
|
||||
callback->ConvexDebugTri(mP2.Ptr(), mP3.Ptr(), mNear3.Ptr(), 0xFF0000);
|
||||
callback->ConvexDebugPoint(mNear1.Ptr(), 0.01f, 0xFF0000);
|
||||
callback->ConvexDebugPoint(mNear2.Ptr(), 0.01f, 0xFF0000);
|
||||
callback->ConvexDebugPoint(mNear3.Ptr(), 0.01f, 0xFF0000);
|
||||
}
|
||||
|
||||
float area(void)
|
||||
{
|
||||
float a = mConcavity * mP1.Area(mP2, mP3);
|
||||
return a;
|
||||
}
|
||||
|
||||
void addWeighted(WpointVector &list, ConvexDecompInterface *callback)
|
||||
{
|
||||
Wpoint p1(mP1, mC1);
|
||||
Wpoint p2(mP2, mC2);
|
||||
Wpoint p3(mP3, mC3);
|
||||
|
||||
Vector3d d1 = mNear1 - mP1;
|
||||
Vector3d d2 = mNear2 - mP2;
|
||||
Vector3d d3 = mNear3 - mP3;
|
||||
|
||||
d1 *= WSCALE;
|
||||
d2 *= WSCALE;
|
||||
d3 *= WSCALE;
|
||||
|
||||
d1 = d1 + mP1;
|
||||
d2 = d2 + mP2;
|
||||
d3 = d3 + mP3;
|
||||
|
||||
Wpoint p4(d1, mC1);
|
||||
Wpoint p5(d2, mC2);
|
||||
Wpoint p6(d3, mC3);
|
||||
|
||||
list.push_back(p1);
|
||||
list.push_back(p2);
|
||||
list.push_back(p3);
|
||||
|
||||
list.push_back(p4);
|
||||
list.push_back(p5);
|
||||
list.push_back(p6);
|
||||
|
||||
#if 0
|
||||
callback->ConvexDebugPoint(mP1.Ptr(),0.01f,0x00FF00);
|
||||
callback->ConvexDebugPoint(mP2.Ptr(),0.01f,0x00FF00);
|
||||
callback->ConvexDebugPoint(mP3.Ptr(),0.01f,0x00FF00);
|
||||
callback->ConvexDebugPoint(d1.Ptr(),0.01f,0xFF0000);
|
||||
callback->ConvexDebugPoint(d2.Ptr(),0.01f,0xFF0000);
|
||||
callback->ConvexDebugPoint(d3.Ptr(),0.01f,0xFF0000);
|
||||
|
||||
callback->ConvexDebugTri(mP1.Ptr(), d1.Ptr(), d1.Ptr(),0x00FF00);
|
||||
callback->ConvexDebugTri(mP2.Ptr(), d2.Ptr(), d2.Ptr(),0x00FF00);
|
||||
callback->ConvexDebugTri(mP3.Ptr(), d3.Ptr(), d3.Ptr(),0x00FF00);
|
||||
|
||||
Vector3d np1 = mP1 + mNormal*0.05f;
|
||||
Vector3d np2 = mP2 + mNormal*0.05f;
|
||||
Vector3d np3 = mP3 + mNormal*0.05f;
|
||||
|
||||
callback->ConvexDebugTri(mP1.Ptr(), np1.Ptr(), np1.Ptr(), 0xFF00FF );
|
||||
callback->ConvexDebugTri(mP2.Ptr(), np2.Ptr(), np2.Ptr(), 0xFF00FF );
|
||||
callback->ConvexDebugTri(mP3.Ptr(), np3.Ptr(), np3.Ptr(), 0xFF00FF );
|
||||
|
||||
callback->ConvexDebugPoint( np1.Ptr(), 0.01F, 0XFF00FF );
|
||||
callback->ConvexDebugPoint( np2.Ptr(), 0.01F, 0XFF00FF );
|
||||
callback->ConvexDebugPoint( np3.Ptr(), 0.01F, 0XFF00FF );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
Vector3d mP1;
|
||||
Vector3d mP2;
|
||||
Vector3d mP3;
|
||||
Vector3d mNear1;
|
||||
Vector3d mNear2;
|
||||
Vector3d mNear3;
|
||||
Vector3d mNormal;
|
||||
float mPlaneD;
|
||||
float mConcavity;
|
||||
float mC1;
|
||||
float mC2;
|
||||
float mC3;
|
||||
unsigned int mI1;
|
||||
unsigned int mI2;
|
||||
unsigned int mI3;
|
||||
int mProcessed; // already been added...
|
||||
};
|
||||
|
||||
typedef std::vector<CTri> CTriVector;
|
||||
|
||||
bool featureMatch(CTri &m, const CTriVector &tris, ConvexDecompInterface *callback, const CTriVector &input_mesh)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
float neardot = 0.707f;
|
||||
|
||||
m.mConcavity = 0;
|
||||
|
||||
//gLog->Display("*********** FEATURE MATCH *************\r\n");
|
||||
//gLog->Display("Plane: %0.4f,%0.4f,%0.4f %0.4f\r\n", m.mNormal.x, m.mNormal.y, m.mNormal.z, m.mPlaneD );
|
||||
//gLog->Display("*********************************************\r\n");
|
||||
|
||||
CTriVector::const_iterator i;
|
||||
|
||||
CTri nearest;
|
||||
|
||||
for (i = tris.begin(); i != tris.end(); ++i)
|
||||
{
|
||||
const CTri &t = (*i);
|
||||
|
||||
//gLog->Display(" HullPlane: %0.4f,%0.4f,%0.4f %0.4f\r\n", t.mNormal.x, t.mNormal.y, t.mNormal.z, t.mPlaneD );
|
||||
|
||||
if (t.samePlane(m))
|
||||
{
|
||||
//gLog->Display("*** PLANE MATCH!!!\r\n");
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
float dot = t.mNormal.Dot(m.mNormal);
|
||||
|
||||
if (dot > neardot)
|
||||
{
|
||||
float d1 = t.planeDistance(m.mP1);
|
||||
float d2 = t.planeDistance(m.mP2);
|
||||
float d3 = t.planeDistance(m.mP3);
|
||||
|
||||
if (d1 > 0.001f || d2 > 0.001f || d3 > 0.001f) // can't be near coplaner!
|
||||
{
|
||||
neardot = dot;
|
||||
|
||||
Vector3d n1, n2, n3;
|
||||
|
||||
t.raySect(m.mP1, m.mNormal, m.mNear1);
|
||||
t.raySect(m.mP2, m.mNormal, m.mNear2);
|
||||
t.raySect(m.mP3, m.mNormal, m.mNear3);
|
||||
|
||||
nearest = t;
|
||||
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret)
|
||||
{
|
||||
if (0)
|
||||
{
|
||||
CTriVector::const_iterator i;
|
||||
for (i = input_mesh.begin(); i != input_mesh.end(); ++i)
|
||||
{
|
||||
const CTri &c = (*i);
|
||||
if (c.mI1 != m.mI1 && c.mI2 != m.mI2 && c.mI3 != m.mI3)
|
||||
{
|
||||
c.clip(m.mP1, m.mNear1);
|
||||
c.clip(m.mP2, m.mNear2);
|
||||
c.clip(m.mP3, m.mNear3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//gLog->Display("*********************************************\r\n");
|
||||
//gLog->Display(" HullPlaneNearest: %0.4f,%0.4f,%0.4f %0.4f\r\n", nearest.mNormal.x, nearest.mNormal.y, nearest.mNormal.z, nearest.mPlaneD );
|
||||
|
||||
m.mC1 = m.mP1.Distance(m.mNear1);
|
||||
m.mC2 = m.mP2.Distance(m.mNear2);
|
||||
m.mC3 = m.mP3.Distance(m.mNear3);
|
||||
|
||||
m.mConcavity = m.mC1;
|
||||
|
||||
if (m.mC2 > m.mConcavity) m.mConcavity = m.mC2;
|
||||
if (m.mC3 > m.mConcavity) m.mConcavity = m.mC3;
|
||||
|
||||
#if 0
|
||||
callback->ConvexDebugTri( m.mP1.Ptr(), m.mP2.Ptr(), m.mP3.Ptr(), 0x00FF00 );
|
||||
callback->ConvexDebugTri( m.mNear1.Ptr(), m.mNear2.Ptr(), m.mNear3.Ptr(), 0xFF0000 );
|
||||
|
||||
callback->ConvexDebugTri( m.mP1.Ptr(), m.mP1.Ptr(), m.mNear1.Ptr(), 0xFFFF00 );
|
||||
callback->ConvexDebugTri( m.mP2.Ptr(), m.mP2.Ptr(), m.mNear2.Ptr(), 0xFFFF00 );
|
||||
callback->ConvexDebugTri( m.mP3.Ptr(), m.mP3.Ptr(), m.mNear3.Ptr(), 0xFFFF00 );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
//gLog->Display("No match\r\n");
|
||||
}
|
||||
|
||||
//gLog->Display("*********************************************\r\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool isFeatureTri(CTri &t, CTriVector &flist, float fc, ConvexDecompInterface *callback, unsigned int color)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (t.mProcessed == 0) // if not already processed
|
||||
{
|
||||
float c = t.mConcavity / fc; // must be within 80% of the concavity of the parent.
|
||||
|
||||
if (c > 0.85f)
|
||||
{
|
||||
// see if this triangle is a 'feature' triangle. Meaning it shares an
|
||||
// edge with any existing feature triangle and is within roughly the same
|
||||
// concavity of the parent.
|
||||
if (flist.size())
|
||||
{
|
||||
CTriVector::iterator i;
|
||||
for (i = flist.begin(); i != flist.end(); ++i)
|
||||
{
|
||||
CTri &ftri = (*i);
|
||||
if (ftri.sharesEdge(t))
|
||||
{
|
||||
t.mProcessed = 2; // it is now part of a feature.
|
||||
flist.push_back(t); // add it to the feature list.
|
||||
// callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(),t.mP3.Ptr(), color );
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
t.mProcessed = 2;
|
||||
flist.push_back(t); // add it to the feature list.
|
||||
// callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(),t.mP3.Ptr(), color );
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
t.mProcessed = 1; // eliminated for this feature, but might be valid for the next one..
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
float computeConcavity(unsigned int vcount,
|
||||
const float *vertices,
|
||||
unsigned int tcount,
|
||||
const unsigned int *indices,
|
||||
ConvexDecompInterface *callback,
|
||||
float *plane, // plane equation to split on
|
||||
float &volume)
|
||||
{
|
||||
float cret = 0;
|
||||
volume = 1;
|
||||
|
||||
HullResult result;
|
||||
HullLibrary hl;
|
||||
HullDesc desc;
|
||||
|
||||
desc.mMaxFaces = 256;
|
||||
desc.mMaxVertices = 256;
|
||||
desc.SetHullFlag(QF_TRIANGLES);
|
||||
|
||||
desc.mVcount = vcount;
|
||||
desc.mVertices = vertices;
|
||||
desc.mVertexStride = sizeof(float) * 3;
|
||||
|
||||
HullError ret = hl.CreateConvexHull(desc, result);
|
||||
|
||||
if (ret == QE_OK)
|
||||
{
|
||||
#if 0
|
||||
float bmin[3];
|
||||
float bmax[3];
|
||||
|
||||
float dx = bmax[0] - bmin[0];
|
||||
float dy = bmax[1] - bmin[1];
|
||||
float dz = bmax[2] - bmin[2];
|
||||
|
||||
Vector3d center;
|
||||
|
||||
center.x = bmin[0] + dx*0.5f;
|
||||
center.y = bmin[1] + dy*0.5f;
|
||||
center.z = bmin[2] + dz*0.5f;
|
||||
#endif
|
||||
|
||||
volume = computeMeshVolume2(result.mOutputVertices, result.mNumFaces, result.mIndices);
|
||||
|
||||
#if 1
|
||||
// ok..now..for each triangle on the original mesh..
|
||||
// we extrude the points to the nearest point on the hull.
|
||||
const unsigned int *source = result.mIndices;
|
||||
|
||||
CTriVector tris;
|
||||
|
||||
for (unsigned int i = 0; i < result.mNumFaces; i++)
|
||||
{
|
||||
unsigned int i1 = *source++;
|
||||
unsigned int i2 = *source++;
|
||||
unsigned int i3 = *source++;
|
||||
|
||||
const float *p1 = &result.mOutputVertices[i1 * 3];
|
||||
const float *p2 = &result.mOutputVertices[i2 * 3];
|
||||
const float *p3 = &result.mOutputVertices[i3 * 3];
|
||||
|
||||
// callback->ConvexDebugTri(p1,p2,p3,0xFFFFFF);
|
||||
|
||||
CTri t(p1, p2, p3, i1, i2, i3); //
|
||||
tris.push_back(t);
|
||||
}
|
||||
|
||||
// we have not pre-computed the plane equation for each triangle in the convex hull..
|
||||
|
||||
float totalVolume = 0;
|
||||
|
||||
CTriVector ftris; // 'feature' triangles.
|
||||
|
||||
const unsigned int *src = indices;
|
||||
|
||||
float maxc = 0;
|
||||
|
||||
if (1)
|
||||
{
|
||||
CTriVector input_mesh;
|
||||
if (1)
|
||||
{
|
||||
const unsigned int *src = indices;
|
||||
for (unsigned int i = 0; i < tcount; i++)
|
||||
{
|
||||
unsigned int i1 = *src++;
|
||||
unsigned int i2 = *src++;
|
||||
unsigned int i3 = *src++;
|
||||
|
||||
const float *p1 = &vertices[i1 * 3];
|
||||
const float *p2 = &vertices[i2 * 3];
|
||||
const float *p3 = &vertices[i3 * 3];
|
||||
|
||||
CTri t(p1, p2, p3, i1, i2, i3);
|
||||
input_mesh.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
CTri maxctri;
|
||||
|
||||
for (unsigned int i = 0; i < tcount; i++)
|
||||
{
|
||||
unsigned int i1 = *src++;
|
||||
unsigned int i2 = *src++;
|
||||
unsigned int i3 = *src++;
|
||||
|
||||
const float *p1 = &vertices[i1 * 3];
|
||||
const float *p2 = &vertices[i2 * 3];
|
||||
const float *p3 = &vertices[i3 * 3];
|
||||
|
||||
CTri t(p1, p2, p3, i1, i2, i3);
|
||||
|
||||
featureMatch(t, tris, callback, input_mesh);
|
||||
|
||||
if (t.mConcavity > CONCAVE_THRESH)
|
||||
{
|
||||
if (t.mConcavity > maxc)
|
||||
{
|
||||
maxc = t.mConcavity;
|
||||
maxctri = t;
|
||||
}
|
||||
|
||||
float v = t.getVolume(0);
|
||||
totalVolume += v;
|
||||
ftris.push_back(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ( ftris.size() && 0 )
|
||||
{
|
||||
|
||||
// ok..now we extract the triangles which form the maximum concavity.
|
||||
CTriVector major_feature;
|
||||
float maxarea = 0;
|
||||
|
||||
while ( maxc > CONCAVE_THRESH )
|
||||
{
|
||||
|
||||
unsigned int color = getDebugColor(); //
|
||||
|
||||
CTriVector flist;
|
||||
|
||||
bool found;
|
||||
|
||||
float totalarea = 0;
|
||||
|
||||
do
|
||||
{
|
||||
found = false;
|
||||
CTriVector::iterator i;
|
||||
for (i=ftris.begin(); i!=ftris.end(); ++i)
|
||||
{
|
||||
CTri &t = (*i);
|
||||
if ( isFeatureTri(t,flist,maxc,callback,color) )
|
||||
{
|
||||
found = true;
|
||||
totalarea+=t.area();
|
||||
}
|
||||
}
|
||||
} while ( found );
|
||||
|
||||
|
||||
if ( totalarea > maxarea )
|
||||
{
|
||||
major_feature = flist;
|
||||
maxarea = totalarea;
|
||||
}
|
||||
|
||||
maxc = 0;
|
||||
|
||||
for (unsigned int i=0; i<ftris.size(); i++)
|
||||
{
|
||||
CTri &t = ftris[i];
|
||||
if ( t.mProcessed != 2 )
|
||||
{
|
||||
t.mProcessed = 0;
|
||||
if ( t.mConcavity > maxc )
|
||||
{
|
||||
maxc = t.mConcavity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unsigned int color = getDebugColor();
|
||||
|
||||
WpointVector list;
|
||||
for (unsigned int i=0; i<major_feature.size(); ++i)
|
||||
{
|
||||
major_feature[i].addWeighted(list,callback);
|
||||
major_feature[i].debug(color,callback);
|
||||
}
|
||||
|
||||
getBestFitPlane( list.size(), &list[0].mPoint.x, sizeof(Wpoint), &list[0].mWeight, sizeof(Wpoint), plane );
|
||||
|
||||
computeSplitPlane( vcount, vertices, tcount, indices, callback, plane );
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
computeSplitPlane( vcount, vertices, tcount, indices, callback, plane );
|
||||
}
|
||||
#endif
|
||||
|
||||
cret = totalVolume;
|
||||
|
||||
hl.ReleaseResult(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
return cret;
|
||||
}
|
||||
|
||||
} // namespace ConvexDecomposition
|
||||
55
Engine/lib/bullet/Extras/ConvexDecomposition/concavity.h
Normal file
55
Engine/lib/bullet/Extras/ConvexDecomposition/concavity.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef COMPUTE_CONCAVITY_H
|
||||
|
||||
#define COMPUTE_CONCAVITY_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
class ConvexDecompInterface;
|
||||
|
||||
// compute's how 'concave' this object is and returns the total volume of the
|
||||
// convex hull as well as the volume of the 'concavity' which was found.
|
||||
float computeConcavity(unsigned int vcount,
|
||||
const float *vertices,
|
||||
unsigned int tcount,
|
||||
const unsigned int *indices,
|
||||
ConvexDecompInterface *callback,
|
||||
float *plane,
|
||||
float &volume);
|
||||
|
||||
} // namespace ConvexDecomposition
|
||||
|
||||
#endif
|
||||
197
Engine/lib/bullet/Extras/ConvexDecomposition/fitsphere.cpp
Normal file
197
Engine/lib/bullet/Extras/ConvexDecomposition/fitsphere.cpp
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "fitsphere.h"
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
/*
|
||||
An Efficient Bounding Sphere
|
||||
by Jack Ritter
|
||||
from "Graphics Gems", Academic Press, 1990
|
||||
*/
|
||||
|
||||
/* Routine to calculate tight bounding sphere over */
|
||||
/* a set of points in 3D */
|
||||
/* This contains the routine find_bounding_sphere(), */
|
||||
/* the struct definition, and the globals used for parameters. */
|
||||
/* The abs() of all coordinates must be < BIGNUMBER */
|
||||
/* Code written by Jack Ritter and Lyle Rains. */
|
||||
|
||||
#define BIGNUMBER 100000000.0 /* hundred million */
|
||||
|
||||
static inline void Set(float *n, float x, float y, float z)
|
||||
{
|
||||
n[0] = x;
|
||||
n[1] = y;
|
||||
n[2] = z;
|
||||
}
|
||||
|
||||
static inline void Copy(float *dest, const float *source)
|
||||
{
|
||||
dest[0] = source[0];
|
||||
dest[1] = source[1];
|
||||
dest[2] = source[2];
|
||||
}
|
||||
|
||||
float computeBoundingSphere(unsigned int vcount, const float *points, float *center)
|
||||
{
|
||||
float mRadius;
|
||||
float mRadius2;
|
||||
|
||||
float xmin[3];
|
||||
float xmax[3];
|
||||
float ymin[3];
|
||||
float ymax[3];
|
||||
float zmin[3];
|
||||
float zmax[3];
|
||||
float dia1[3];
|
||||
float dia2[3];
|
||||
|
||||
/* FIRST PASS: find 6 minima/maxima points */
|
||||
Set(xmin, BIGNUMBER, BIGNUMBER, BIGNUMBER);
|
||||
Set(xmax, -BIGNUMBER, -BIGNUMBER, -BIGNUMBER);
|
||||
Set(ymin, BIGNUMBER, BIGNUMBER, BIGNUMBER);
|
||||
Set(ymax, -BIGNUMBER, -BIGNUMBER, -BIGNUMBER);
|
||||
Set(zmin, BIGNUMBER, BIGNUMBER, BIGNUMBER);
|
||||
Set(zmax, -BIGNUMBER, -BIGNUMBER, -BIGNUMBER);
|
||||
|
||||
for (unsigned i = 0; i < vcount; i++)
|
||||
{
|
||||
const float *caller_p = &points[i * 3];
|
||||
|
||||
if (caller_p[0] < xmin[0])
|
||||
Copy(xmin, caller_p); /* New xminimum point */
|
||||
if (caller_p[0] > xmax[0])
|
||||
Copy(xmax, caller_p);
|
||||
if (caller_p[1] < ymin[1])
|
||||
Copy(ymin, caller_p);
|
||||
if (caller_p[1] > ymax[1])
|
||||
Copy(ymax, caller_p);
|
||||
if (caller_p[2] < zmin[2])
|
||||
Copy(zmin, caller_p);
|
||||
if (caller_p[2] > zmax[2])
|
||||
Copy(zmax, caller_p);
|
||||
}
|
||||
|
||||
/* Set xspan = distance between the 2 points xmin & xmax (squared) */
|
||||
float dx = xmax[0] - xmin[0];
|
||||
float dy = xmax[1] - xmin[1];
|
||||
float dz = xmax[2] - xmin[2];
|
||||
float xspan = dx * dx + dy * dy + dz * dz;
|
||||
|
||||
/* Same for y & z spans */
|
||||
dx = ymax[0] - ymin[0];
|
||||
dy = ymax[1] - ymin[1];
|
||||
dz = ymax[2] - ymin[2];
|
||||
float yspan = dx * dx + dy * dy + dz * dz;
|
||||
|
||||
dx = zmax[0] - zmin[0];
|
||||
dy = zmax[1] - zmin[1];
|
||||
dz = zmax[2] - zmin[2];
|
||||
float zspan = dx * dx + dy * dy + dz * dz;
|
||||
|
||||
/* Set points dia1 & dia2 to the maximally separated pair */
|
||||
Copy(dia1, xmin);
|
||||
Copy(dia2, xmax); /* assume xspan biggest */
|
||||
float maxspan = xspan;
|
||||
|
||||
if (yspan > maxspan)
|
||||
{
|
||||
maxspan = yspan;
|
||||
Copy(dia1, ymin);
|
||||
Copy(dia2, ymax);
|
||||
}
|
||||
|
||||
if (zspan > maxspan)
|
||||
{
|
||||
Copy(dia1, zmin);
|
||||
Copy(dia2, zmax);
|
||||
}
|
||||
|
||||
/* dia1,dia2 is a diameter of initial sphere */
|
||||
/* calc initial center */
|
||||
center[0] = (dia1[0] + dia2[0]) * 0.5f;
|
||||
center[1] = (dia1[1] + dia2[1]) * 0.5f;
|
||||
center[2] = (dia1[2] + dia2[2]) * 0.5f;
|
||||
|
||||
/* calculate initial radius**2 and radius */
|
||||
|
||||
dx = dia2[0] - center[0]; /* x component of radius vector */
|
||||
dy = dia2[1] - center[1]; /* y component of radius vector */
|
||||
dz = dia2[2] - center[2]; /* z component of radius vector */
|
||||
|
||||
mRadius2 = dx * dx + dy * dy + dz * dz;
|
||||
mRadius = float(sqrt(mRadius2));
|
||||
|
||||
/* SECOND PASS: increment current sphere */
|
||||
|
||||
if (1)
|
||||
{
|
||||
for (unsigned i = 0; i < vcount; i++)
|
||||
{
|
||||
const float *caller_p = &points[i * 3];
|
||||
|
||||
dx = caller_p[0] - center[0];
|
||||
dy = caller_p[1] - center[1];
|
||||
dz = caller_p[2] - center[2];
|
||||
|
||||
float old_to_p_sq = dx * dx + dy * dy + dz * dz;
|
||||
|
||||
if (old_to_p_sq > mRadius2) /* do r**2 test first */
|
||||
{ /* this point is outside of current sphere */
|
||||
float old_to_p = float(sqrt(old_to_p_sq));
|
||||
/* calc radius of new sphere */
|
||||
mRadius = (mRadius + old_to_p) * 0.5f;
|
||||
mRadius2 = mRadius * mRadius; /* for next r**2 compare */
|
||||
float old_to_new = old_to_p - mRadius;
|
||||
|
||||
/* calc center of new sphere */
|
||||
|
||||
float recip = 1.0f / old_to_p;
|
||||
|
||||
float cx = (mRadius * center[0] + old_to_new * caller_p[0]) * recip;
|
||||
float cy = (mRadius * center[1] + old_to_new * caller_p[1]) * recip;
|
||||
float cz = (mRadius * center[2] + old_to_new * caller_p[2]) * recip;
|
||||
|
||||
Set(center, cx, cy, cz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mRadius;
|
||||
}
|
||||
41
Engine/lib/bullet/Extras/ConvexDecomposition/fitsphere.h
Normal file
41
Engine/lib/bullet/Extras/ConvexDecomposition/fitsphere.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef FIT_SPHERE_H
|
||||
|
||||
#define FIT_SPHERE_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
float computeBoundingSphere(unsigned int vcount, const float *points, float *center);
|
||||
|
||||
#endif
|
||||
238
Engine/lib/bullet/Extras/ConvexDecomposition/float_math.cpp
Normal file
238
Engine/lib/bullet/Extras/ConvexDecomposition/float_math.cpp
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
#include "float_math.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
void fm_inverseRT(const float *matrix, const float *pos, float *t) // inverse rotate translate the point.
|
||||
{
|
||||
float _x = pos[0] - matrix[3 * 4 + 0];
|
||||
float _y = pos[1] - matrix[3 * 4 + 1];
|
||||
float _z = pos[2] - matrix[3 * 4 + 2];
|
||||
|
||||
// Multiply inverse-translated source vector by inverted rotation transform
|
||||
|
||||
t[0] = (matrix[0 * 4 + 0] * _x) + (matrix[0 * 4 + 1] * _y) + (matrix[0 * 4 + 2] * _z);
|
||||
t[1] = (matrix[1 * 4 + 0] * _x) + (matrix[1 * 4 + 1] * _y) + (matrix[1 * 4 + 2] * _z);
|
||||
t[2] = (matrix[2 * 4 + 0] * _x) + (matrix[2 * 4 + 1] * _y) + (matrix[2 * 4 + 2] * _z);
|
||||
}
|
||||
|
||||
void fm_identity(float *matrix) // set 4x4 matrix to identity.
|
||||
{
|
||||
matrix[0 * 4 + 0] = 1;
|
||||
matrix[1 * 4 + 1] = 1;
|
||||
matrix[2 * 4 + 2] = 1;
|
||||
matrix[3 * 4 + 3] = 1;
|
||||
|
||||
matrix[1 * 4 + 0] = 0;
|
||||
matrix[2 * 4 + 0] = 0;
|
||||
matrix[3 * 4 + 0] = 0;
|
||||
|
||||
matrix[0 * 4 + 1] = 0;
|
||||
matrix[2 * 4 + 1] = 0;
|
||||
matrix[3 * 4 + 1] = 0;
|
||||
|
||||
matrix[0 * 4 + 2] = 0;
|
||||
matrix[1 * 4 + 2] = 0;
|
||||
matrix[3 * 4 + 2] = 0;
|
||||
|
||||
matrix[0 * 4 + 3] = 0;
|
||||
matrix[1 * 4 + 3] = 0;
|
||||
matrix[2 * 4 + 3] = 0;
|
||||
}
|
||||
|
||||
void fm_eulerMatrix(float ax, float ay, float az, float *matrix) // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
|
||||
{
|
||||
float quat[4];
|
||||
fm_eulerToQuat(ax, ay, az, quat);
|
||||
fm_quatToMatrix(quat, matrix);
|
||||
}
|
||||
|
||||
void fm_getAABB(unsigned int vcount, const float *points, unsigned int pstride, float *bmin, float *bmax)
|
||||
{
|
||||
const unsigned char *source = (const unsigned char *)points;
|
||||
|
||||
bmin[0] = points[0];
|
||||
bmin[1] = points[1];
|
||||
bmin[2] = points[2];
|
||||
|
||||
bmax[0] = points[0];
|
||||
bmax[1] = points[1];
|
||||
bmax[2] = points[2];
|
||||
|
||||
for (unsigned int i = 1; i < vcount; i++)
|
||||
{
|
||||
source += pstride;
|
||||
const float *p = (const float *)source;
|
||||
|
||||
if (p[0] < bmin[0]) bmin[0] = p[0];
|
||||
if (p[1] < bmin[1]) bmin[1] = p[1];
|
||||
if (p[2] < bmin[2]) bmin[2] = p[2];
|
||||
|
||||
if (p[0] > bmax[0]) bmax[0] = p[0];
|
||||
if (p[1] > bmax[1]) bmax[1] = p[1];
|
||||
if (p[2] > bmax[2]) bmax[2] = p[2];
|
||||
}
|
||||
}
|
||||
|
||||
void fm_eulerToQuat(float roll, float pitch, float yaw, float *quat) // convert euler angles to quaternion.
|
||||
{
|
||||
roll *= 0.5f;
|
||||
pitch *= 0.5f;
|
||||
yaw *= 0.5f;
|
||||
|
||||
float cr = cosf(roll);
|
||||
float cp = cosf(pitch);
|
||||
float cy = cosf(yaw);
|
||||
|
||||
float sr = sinf(roll);
|
||||
float sp = sinf(pitch);
|
||||
float sy = sinf(yaw);
|
||||
|
||||
float cpcy = cp * cy;
|
||||
float spsy = sp * sy;
|
||||
float spcy = sp * cy;
|
||||
float cpsy = cp * sy;
|
||||
|
||||
quat[0] = (sr * cpcy - cr * spsy);
|
||||
quat[1] = (cr * spcy + sr * cpsy);
|
||||
quat[2] = (cr * cpsy - sr * spcy);
|
||||
quat[3] = cr * cpcy + sr * spsy;
|
||||
}
|
||||
|
||||
void fm_quatToMatrix(const float *quat, float *matrix) // convert quaterinion rotation to matrix, zeros out the translation component.
|
||||
{
|
||||
float xx = quat[0] * quat[0];
|
||||
float yy = quat[1] * quat[1];
|
||||
float zz = quat[2] * quat[2];
|
||||
float xy = quat[0] * quat[1];
|
||||
float xz = quat[0] * quat[2];
|
||||
float yz = quat[1] * quat[2];
|
||||
float wx = quat[3] * quat[0];
|
||||
float wy = quat[3] * quat[1];
|
||||
float wz = quat[3] * quat[2];
|
||||
|
||||
matrix[0 * 4 + 0] = 1 - 2 * (yy + zz);
|
||||
matrix[1 * 4 + 0] = 2 * (xy - wz);
|
||||
matrix[2 * 4 + 0] = 2 * (xz + wy);
|
||||
|
||||
matrix[0 * 4 + 1] = 2 * (xy + wz);
|
||||
matrix[1 * 4 + 1] = 1 - 2 * (xx + zz);
|
||||
matrix[2 * 4 + 1] = 2 * (yz - wx);
|
||||
|
||||
matrix[0 * 4 + 2] = 2 * (xz - wy);
|
||||
matrix[1 * 4 + 2] = 2 * (yz + wx);
|
||||
matrix[2 * 4 + 2] = 1 - 2 * (xx + yy);
|
||||
|
||||
matrix[3 * 4 + 0] = matrix[3 * 4 + 1] = matrix[3 * 4 + 2] = 0.0f;
|
||||
matrix[0 * 4 + 3] = matrix[1 * 4 + 3] = matrix[2 * 4 + 3] = 0.0f;
|
||||
matrix[3 * 4 + 3] = 1.0f;
|
||||
}
|
||||
|
||||
void fm_quatRotate(const float *quat, const float *v, float *r) // rotate a vector directly by a quaternion.
|
||||
{
|
||||
float left[4];
|
||||
|
||||
left[0] = quat[3] * v[0] + quat[1] * v[2] - v[1] * quat[2];
|
||||
left[1] = quat[3] * v[1] + quat[2] * v[0] - v[2] * quat[0];
|
||||
left[2] = quat[3] * v[2] + quat[0] * v[1] - v[0] * quat[1];
|
||||
left[3] = -quat[0] * v[0] - quat[1] * v[1] - quat[2] * v[2];
|
||||
|
||||
r[0] = (left[3] * -quat[0]) + (quat[3] * left[0]) + (left[1] * -quat[2]) - (-quat[1] * left[2]);
|
||||
r[1] = (left[3] * -quat[1]) + (quat[3] * left[1]) + (left[2] * -quat[0]) - (-quat[2] * left[0]);
|
||||
r[2] = (left[3] * -quat[2]) + (quat[3] * left[2]) + (left[0] * -quat[1]) - (-quat[0] * left[1]);
|
||||
}
|
||||
|
||||
void fm_getTranslation(const float *matrix, float *t)
|
||||
{
|
||||
t[0] = matrix[3 * 4 + 0];
|
||||
t[1] = matrix[3 * 4 + 1];
|
||||
t[2] = matrix[3 * 4 + 2];
|
||||
}
|
||||
|
||||
void fm_matrixToQuat(const float *matrix, float *quat) // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
|
||||
{
|
||||
float tr = matrix[0 * 4 + 0] + matrix[1 * 4 + 1] + matrix[2 * 4 + 2];
|
||||
|
||||
// check the diagonal
|
||||
|
||||
if (tr > 0.0f)
|
||||
{
|
||||
float s = (float)sqrt((double)(tr + 1.0f));
|
||||
quat[3] = s * 0.5f;
|
||||
s = 0.5f / s;
|
||||
quat[0] = (matrix[1 * 4 + 2] - matrix[2 * 4 + 1]) * s;
|
||||
quat[1] = (matrix[2 * 4 + 0] - matrix[0 * 4 + 2]) * s;
|
||||
quat[2] = (matrix[0 * 4 + 1] - matrix[1 * 4 + 0]) * s;
|
||||
}
|
||||
else
|
||||
{
|
||||
// diagonal is negative
|
||||
int nxt[3] = {1, 2, 0};
|
||||
float qa[4];
|
||||
|
||||
int i = 0;
|
||||
|
||||
if (matrix[1 * 4 + 1] > matrix[0 * 4 + 0]) i = 1;
|
||||
if (matrix[2 * 4 + 2] > matrix[i * 4 + i]) i = 2;
|
||||
|
||||
int j = nxt[i];
|
||||
int k = nxt[j];
|
||||
|
||||
float s = sqrtf(((matrix[i * 4 + i] - (matrix[j * 4 + j] + matrix[k * 4 + k])) + 1.0f));
|
||||
|
||||
qa[i] = s * 0.5f;
|
||||
|
||||
if (s != 0.0f) s = 0.5f / s;
|
||||
|
||||
qa[3] = (matrix[j * 4 + k] - matrix[k * 4 + j]) * s;
|
||||
qa[j] = (matrix[i * 4 + j] + matrix[j * 4 + i]) * s;
|
||||
qa[k] = (matrix[i * 4 + k] + matrix[k * 4 + i]) * s;
|
||||
|
||||
quat[0] = qa[0];
|
||||
quat[1] = qa[1];
|
||||
quat[2] = qa[2];
|
||||
quat[3] = qa[3];
|
||||
}
|
||||
}
|
||||
|
||||
float fm_sphereVolume(float radius) // return's the volume of a sphere of this radius (4/3 PI * R cubed )
|
||||
{
|
||||
return (4.0f / 3.0f) * FM_PI * radius * radius * radius;
|
||||
}
|
||||
71
Engine/lib/bullet/Extras/ConvexDecomposition/float_math.h
Normal file
71
Engine/lib/bullet/Extras/ConvexDecomposition/float_math.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#ifndef FLOAT_MATH_H
|
||||
|
||||
#define FLOAT_MATH_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable : 4324) // disable padding warning
|
||||
#pragma warning(disable : 4244) // disable padding warning
|
||||
#pragma warning(disable : 4267) // possible loss of data
|
||||
#pragma warning(disable : 4530) // Disable the exception disable but used in MSCV Stl warning.
|
||||
#pragma warning(disable : 4996) //Turn off warnings about deprecated C routines
|
||||
#pragma warning(disable : 4786) // Disable the "debug name too long" warning
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
// a set of routines that last you do common 3d math
|
||||
// operations without any vector, matrix, or quaternion
|
||||
// classes or templates.
|
||||
//
|
||||
// a vector (or point) is a 'float *' to 3 floating point numbers.
|
||||
// a matrix is a 'float *' to an array of 16 floating point numbers representing a 4x4 transformation matrix compatible with D3D or OGL
|
||||
// a quaternion is a 'float *' to 4 floats representing a quaternion x,y,z,w
|
||||
|
||||
const float FM_PI = 3.141592654f;
|
||||
const float FM_DEG_TO_RAD = ((2.0f * FM_PI) / 360.0f);
|
||||
const float FM_RAD_TO_DEG = (360.0f / (2.0f * FM_PI));
|
||||
|
||||
void fm_identity(float *matrix); // set 4x4 matrix to identity.
|
||||
void fm_inverseRT(const float *matrix, const float *pos, float *t); // inverse rotate translate the point.
|
||||
void fm_eulerMatrix(float ax, float ay, float az, float *matrix); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
|
||||
void fm_getAABB(unsigned int vcount, const float *points, unsigned int pstride, float *bmin, float *bmax);
|
||||
void fm_eulerToQuat(float roll, float pitch, float yaw, float *quat); // convert euler angles to quaternion.
|
||||
void fm_quatToMatrix(const float *quat, float *matrix); // convert quaterinion rotation to matrix, translation set to zero.
|
||||
void fm_quatRotate(const float *quat, const float *v, float *r); // rotate a vector directly by a quaternion.
|
||||
void fm_getTranslation(const float *matrix, float *t);
|
||||
void fm_matrixToQuat(const float *matrix, float *quat); // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
|
||||
float fm_sphereVolume(float radius); // return's the volume of a sphere of this radius (4/3 PI * R cubed )
|
||||
|
||||
#endif
|
||||
124
Engine/lib/bullet/Extras/ConvexDecomposition/meshvolume.cpp
Normal file
124
Engine/lib/bullet/Extras/ConvexDecomposition/meshvolume.cpp
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
#include "float_math.h"
|
||||
#include "meshvolume.h"
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
inline float det(const float *p1, const float *p2, const float *p3)
|
||||
{
|
||||
return p1[0] * p2[1] * p3[2] + p2[0] * p3[1] * p1[2] + p3[0] * p1[1] * p2[2] - p1[0] * p3[1] * p2[2] - p2[0] * p1[1] * p3[2] - p3[0] * p2[1] * p1[2];
|
||||
}
|
||||
|
||||
float computeMeshVolume(const float *vertices, unsigned int tcount, const unsigned int *indices)
|
||||
{
|
||||
float volume = 0;
|
||||
|
||||
for (unsigned int i = 0; i < tcount; i++, indices += 3)
|
||||
{
|
||||
const float *p1 = &vertices[indices[0] * 3];
|
||||
const float *p2 = &vertices[indices[1] * 3];
|
||||
const float *p3 = &vertices[indices[2] * 3];
|
||||
|
||||
volume += det(p1, p2, p3); // compute the volume of the tetrahedran relative to the origin.
|
||||
}
|
||||
|
||||
volume *= (1.0f / 6.0f);
|
||||
if (volume < 0)
|
||||
volume *= -1;
|
||||
return volume;
|
||||
}
|
||||
|
||||
inline void CrossProduct(const float *a, const float *b, float *cross)
|
||||
{
|
||||
cross[0] = a[1] * b[2] - a[2] * b[1];
|
||||
cross[1] = a[2] * b[0] - a[0] * b[2];
|
||||
cross[2] = a[0] * b[1] - a[1] * b[0];
|
||||
}
|
||||
|
||||
inline float DotProduct(const float *a, const float *b)
|
||||
{
|
||||
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
||||
}
|
||||
|
||||
inline float tetVolume(const float *p0, const float *p1, const float *p2, const float *p3)
|
||||
{
|
||||
float a[3];
|
||||
float b[3];
|
||||
float c[3];
|
||||
|
||||
a[0] = p1[0] - p0[0];
|
||||
a[1] = p1[1] - p0[1];
|
||||
a[2] = p1[2] - p0[2];
|
||||
|
||||
b[0] = p2[0] - p0[0];
|
||||
b[1] = p2[1] - p0[1];
|
||||
b[2] = p2[2] - p0[2];
|
||||
|
||||
c[0] = p3[0] - p0[0];
|
||||
c[1] = p3[1] - p0[1];
|
||||
c[2] = p3[2] - p0[2];
|
||||
|
||||
float cross[3];
|
||||
|
||||
CrossProduct(b, c, cross);
|
||||
|
||||
float volume = DotProduct(a, cross);
|
||||
|
||||
if (volume < 0)
|
||||
return -volume;
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
inline float det(const float *p0, const float *p1, const float *p2, const float *p3)
|
||||
{
|
||||
return p1[0] * p2[1] * p3[2] + p2[0] * p3[1] * p1[2] + p3[0] * p1[1] * p2[2] - p1[0] * p3[1] * p2[2] - p2[0] * p1[1] * p3[2] - p3[0] * p2[1] * p1[2];
|
||||
}
|
||||
|
||||
float computeMeshVolume2(const float *vertices, unsigned int tcount, const unsigned int *indices)
|
||||
{
|
||||
float volume = 0;
|
||||
|
||||
const float *p0 = vertices;
|
||||
for (unsigned int i = 0; i < tcount; i++, indices += 3)
|
||||
{
|
||||
const float *p1 = &vertices[indices[0] * 3];
|
||||
const float *p2 = &vertices[indices[1] * 3];
|
||||
const float *p3 = &vertices[indices[2] * 3];
|
||||
|
||||
volume += tetVolume(p0, p1, p2, p3); // compute the volume of the tetrahdren relative to the root vertice
|
||||
}
|
||||
|
||||
return volume * (1.0f / 6.0f);
|
||||
}
|
||||
42
Engine/lib/bullet/Extras/ConvexDecomposition/meshvolume.h
Normal file
42
Engine/lib/bullet/Extras/ConvexDecomposition/meshvolume.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef MESH_VOLUME_H
|
||||
|
||||
#define MESH_VOLUME_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
float computeMeshVolume(const float *vertices, unsigned int tcount, const unsigned int *indices);
|
||||
float computeMeshVolume2(const float *vertices, unsigned int tcount, const unsigned int *indices);
|
||||
|
||||
#endif
|
||||
227
Engine/lib/bullet/Extras/ConvexDecomposition/planetri.cpp
Normal file
227
Engine/lib/bullet/Extras/ConvexDecomposition/planetri.cpp
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
#include "float_math.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "planetri.h"
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
static inline float DistToPt(const float *p, const float *plane)
|
||||
{
|
||||
float x = p[0];
|
||||
float y = p[1];
|
||||
float z = p[2];
|
||||
float d = x * plane[0] + y * plane[1] + z * plane[2] + plane[3];
|
||||
return d;
|
||||
}
|
||||
|
||||
static PlaneTriResult getSidePlane(const float *p, const float *plane, float epsilon)
|
||||
{
|
||||
float d = DistToPt(p, plane);
|
||||
|
||||
if ((d + epsilon) > 0)
|
||||
return PTR_FRONT; // it is 'in front' within the provided epsilon value.
|
||||
|
||||
return PTR_BACK;
|
||||
}
|
||||
|
||||
static void add(const float *p, float *dest, unsigned int tstride, unsigned int &pcount)
|
||||
{
|
||||
char *d = (char *)dest;
|
||||
d = d + pcount * tstride;
|
||||
dest = (float *)d;
|
||||
dest[0] = p[0];
|
||||
dest[1] = p[1];
|
||||
dest[2] = p[2];
|
||||
pcount++;
|
||||
assert(pcount <= 4);
|
||||
}
|
||||
|
||||
// assumes that the points are on opposite sides of the plane!
|
||||
static void intersect(const float *p1, const float *p2, float *split, const float *plane)
|
||||
{
|
||||
float dp1 = DistToPt(p1, plane);
|
||||
|
||||
float dir[3];
|
||||
|
||||
dir[0] = p2[0] - p1[0];
|
||||
dir[1] = p2[1] - p1[1];
|
||||
dir[2] = p2[2] - p1[2];
|
||||
|
||||
float dot1 = dir[0] * plane[0] + dir[1] * plane[1] + dir[2] * plane[2];
|
||||
float dot2 = dp1 - plane[3];
|
||||
|
||||
float t = -(plane[3] + dot2) / dot1;
|
||||
|
||||
split[0] = (dir[0] * t) + p1[0];
|
||||
split[1] = (dir[1] * t) + p1[1];
|
||||
split[2] = (dir[2] * t) + p1[2];
|
||||
}
|
||||
|
||||
PlaneTriResult planeTriIntersection(const float *plane, // the plane equation in Ax+By+Cz+D format
|
||||
const float *triangle, // the source triangle.
|
||||
unsigned int tstride, // stride in bytes of the input and output triangles
|
||||
float epsilon, // the co-planer epsilon value.
|
||||
float *front, // the triangle in front of the
|
||||
unsigned int &fcount, // number of vertices in the 'front' triangle
|
||||
float *back, // the triangle in back of the plane
|
||||
unsigned int &bcount) // the number of vertices in the 'back' triangle.
|
||||
{
|
||||
fcount = 0;
|
||||
bcount = 0;
|
||||
|
||||
const char *tsource = (const char *)triangle;
|
||||
|
||||
// get the three vertices of the triangle.
|
||||
const float *p1 = (const float *)(tsource);
|
||||
const float *p2 = (const float *)(tsource + tstride);
|
||||
const float *p3 = (const float *)(tsource + tstride * 2);
|
||||
|
||||
PlaneTriResult r1 = getSidePlane(p1, plane, epsilon); // compute the side of the plane each vertex is on
|
||||
PlaneTriResult r2 = getSidePlane(p2, plane, epsilon);
|
||||
PlaneTriResult r3 = getSidePlane(p3, plane, epsilon);
|
||||
|
||||
if (r1 == r2 && r1 == r3) // if all three vertices are on the same side of the plane.
|
||||
{
|
||||
if (r1 == PTR_FRONT) // if all three are in front of the plane, then copy to the 'front' output triangle.
|
||||
{
|
||||
add(p1, front, tstride, fcount);
|
||||
add(p2, front, tstride, fcount);
|
||||
add(p3, front, tstride, fcount);
|
||||
}
|
||||
else
|
||||
{
|
||||
add(p1, back, tstride, bcount); // if all three are in 'abck' then copy to the 'back' output triangle.
|
||||
add(p2, back, tstride, bcount);
|
||||
add(p3, back, tstride, bcount);
|
||||
}
|
||||
return r1; // if all three points are on the same side of the plane return result
|
||||
}
|
||||
|
||||
// ok.. we need to split the triangle at the plane.
|
||||
|
||||
// First test ray segment P1 to P2
|
||||
if (r1 == r2) // if these are both on the same side...
|
||||
{
|
||||
if (r1 == PTR_FRONT)
|
||||
{
|
||||
add(p1, front, tstride, fcount);
|
||||
add(p2, front, tstride, fcount);
|
||||
}
|
||||
else
|
||||
{
|
||||
add(p1, back, tstride, bcount);
|
||||
add(p2, back, tstride, bcount);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float split[3]; // split the point
|
||||
intersect(p1, p2, split, plane);
|
||||
|
||||
if (r1 == PTR_FRONT)
|
||||
{
|
||||
add(p1, front, tstride, fcount);
|
||||
add(split, front, tstride, fcount);
|
||||
|
||||
add(split, back, tstride, bcount);
|
||||
add(p2, back, tstride, bcount);
|
||||
}
|
||||
else
|
||||
{
|
||||
add(p1, back, tstride, bcount);
|
||||
add(split, back, tstride, bcount);
|
||||
|
||||
add(split, front, tstride, fcount);
|
||||
add(p2, front, tstride, fcount);
|
||||
}
|
||||
}
|
||||
|
||||
// Next test ray segment P2 to P3
|
||||
if (r2 == r3) // if these are both on the same side...
|
||||
{
|
||||
if (r3 == PTR_FRONT)
|
||||
{
|
||||
add(p3, front, tstride, fcount);
|
||||
}
|
||||
else
|
||||
{
|
||||
add(p3, back, tstride, bcount);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float split[3]; // split the point
|
||||
intersect(p2, p3, split, plane);
|
||||
|
||||
if (r3 == PTR_FRONT)
|
||||
{
|
||||
add(split, front, tstride, fcount);
|
||||
add(split, back, tstride, bcount);
|
||||
|
||||
add(p3, front, tstride, fcount);
|
||||
}
|
||||
else
|
||||
{
|
||||
add(split, front, tstride, fcount);
|
||||
add(split, back, tstride, bcount);
|
||||
|
||||
add(p3, back, tstride, bcount);
|
||||
}
|
||||
}
|
||||
|
||||
// Next test ray segment P3 to P1
|
||||
if (r3 != r1) // if these are both on the same side...
|
||||
{
|
||||
float split[3]; // split the point
|
||||
|
||||
intersect(p3, p1, split, plane);
|
||||
|
||||
if (r1 == PTR_FRONT)
|
||||
{
|
||||
add(split, front, tstride, fcount);
|
||||
add(split, back, tstride, bcount);
|
||||
}
|
||||
else
|
||||
{
|
||||
add(split, front, tstride, fcount);
|
||||
add(split, back, tstride, bcount);
|
||||
}
|
||||
}
|
||||
|
||||
return PTR_SPLIT;
|
||||
}
|
||||
55
Engine/lib/bullet/Extras/ConvexDecomposition/planetri.h
Normal file
55
Engine/lib/bullet/Extras/ConvexDecomposition/planetri.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef PLANE_TRI_H
|
||||
|
||||
#define PLANE_TRI_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
enum PlaneTriResult
|
||||
{
|
||||
PTR_FRONT,
|
||||
PTR_BACK,
|
||||
PTR_SPLIT
|
||||
};
|
||||
|
||||
PlaneTriResult planeTriIntersection(const float *plane, // the plane equation in Ax+By+Cz+D format
|
||||
const float *triangle, // the source position triangle.
|
||||
unsigned int tstride, // stride in bytes between vertices of the triangle.
|
||||
float epsilon, // the co-planer epsilon value.
|
||||
float *front, // the triangle in front of the
|
||||
unsigned int &fcount, // number of vertices in the 'front' triangle.
|
||||
float *back, // the triangle in back of the plane
|
||||
unsigned int &bcount); // the number of vertices in the 'back' triangle.
|
||||
|
||||
#endif
|
||||
12
Engine/lib/bullet/Extras/ConvexDecomposition/premake4.lua
Normal file
12
Engine/lib/bullet/Extras/ConvexDecomposition/premake4.lua
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
project "ConvexDecomposition"
|
||||
|
||||
kind "StaticLib"
|
||||
|
||||
includedirs {".","../../src"}
|
||||
if os.is("Linux") then
|
||||
buildoptions{"-fPIC"}
|
||||
end
|
||||
files {
|
||||
"**.cpp",
|
||||
"**.h"
|
||||
}
|
||||
128
Engine/lib/bullet/Extras/ConvexDecomposition/raytri.cpp
Normal file
128
Engine/lib/bullet/Extras/ConvexDecomposition/raytri.cpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#include "float_math.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "raytri.h"
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
/* a = b - c */
|
||||
#define vector(a, b, c) \
|
||||
(a)[0] = (b)[0] - (c)[0]; \
|
||||
(a)[1] = (b)[1] - (c)[1]; \
|
||||
(a)[2] = (b)[2] - (c)[2];
|
||||
|
||||
#define innerProduct(v, q) \
|
||||
((v)[0] * (q)[0] + \
|
||||
(v)[1] * (q)[1] + \
|
||||
(v)[2] * (q)[2])
|
||||
|
||||
#define crossProduct(a, b, c) \
|
||||
(a)[0] = (b)[1] * (c)[2] - (c)[1] * (b)[2]; \
|
||||
(a)[1] = (b)[2] * (c)[0] - (c)[2] * (b)[0]; \
|
||||
(a)[2] = (b)[0] * (c)[1] - (c)[0] * (b)[1];
|
||||
|
||||
bool rayIntersectsTriangle(const float *p, const float *d, const float *v0, const float *v1, const float *v2, float &t)
|
||||
{
|
||||
float e1[3], e2[3], h[3], s[3], q[3];
|
||||
float a, f, u, v;
|
||||
|
||||
vector(e1, v1, v0);
|
||||
vector(e2, v2, v0);
|
||||
crossProduct(h, d, e2);
|
||||
a = innerProduct(e1, h);
|
||||
|
||||
if (a > -0.00001 && a < 0.00001)
|
||||
return (false);
|
||||
|
||||
f = 1 / a;
|
||||
vector(s, p, v0);
|
||||
u = f * (innerProduct(s, h));
|
||||
|
||||
if (u < 0.0 || u > 1.0)
|
||||
return (false);
|
||||
|
||||
crossProduct(q, s, e1);
|
||||
v = f * innerProduct(d, q);
|
||||
if (v < 0.0 || u + v > 1.0)
|
||||
return (false);
|
||||
// at this stage we can compute t to find out where
|
||||
// the intersection point is on the line
|
||||
t = f * innerProduct(e2, q);
|
||||
if (t > 0) // ray intersection
|
||||
return (true);
|
||||
else // this means that there is a line intersection
|
||||
// but not a ray intersection
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool lineIntersectsTriangle(const float *rayStart, const float *rayEnd, const float *p1, const float *p2, const float *p3, float *sect)
|
||||
{
|
||||
float dir[3];
|
||||
|
||||
dir[0] = rayEnd[0] - rayStart[0];
|
||||
dir[1] = rayEnd[1] - rayStart[1];
|
||||
dir[2] = rayEnd[2] - rayStart[2];
|
||||
|
||||
float d = sqrtf(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]);
|
||||
float r = 1.0f / d;
|
||||
|
||||
dir[0] *= r;
|
||||
dir[1] *= r;
|
||||
dir[2] *= r;
|
||||
|
||||
float t;
|
||||
|
||||
bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
if (t > d)
|
||||
{
|
||||
sect[0] = rayStart[0] + dir[0] * t;
|
||||
sect[1] = rayStart[1] + dir[1] * t;
|
||||
sect[2] = rayStart[2] + dir[2] * t;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
43
Engine/lib/bullet/Extras/ConvexDecomposition/raytri.h
Normal file
43
Engine/lib/bullet/Extras/ConvexDecomposition/raytri.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef RAY_TRI_H
|
||||
|
||||
#define RAY_TRI_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
// returns true if the ray intersects the triangle.
|
||||
bool lineIntersectsTriangle(const float *rayStart, const float *rayEnd, const float *p1, const float *p2, const float *p3, float *sect);
|
||||
bool rayIntersectsTriangle(const float *p, const float *d, const float *v0, const float *v1, const float *v2, float &t);
|
||||
|
||||
#endif
|
||||
294
Engine/lib/bullet/Extras/ConvexDecomposition/splitplane.cpp
Normal file
294
Engine/lib/bullet/Extras/ConvexDecomposition/splitplane.cpp
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
#include "float_math.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
#include "splitplane.h"
|
||||
#include "ConvexDecomposition.h"
|
||||
#include "cd_vector.h"
|
||||
#include "cd_hull.h"
|
||||
#include "cd_wavefront.h"
|
||||
#include "bestfit.h"
|
||||
#include "planetri.h"
|
||||
#include "vlookup.h"
|
||||
#include "meshvolume.h"
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
static void computePlane(const float *A, const float *B, const float *C, float *plane)
|
||||
{
|
||||
float vx = (B[0] - C[0]);
|
||||
float vy = (B[1] - C[1]);
|
||||
float vz = (B[2] - C[2]);
|
||||
|
||||
float wx = (A[0] - B[0]);
|
||||
float wy = (A[1] - B[1]);
|
||||
float wz = (A[2] - B[2]);
|
||||
|
||||
float vw_x = vy * wz - vz * wy;
|
||||
float vw_y = vz * wx - vx * wz;
|
||||
float vw_z = vx * wy - vy * wx;
|
||||
|
||||
float mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
|
||||
|
||||
if (mag < 0.000001f)
|
||||
{
|
||||
mag = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mag = 1.0f / mag;
|
||||
}
|
||||
|
||||
float x = vw_x * mag;
|
||||
float y = vw_y * mag;
|
||||
float z = vw_z * mag;
|
||||
|
||||
float D = 0.0f - ((x * A[0]) + (y * A[1]) + (z * A[2]));
|
||||
|
||||
plane[0] = x;
|
||||
plane[1] = y;
|
||||
plane[2] = z;
|
||||
plane[3] = D;
|
||||
}
|
||||
|
||||
class Rect3d
|
||||
{
|
||||
public:
|
||||
Rect3d(void){};
|
||||
|
||||
Rect3d(const float *bmin, const float *bmax)
|
||||
{
|
||||
mMin[0] = bmin[0];
|
||||
mMin[1] = bmin[1];
|
||||
mMin[2] = bmin[2];
|
||||
|
||||
mMax[0] = bmax[0];
|
||||
mMax[1] = bmax[1];
|
||||
mMax[2] = bmax[2];
|
||||
}
|
||||
|
||||
void SetMin(const float *bmin)
|
||||
{
|
||||
mMin[0] = bmin[0];
|
||||
mMin[1] = bmin[1];
|
||||
mMin[2] = bmin[2];
|
||||
}
|
||||
|
||||
void SetMax(const float *bmax)
|
||||
{
|
||||
mMax[0] = bmax[0];
|
||||
mMax[1] = bmax[1];
|
||||
mMax[2] = bmax[2];
|
||||
}
|
||||
|
||||
void SetMin(float x, float y, float z)
|
||||
{
|
||||
mMin[0] = x;
|
||||
mMin[1] = y;
|
||||
mMin[2] = z;
|
||||
}
|
||||
|
||||
void SetMax(float x, float y, float z)
|
||||
{
|
||||
mMax[0] = x;
|
||||
mMax[1] = y;
|
||||
mMax[2] = z;
|
||||
}
|
||||
|
||||
float mMin[3];
|
||||
float mMax[3];
|
||||
};
|
||||
|
||||
void splitRect(unsigned int axis,
|
||||
const Rect3d &source,
|
||||
Rect3d &b1,
|
||||
Rect3d &b2,
|
||||
const float *midpoint)
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case 0:
|
||||
b1.SetMin(source.mMin);
|
||||
b1.SetMax(midpoint[0], source.mMax[1], source.mMax[2]);
|
||||
|
||||
b2.SetMin(midpoint[0], source.mMin[1], source.mMin[2]);
|
||||
b2.SetMax(source.mMax);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
b1.SetMin(source.mMin);
|
||||
b1.SetMax(source.mMax[0], midpoint[1], source.mMax[2]);
|
||||
|
||||
b2.SetMin(source.mMin[0], midpoint[1], source.mMin[2]);
|
||||
b2.SetMax(source.mMax);
|
||||
|
||||
break;
|
||||
case 2:
|
||||
b1.SetMin(source.mMin);
|
||||
b1.SetMax(source.mMax[0], source.mMax[1], midpoint[2]);
|
||||
|
||||
b2.SetMin(source.mMin[0], source.mMin[1], midpoint[2]);
|
||||
b2.SetMax(source.mMax);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool computeSplitPlane(unsigned int vcount,
|
||||
const float *vertices,
|
||||
unsigned int tcount,
|
||||
const unsigned int *indices,
|
||||
ConvexDecompInterface *callback,
|
||||
float *plane)
|
||||
{
|
||||
float bmin[3] = {1e9, 1e9, 1e9};
|
||||
float bmax[3] = {-1e9, -1e9, -1e9};
|
||||
|
||||
for (unsigned int i = 0; i < vcount; i++)
|
||||
{
|
||||
const float *p = &vertices[i * 3];
|
||||
|
||||
if (p[0] < bmin[0]) bmin[0] = p[0];
|
||||
if (p[1] < bmin[1]) bmin[1] = p[1];
|
||||
if (p[2] < bmin[2]) bmin[2] = p[2];
|
||||
|
||||
if (p[0] > bmax[0]) bmax[0] = p[0];
|
||||
if (p[1] > bmax[1]) bmax[1] = p[1];
|
||||
if (p[2] > bmax[2]) bmax[2] = p[2];
|
||||
}
|
||||
|
||||
float dx = bmax[0] - bmin[0];
|
||||
float dy = bmax[1] - bmin[1];
|
||||
float dz = bmax[2] - bmin[2];
|
||||
|
||||
float laxis = dx;
|
||||
|
||||
unsigned int axis = 0;
|
||||
|
||||
if (dy > dx)
|
||||
{
|
||||
axis = 1;
|
||||
laxis = dy;
|
||||
}
|
||||
|
||||
if (dz > dx && dz > dy)
|
||||
{
|
||||
axis = 2;
|
||||
laxis = dz;
|
||||
}
|
||||
|
||||
float p1[3];
|
||||
float p2[3];
|
||||
float p3[3];
|
||||
|
||||
p3[0] = p2[0] = p1[0] = bmin[0] + dx * 0.5f;
|
||||
p3[1] = p2[1] = p1[1] = bmin[1] + dy * 0.5f;
|
||||
p3[2] = p2[2] = p1[2] = bmin[2] + dz * 0.5f;
|
||||
|
||||
Rect3d b(bmin, bmax);
|
||||
|
||||
Rect3d b1, b2;
|
||||
|
||||
splitRect(axis, b, b1, b2, p1);
|
||||
|
||||
// callback->ConvexDebugBound(b1.mMin,b1.mMax,0x00FF00);
|
||||
// callback->ConvexDebugBound(b2.mMin,b2.mMax,0xFFFF00);
|
||||
|
||||
switch (axis)
|
||||
{
|
||||
case 0:
|
||||
p2[1] = bmin[1];
|
||||
p2[2] = bmin[2];
|
||||
|
||||
if (dz > dy)
|
||||
{
|
||||
p3[1] = bmax[1];
|
||||
p3[2] = bmin[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
p3[1] = bmin[1];
|
||||
p3[2] = bmax[2];
|
||||
}
|
||||
|
||||
break;
|
||||
case 1:
|
||||
p2[0] = bmin[0];
|
||||
p2[2] = bmin[2];
|
||||
|
||||
if (dx > dz)
|
||||
{
|
||||
p3[0] = bmax[0];
|
||||
p3[2] = bmin[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
p3[0] = bmin[0];
|
||||
p3[2] = bmax[2];
|
||||
}
|
||||
|
||||
break;
|
||||
case 2:
|
||||
p2[0] = bmin[0];
|
||||
p2[1] = bmin[1];
|
||||
|
||||
if (dx > dy)
|
||||
{
|
||||
p3[0] = bmax[0];
|
||||
p3[1] = bmin[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
p3[0] = bmin[0];
|
||||
p3[1] = bmax[1];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// callback->ConvexDebugTri(p1,p2,p3,0xFF0000);
|
||||
|
||||
computePlane(p1, p2, p3, plane);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ConvexDecomposition
|
||||
55
Engine/lib/bullet/Extras/ConvexDecomposition/splitplane.h
Normal file
55
Engine/lib/bullet/Extras/ConvexDecomposition/splitplane.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef SPLIT_PLANE_H
|
||||
|
||||
#define SPLIT_PLANE_H
|
||||
|
||||
//** Computes an 'optimal' split plane for the supplied mesh.
|
||||
//** needs much improvement since it currently just splits along
|
||||
//** the longest side of the AABB.
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
namespace ConvexDecomposition
|
||||
{
|
||||
class ConvexDecompInterface;
|
||||
|
||||
bool computeSplitPlane(unsigned int vcount,
|
||||
const float *vertices,
|
||||
unsigned int tcount,
|
||||
const unsigned int *indices,
|
||||
ConvexDecompInterface *callback,
|
||||
float *plane);
|
||||
|
||||
} // namespace ConvexDecomposition
|
||||
|
||||
#endif
|
||||
311
Engine/lib/bullet/Extras/ConvexDecomposition/vlookup.cpp
Normal file
311
Engine/lib/bullet/Extras/ConvexDecomposition/vlookup.cpp
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
#include "float_math.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#pragma warning(disable : 4786)
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
// CodeSnippet provided by John W. Ratcliff
|
||||
// on March 23, 2006.
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// Personal website: http://jratcliffscarab.blogspot.com
|
||||
// Coding Website: http://codesuppository.blogspot.com
|
||||
// FundRaising Blog: http://amillionpixels.blogspot.com
|
||||
// Fundraising site: http://www.amillionpixels.us
|
||||
// New Temple Site: http://newtemple.blogspot.com
|
||||
//
|
||||
// This snippet shows how to 'hide' the complexity of
|
||||
// the STL by wrapping some useful piece of functionality
|
||||
// around a handful of discrete API calls.
|
||||
//
|
||||
// This API allows you to create an indexed triangle list
|
||||
// from a collection of raw input triangles. Internally
|
||||
// it uses an STL set to build the lookup table very rapidly.
|
||||
//
|
||||
// Here is how you would use it to build an indexed triangle
|
||||
// list from a raw list of triangles.
|
||||
//
|
||||
// (1) create a 'VertexLookup' interface by calling
|
||||
//
|
||||
// VertexLook vl = Vl_createVertexLookup();
|
||||
//
|
||||
// (2) For each vertice in each triangle call:
|
||||
//
|
||||
// unsigned int i1 = Vl_getIndex(vl,p1);
|
||||
// unsigned int i2 = Vl_getIndex(vl,p2);
|
||||
// unsigned int i3 = Vl_getIndex(vl,p3);
|
||||
//
|
||||
// save the 3 indices into your triangle list array.
|
||||
//
|
||||
// (3) Get the vertex array by calling:
|
||||
//
|
||||
// const float *vertices = Vl_getVertices(vl);
|
||||
//
|
||||
// (4) Get the number of vertices so you can copy them into
|
||||
// your own buffer.
|
||||
// unsigned int vcount = Vl_getVcount(vl);
|
||||
//
|
||||
// (5) Release the VertexLookup interface when you are done with it.
|
||||
// Vl_releaseVertexLookup(vl);
|
||||
//
|
||||
// Teaches the following lessons:
|
||||
//
|
||||
// How to wrap the complexity of STL and C++ classes around a
|
||||
// simple API interface.
|
||||
//
|
||||
// How to use an STL set and custom comparator operator for
|
||||
// a complex data type.
|
||||
//
|
||||
// How to create a template class.
|
||||
//
|
||||
// How to achieve significant performance improvements by
|
||||
// taking advantage of built in STL containers in just
|
||||
// a few lines of code.
|
||||
//
|
||||
// You could easily modify this code to support other vertex
|
||||
// formats with any number of interpolants.
|
||||
|
||||
#include "vlookup.h"
|
||||
|
||||
namespace Vlookup
|
||||
{
|
||||
class VertexPosition
|
||||
{
|
||||
public:
|
||||
VertexPosition(void){};
|
||||
VertexPosition(const float *p)
|
||||
{
|
||||
mPos[0] = p[0];
|
||||
mPos[1] = p[1];
|
||||
mPos[2] = p[2];
|
||||
};
|
||||
|
||||
void Set(int index, const float *pos)
|
||||
{
|
||||
const float *p = &pos[index * 3];
|
||||
|
||||
mPos[0] = p[0];
|
||||
mPos[1] = p[1];
|
||||
mPos[2] = p[2];
|
||||
};
|
||||
|
||||
float GetX(void) const { return mPos[0]; };
|
||||
float GetY(void) const { return mPos[1]; };
|
||||
float GetZ(void) const { return mPos[2]; };
|
||||
|
||||
float mPos[3];
|
||||
};
|
||||
|
||||
typedef std::vector<VertexPosition> VertexVector;
|
||||
|
||||
struct Tracker
|
||||
{
|
||||
VertexPosition mFind; // vertice to locate.
|
||||
VertexVector *mList;
|
||||
|
||||
Tracker()
|
||||
{
|
||||
mList = 0;
|
||||
}
|
||||
|
||||
void SetSearch(const VertexPosition &match, VertexVector *list)
|
||||
{
|
||||
mFind = match;
|
||||
mList = list;
|
||||
};
|
||||
};
|
||||
|
||||
struct VertexID
|
||||
{
|
||||
int mID;
|
||||
Tracker *mTracker;
|
||||
|
||||
VertexID(int ID, Tracker *Tracker)
|
||||
{
|
||||
mID = ID;
|
||||
mTracker = Tracker;
|
||||
}
|
||||
};
|
||||
|
||||
class VertexLess
|
||||
{
|
||||
public:
|
||||
bool operator()(VertexID v1, VertexID v2) const;
|
||||
|
||||
private:
|
||||
const VertexPosition &Get(VertexID index) const
|
||||
{
|
||||
if (index.mID == -1) return index.mTracker->mFind;
|
||||
VertexVector &vlist = *index.mTracker->mList;
|
||||
return vlist[index.mID];
|
||||
}
|
||||
};
|
||||
|
||||
template <class Type>
|
||||
class VertexPool
|
||||
{
|
||||
public:
|
||||
typedef std::set<VertexID, VertexLess> VertexSet;
|
||||
typedef std::vector<Type> VertexVector;
|
||||
|
||||
int getVertex(const Type &vtx)
|
||||
{
|
||||
mTracker.SetSearch(vtx, &mVtxs);
|
||||
VertexSet::iterator found;
|
||||
found = mVertSet.find(VertexID(-1, &mTracker));
|
||||
if (found != mVertSet.end())
|
||||
{
|
||||
return found->mID;
|
||||
}
|
||||
int idx = (int)mVtxs.size();
|
||||
mVtxs.push_back(vtx);
|
||||
mVertSet.insert(VertexID(idx, &mTracker));
|
||||
return idx;
|
||||
};
|
||||
|
||||
const float *GetPos(int idx) const
|
||||
{
|
||||
return mVtxs[idx].mPos;
|
||||
}
|
||||
|
||||
const Type &Get(int idx) const
|
||||
{
|
||||
return mVtxs[idx];
|
||||
};
|
||||
|
||||
unsigned int GetSize(void) const
|
||||
{
|
||||
return mVtxs.size();
|
||||
};
|
||||
|
||||
void Clear(int reservesize) // clear the vertice pool.
|
||||
{
|
||||
mVertSet.clear();
|
||||
mVtxs.clear();
|
||||
mVtxs.reserve(reservesize);
|
||||
};
|
||||
|
||||
const VertexVector &GetVertexList(void) const { return mVtxs; };
|
||||
|
||||
void Set(const Type &vtx)
|
||||
{
|
||||
mVtxs.push_back(vtx);
|
||||
}
|
||||
|
||||
unsigned int GetVertexCount(void) const
|
||||
{
|
||||
return mVtxs.size();
|
||||
};
|
||||
|
||||
Type *getBuffer(void)
|
||||
{
|
||||
return &mVtxs[0];
|
||||
};
|
||||
|
||||
private:
|
||||
VertexSet mVertSet; // ordered list.
|
||||
VertexVector mVtxs; // set of vertices.
|
||||
Tracker mTracker;
|
||||
};
|
||||
|
||||
bool VertexLess::operator()(VertexID v1, VertexID v2) const
|
||||
{
|
||||
const VertexPosition &a = Get(v1);
|
||||
const VertexPosition &b = Get(v2);
|
||||
|
||||
int ixA = (int)(a.GetX() * 10000.0f);
|
||||
int ixB = (int)(b.GetX() * 10000.0f);
|
||||
|
||||
if (ixA < ixB) return true;
|
||||
if (ixA > ixB) return false;
|
||||
|
||||
int iyA = (int)(a.GetY() * 10000.0f);
|
||||
int iyB = (int)(b.GetY() * 10000.0f);
|
||||
|
||||
if (iyA < iyB) return true;
|
||||
if (iyA > iyB) return false;
|
||||
|
||||
int izA = (int)(a.GetZ() * 10000.0f);
|
||||
int izB = (int)(b.GetZ() * 10000.0f);
|
||||
|
||||
if (izA < izB) return true;
|
||||
if (izA > izB) return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Vlookup
|
||||
|
||||
using namespace Vlookup;
|
||||
|
||||
VertexLookup Vl_createVertexLookup(void)
|
||||
{
|
||||
VertexLookup ret = new VertexPool<VertexPosition>;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Vl_releaseVertexLookup(VertexLookup vlook)
|
||||
{
|
||||
VertexPool<VertexPosition> *vp = (VertexPool<VertexPosition> *)vlook;
|
||||
delete vp;
|
||||
}
|
||||
|
||||
unsigned int Vl_getIndex(VertexLookup vlook, const float *pos) // get index.
|
||||
{
|
||||
VertexPool<VertexPosition> *vp = (VertexPool<VertexPosition> *)vlook;
|
||||
VertexPosition p(pos);
|
||||
return vp->getVertex(p);
|
||||
}
|
||||
|
||||
const float *Vl_getVertices(VertexLookup vlook)
|
||||
{
|
||||
VertexPool<VertexPosition> *vp = (VertexPool<VertexPosition> *)vlook;
|
||||
return vp->GetPos(0);
|
||||
}
|
||||
|
||||
unsigned int Vl_getVcount(VertexLookup vlook)
|
||||
{
|
||||
VertexPool<VertexPosition> *vp = (VertexPool<VertexPosition> *)vlook;
|
||||
return vp->GetVertexCount();
|
||||
}
|
||||
115
Engine/lib/bullet/Extras/ConvexDecomposition/vlookup.h
Normal file
115
Engine/lib/bullet/Extras/ConvexDecomposition/vlookup.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
#ifndef VLOOKUP_H
|
||||
|
||||
#define VLOOKUP_H
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Copyright (c) 2004 Open Dynamics Framework Group
|
||||
www.physicstools.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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 INTEL 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.
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
// http://codesuppository.blogspot.com
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// http://www.amillionpixels.us
|
||||
//
|
||||
|
||||
// CodeSnippet provided by John W. Ratcliff
|
||||
// on March 23, 2006.
|
||||
//
|
||||
// mailto: jratcliff@infiniplex.net
|
||||
//
|
||||
// Personal website: http://jratcliffscarab.blogspot.com
|
||||
// Coding Website: http://codesuppository.blogspot.com
|
||||
// FundRaising Blog: http://amillionpixels.blogspot.com
|
||||
// Fundraising site: http://www.amillionpixels.us
|
||||
// New Temple Site: http://newtemple.blogspot.com
|
||||
//
|
||||
// This snippet shows how to 'hide' the complexity of
|
||||
// the STL by wrapping some useful piece of functionality
|
||||
// around a handful of discrete API calls.
|
||||
//
|
||||
// This API allows you to create an indexed triangle list
|
||||
// from a collection of raw input triangles. Internally
|
||||
// it uses an STL set to build the lookup table very rapidly.
|
||||
//
|
||||
// Here is how you would use it to build an indexed triangle
|
||||
// list from a raw list of triangles.
|
||||
//
|
||||
// (1) create a 'VertexLookup' interface by calling
|
||||
//
|
||||
// VertexLook vl = Vl_createVertexLookup();
|
||||
//
|
||||
// (2) For each vertice in each triangle call:
|
||||
//
|
||||
// unsigned int i1 = Vl_getIndex(vl,p1);
|
||||
// unsigned int i2 = Vl_getIndex(vl,p2);
|
||||
// unsigned int i3 = Vl_getIndex(vl,p3);
|
||||
//
|
||||
// save the 3 indices into your triangle list array.
|
||||
//
|
||||
// (3) Get the vertex array by calling:
|
||||
//
|
||||
// const float *vertices = Vl_getVertices(vl);
|
||||
//
|
||||
// (4) Get the number of vertices so you can copy them into
|
||||
// your own buffer.
|
||||
// unsigned int vcount = Vl_getVcount(vl);
|
||||
//
|
||||
// (5) Release the VertexLookup interface when you are done with it.
|
||||
// Vl_releaseVertexLookup(vl);
|
||||
//
|
||||
// Teaches the following lessons:
|
||||
//
|
||||
// How to wrap the complexity of STL and C++ classes around a
|
||||
// simple API interface.
|
||||
//
|
||||
// How to use an STL set and custom comparator operator for
|
||||
// a complex data type.
|
||||
//
|
||||
// How to create a template class.
|
||||
//
|
||||
// How to achieve significant performance improvements by
|
||||
// taking advantage of built in STL containers in just
|
||||
// a few lines of code.
|
||||
//
|
||||
// You could easily modify this code to support other vertex
|
||||
// formats with any number of interpolants.
|
||||
//
|
||||
// Hide C++ classes from the rest of your application by
|
||||
// keeping them in the CPP and wrapping them in a namespace
|
||||
// Uses an STL set to create an index table for a bunch of vertex positions
|
||||
// used typically to re-index a collection of raw triangle data.
|
||||
|
||||
typedef void *VertexLookup;
|
||||
|
||||
VertexLookup Vl_createVertexLookup(void);
|
||||
void Vl_releaseVertexLookup(VertexLookup vlook);
|
||||
|
||||
unsigned int Vl_getIndex(VertexLookup vlook, const float *pos); // get index.
|
||||
const float *Vl_getVertices(VertexLookup vlook);
|
||||
unsigned int Vl_getVcount(VertexLookup vlook);
|
||||
|
||||
#endif
|
||||
40
Engine/lib/bullet/Extras/GIMPACTUtils/CMakeLists.txt
Normal file
40
Engine/lib/bullet/Extras/GIMPACTUtils/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACT/include
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACTUtils
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexDecomposition
|
||||
)
|
||||
|
||||
ADD_LIBRARY(GIMPACTUtils
|
||||
btGImpactConvexDecompositionShape.cpp btGImpactConvexDecompositionShape.h
|
||||
)
|
||||
SET_TARGET_PROPERTIES(GIMPACTUtils PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(GIMPACTUtils PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
TARGET_LINK_LIBRARIES(GIMPACTUtils ConvexDecomposition BulletCollision)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
IF (INSTALL_EXTRA_LIBS)
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
#FILES_MATCHING requires CMake 2.6
|
||||
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS GIMPACTUtils DESTINATION .)
|
||||
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS GIMPACTUtils
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib${LIB_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LIB_SUFFIX})
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
|
||||
".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(GIMPACTUtils PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(GIMPACTUtils PROPERTIES PUBLIC_HEADER "btGImpactConvexDecompositionShape.h")
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ENDIF (INSTALL_EXTRA_LIBS)
|
||||
11
Engine/lib/bullet/Extras/GIMPACTUtils/LICENSE.txt
Normal file
11
Engine/lib/bullet/Extras/GIMPACTUtils/LICENSE.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
This source file is part of GIMPACT Library.
|
||||
|
||||
For the latest info, see http://gimpact.sourceforge.net/
|
||||
|
||||
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btGImpactConvexDecompositionShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
|
||||
|
||||
#include "ConvexBuilder.h"
|
||||
|
||||
class GIM_ConvexDecomposition : public ConvexDecomposition::ConvexDecompInterface
|
||||
{
|
||||
protected:
|
||||
btGImpactConvexDecompositionShape* m_compoundShape;
|
||||
|
||||
btAlignedObjectArray<btCollisionShape*> m_convexShapes;
|
||||
|
||||
public:
|
||||
int mBaseCount;
|
||||
int mHullCount;
|
||||
bool m_transformSubShapes;
|
||||
|
||||
GIM_ConvexDecomposition(btGImpactConvexDecompositionShape* compoundShape, bool transformSubShapes)
|
||||
{
|
||||
mBaseCount = 0;
|
||||
mHullCount = 0;
|
||||
m_compoundShape = compoundShape;
|
||||
m_transformSubShapes = transformSubShapes;
|
||||
}
|
||||
|
||||
virtual ~GIM_ConvexDecomposition()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < m_convexShapes.size(); i++)
|
||||
{
|
||||
btCollisionShape* shape = m_convexShapes[i];
|
||||
delete shape;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ConvexDecompResult(ConvexDecomposition::ConvexResult& result)
|
||||
{
|
||||
//calc centroid, to shift vertices around center of mass
|
||||
btVector3 centroid(0, 0, 0);
|
||||
btAlignedObjectArray<btVector3> vertices;
|
||||
|
||||
if (m_transformSubShapes)
|
||||
{
|
||||
//const unsigned int *src = result.mHullIndices;
|
||||
for (unsigned int i = 0; i < result.mHullVcount; i++)
|
||||
{
|
||||
btVector3 vertex(result.mHullVertices[i * 3], result.mHullVertices[i * 3 + 1], result.mHullVertices[i * 3 + 2]);
|
||||
|
||||
centroid += vertex;
|
||||
}
|
||||
centroid *= 1.f / (float(result.mHullVcount));
|
||||
}
|
||||
|
||||
// collect vertices
|
||||
for (unsigned int i = 0; i < result.mHullVcount; i++)
|
||||
{
|
||||
btVector3 vertex(result.mHullVertices[i * 3], result.mHullVertices[i * 3 + 1], result.mHullVertices[i * 3 + 2]);
|
||||
|
||||
if (m_transformSubShapes)
|
||||
{
|
||||
vertex -= centroid;
|
||||
}
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
|
||||
// build convex shape
|
||||
|
||||
btCollisionShape* convexShape = new btConvexHullShape(
|
||||
&(vertices[0].getX()), vertices.size(), sizeof(btVector3));
|
||||
m_convexShapes.push_back(convexShape);
|
||||
|
||||
convexShape->setMargin(m_compoundShape->getMargin());
|
||||
|
||||
if (m_transformSubShapes)
|
||||
{
|
||||
btTransform trans;
|
||||
trans.setIdentity();
|
||||
trans.setOrigin(centroid);
|
||||
|
||||
// add convex shape
|
||||
|
||||
m_compoundShape->addChildShape(trans, convexShape);
|
||||
}
|
||||
else
|
||||
{
|
||||
btTransform trans;
|
||||
trans.setIdentity();
|
||||
//trans.setOrigin(centroid);
|
||||
|
||||
// add convex shape
|
||||
|
||||
m_compoundShape->addChildShape(trans, convexShape);
|
||||
|
||||
//m_compoundShape->addChildShape(convexShape);
|
||||
}
|
||||
}
|
||||
|
||||
void processDecomposition(int part)
|
||||
{
|
||||
btGImpactMeshShapePart::TrimeshPrimitiveManager* trimeshInterface =
|
||||
m_compoundShape->getTrimeshInterface(part);
|
||||
|
||||
trimeshInterface->lock();
|
||||
|
||||
//collect vertices
|
||||
btAlignedObjectArray<float> vertices;
|
||||
vertices.reserve(trimeshInterface->get_vertex_count() * 3);
|
||||
|
||||
for (int vi = 0; vi < trimeshInterface->get_vertex_count(); vi++)
|
||||
{
|
||||
btVector3 vec;
|
||||
trimeshInterface->get_vertex(vi, vec);
|
||||
vertices.push_back(vec[0]);
|
||||
vertices.push_back(vec[1]);
|
||||
vertices.push_back(vec[2]);
|
||||
}
|
||||
|
||||
//collect indices
|
||||
btAlignedObjectArray<unsigned int> indices;
|
||||
indices.reserve(trimeshInterface->get_primitive_count() * 3);
|
||||
|
||||
for (int i = 0; i < trimeshInterface->get_primitive_count(); i++)
|
||||
{
|
||||
unsigned int i0, i1, i2;
|
||||
trimeshInterface->get_indices(i, i0, i1, i2);
|
||||
indices.push_back(i0);
|
||||
indices.push_back(i1);
|
||||
indices.push_back(i2);
|
||||
}
|
||||
|
||||
trimeshInterface->unlock();
|
||||
|
||||
unsigned int depth = 5;
|
||||
float cpercent = 5;
|
||||
float ppercent = 15;
|
||||
unsigned int maxv = 16;
|
||||
float skinWidth = 0.0f;
|
||||
|
||||
ConvexDecomposition::DecompDesc desc;
|
||||
desc.mVcount = trimeshInterface->get_vertex_count();
|
||||
desc.mVertices = &vertices[0];
|
||||
desc.mTcount = trimeshInterface->get_primitive_count();
|
||||
desc.mIndices = &indices[0];
|
||||
desc.mDepth = depth;
|
||||
desc.mCpercent = cpercent;
|
||||
desc.mPpercent = ppercent;
|
||||
desc.mMaxVertices = maxv;
|
||||
desc.mSkinWidth = skinWidth;
|
||||
desc.mCallback = this;
|
||||
|
||||
//convexDecomposition.performConvexDecomposition(desc);
|
||||
|
||||
ConvexBuilder cb(desc.mCallback);
|
||||
cb.process(desc);
|
||||
}
|
||||
};
|
||||
|
||||
void btGImpactConvexDecompositionShape::buildConvexDecomposition(bool transformSubShapes)
|
||||
{
|
||||
m_decomposition = new GIM_ConvexDecomposition(this, transformSubShapes);
|
||||
|
||||
int part_count = m_trimeshInterfaces.size();
|
||||
for (int i = 0; i < part_count; i++)
|
||||
{
|
||||
m_decomposition->processDecomposition(i);
|
||||
}
|
||||
|
||||
postUpdate();
|
||||
}
|
||||
|
||||
btGImpactConvexDecompositionShape::~btGImpactConvexDecompositionShape()
|
||||
{
|
||||
delete m_decomposition;
|
||||
}
|
||||
void btGImpactConvexDecompositionShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
|
||||
{
|
||||
int part_count = m_trimeshInterfaces.size();
|
||||
for (int part = 0; part < part_count; part++)
|
||||
{
|
||||
void* ptr = (void*)&m_trimeshInterfaces[part];
|
||||
|
||||
btGImpactMeshShapePart::TrimeshPrimitiveManager* trimeshInterface =
|
||||
static_cast<btGImpactMeshShapePart::TrimeshPrimitiveManager*>(ptr);
|
||||
|
||||
trimeshInterface->lock();
|
||||
|
||||
btPrimitiveTriangle triangle;
|
||||
|
||||
int i = trimeshInterface->get_primitive_count();
|
||||
while (i--)
|
||||
{
|
||||
trimeshInterface->get_primitive_triangle(i, triangle);
|
||||
callback->processTriangle(triangle.m_vertices, part, i);
|
||||
}
|
||||
|
||||
trimeshInterface->unlock();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*! \file btGImpactConvexDecompositionShape.h
|
||||
\author Francisco León Nájera
|
||||
*/
|
||||
/*
|
||||
This source file is part of GIMPACT Library.
|
||||
|
||||
For the latest info, see http://gimpact.sourceforge.net/
|
||||
|
||||
Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
|
||||
email: projectileman@yahoo.com
|
||||
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef GIMPACT_CONVEX_DECOMPOSITION_SHAPE_H
|
||||
#define GIMPACT_CONVEX_DECOMPOSITION_SHAPE_H
|
||||
|
||||
#include "BulletCollision/Gimpact/btGImpactShape.h" // box tree class
|
||||
|
||||
//! This class creates a decomposition from a trimesh.
|
||||
/*!
|
||||
|
||||
*/
|
||||
class btGImpactConvexDecompositionShape : public btGImpactCompoundShape
|
||||
{
|
||||
protected:
|
||||
btAlignedObjectArray<btGImpactMeshShapePart::TrimeshPrimitiveManager> m_trimeshInterfaces;
|
||||
|
||||
class GIM_ConvexDecomposition* m_decomposition;
|
||||
|
||||
void buildConvexDecomposition(bool transformSubShapes);
|
||||
|
||||
public:
|
||||
btGImpactConvexDecompositionShape(
|
||||
btStridingMeshInterface* meshInterface,
|
||||
const btVector3& mesh_scale,
|
||||
btScalar margin = btScalar(0.01), bool children_has_transform = true)
|
||||
: btGImpactCompoundShape(children_has_transform)
|
||||
{
|
||||
m_collisionMargin = margin;
|
||||
|
||||
btGImpactMeshShapePart::TrimeshPrimitiveManager triInterface;
|
||||
triInterface.m_meshInterface = meshInterface;
|
||||
triInterface.m_scale = mesh_scale;
|
||||
triInterface.m_margin = btScalar(1.0);
|
||||
|
||||
//add parts
|
||||
int part_count = meshInterface->getNumSubParts();
|
||||
for (int i = 0; i < part_count; i++)
|
||||
{
|
||||
triInterface.m_part = i;
|
||||
m_trimeshInterfaces.push_back(triInterface);
|
||||
}
|
||||
|
||||
m_decomposition = 0;
|
||||
|
||||
buildConvexDecomposition(children_has_transform);
|
||||
}
|
||||
|
||||
virtual ~btGImpactConvexDecompositionShape();
|
||||
|
||||
SIMD_FORCE_INLINE btGImpactMeshShapePart::TrimeshPrimitiveManager* getTrimeshInterface(int part)
|
||||
{
|
||||
return &m_trimeshInterfaces[part];
|
||||
}
|
||||
|
||||
virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
|
||||
};
|
||||
|
||||
#endif //GIMPACT_MESH_SHAPE_H
|
||||
55
Engine/lib/bullet/Extras/HACD/CMakeLists.txt
Normal file
55
Engine/lib/bullet/Extras/HACD/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/HACD
|
||||
)
|
||||
|
||||
SET(HACD_SRCS
|
||||
hacdGraph.cpp
|
||||
hacdHACD.cpp
|
||||
hacdICHull.cpp
|
||||
hacdManifoldMesh.cpp
|
||||
)
|
||||
|
||||
SET(HACD_HDRS
|
||||
hacdCircularList.h
|
||||
hacdGraph.h
|
||||
hacdHACD.h
|
||||
hacdICHull.h
|
||||
hacdManifoldMesh.h
|
||||
hacdVector.h
|
||||
hacdVersion.h
|
||||
hacdCircularList.inl
|
||||
hacdVector.inl
|
||||
)
|
||||
|
||||
ADD_LIBRARY(HACD ${HACD_SRCS} ${HACD_HDRS})
|
||||
SET_TARGET_PROPERTIES(HACD PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(HACD PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
|
||||
#IF (BUILD_SHARED_LIBS)
|
||||
# TARGET_LINK_LIBRARIES(HACD BulletCollision LinearMath)
|
||||
#ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
IF (INSTALL_EXTRA_LIBS)
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
#FILES_MATCHING requires CMake 2.6
|
||||
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS HACD DESTINATION .)
|
||||
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS HACD
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib${LIB_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LIB_SUFFIX})
|
||||
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN "*.inl" PATTERN
|
||||
".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(HACD PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(HACD PROPERTIES PUBLIC_HEADER "${HACD_HDRS}")
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ENDIF (INSTALL_EXTRA_LIBS)
|
||||
13
Engine/lib/bullet/Extras/HACD/LICENSE.txt
Normal file
13
Engine/lib/bullet/Extras/HACD/LICENSE.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
86
Engine/lib/bullet/Extras/HACD/hacdCircularList.h
Normal file
86
Engine/lib/bullet/Extras/HACD/hacdCircularList.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_CIRCULAR_LIST_H
|
||||
#define HACD_CIRCULAR_LIST_H
|
||||
#include <stdlib.h>
|
||||
#include "hacdVersion.h"
|
||||
namespace HACD
|
||||
{
|
||||
//! CircularListElement class.
|
||||
template <typename T>
|
||||
class CircularListElement
|
||||
{
|
||||
public:
|
||||
T& GetData() { return m_data; }
|
||||
const T& GetData() const { return m_data; }
|
||||
CircularListElement<T>*& GetNext() { return m_next; }
|
||||
CircularListElement<T>*& GetPrev() { return m_prev; }
|
||||
const CircularListElement<T>*& GetNext() const { return m_next; }
|
||||
const CircularListElement<T>*& GetPrev() const { return m_prev; }
|
||||
//! Constructor
|
||||
CircularListElement(const T& data) { m_data = data; }
|
||||
CircularListElement(void) {}
|
||||
//! Destructor
|
||||
~CircularListElement(void) {}
|
||||
|
||||
private:
|
||||
T m_data;
|
||||
CircularListElement<T>* m_next;
|
||||
CircularListElement<T>* m_prev;
|
||||
|
||||
CircularListElement(const CircularListElement& rhs);
|
||||
};
|
||||
|
||||
//! CircularList class.
|
||||
template <typename T>
|
||||
class CircularList
|
||||
{
|
||||
public:
|
||||
CircularListElement<T>*& GetHead() { return m_head; }
|
||||
const CircularListElement<T>* GetHead() const { return m_head; }
|
||||
bool IsEmpty() const { return (m_size == 0); }
|
||||
size_t GetSize() const { return m_size; }
|
||||
const T& GetData() const { return m_head->GetData(); }
|
||||
T& GetData() { return m_head->GetData(); }
|
||||
bool Delete();
|
||||
bool Delete(CircularListElement<T>* element);
|
||||
CircularListElement<T>* Add(const T* data = 0);
|
||||
CircularListElement<T>* Add(const T& data);
|
||||
bool Next();
|
||||
bool Prev();
|
||||
void Clear()
|
||||
{
|
||||
while (Delete())
|
||||
;
|
||||
};
|
||||
const CircularList& operator=(const CircularList& rhs);
|
||||
//! Constructor
|
||||
CircularList()
|
||||
{
|
||||
m_head = 0;
|
||||
m_size = 0;
|
||||
}
|
||||
CircularList(const CircularList& rhs);
|
||||
//! Destructor
|
||||
virtual ~CircularList(void) { Clear(); };
|
||||
|
||||
private:
|
||||
CircularListElement<T>* m_head; //!< a pointer to the head of the circular list
|
||||
size_t m_size; //!< number of element in the circular list
|
||||
};
|
||||
} // namespace HACD
|
||||
#include "hacdCircularList.inl"
|
||||
#endif
|
||||
163
Engine/lib/bullet/Extras/HACD/hacdCircularList.inl
Normal file
163
Engine/lib/bullet/Extras/HACD/hacdCircularList.inl
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
#pragma once
|
||||
#ifndef HACD_CIRCULAR_LIST_INL
|
||||
#define HACD_CIRCULAR_LIST_INL
|
||||
#include<stdlib.h>
|
||||
#include "hacdVersion.h"
|
||||
namespace HACD
|
||||
{
|
||||
template < typename T >
|
||||
inline bool CircularList<T>::Delete(CircularListElement<T> * element)
|
||||
{
|
||||
if (!element)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (m_size > 1)
|
||||
{
|
||||
CircularListElement<T> * next = element->GetNext();
|
||||
CircularListElement<T> * prev = element->GetPrev();
|
||||
delete element;
|
||||
m_size--;
|
||||
if (element == m_head)
|
||||
{
|
||||
m_head = next;
|
||||
}
|
||||
next->GetPrev() = prev;
|
||||
prev->GetNext() = next;
|
||||
return true;
|
||||
}
|
||||
else if (m_size == 1)
|
||||
{
|
||||
delete m_head;
|
||||
m_size--;
|
||||
m_head = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
inline bool CircularList<T>::Delete()
|
||||
{
|
||||
if (m_size > 1)
|
||||
{
|
||||
CircularListElement<T> * next = m_head->GetNext();
|
||||
CircularListElement<T> * prev = m_head->GetPrev();
|
||||
delete m_head;
|
||||
m_size--;
|
||||
m_head = next;
|
||||
next->GetPrev() = prev;
|
||||
prev->GetNext() = next;
|
||||
return true;
|
||||
}
|
||||
else if (m_size == 1)
|
||||
{
|
||||
delete m_head;
|
||||
m_size--;
|
||||
m_head = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template < typename T >
|
||||
inline CircularListElement<T> * CircularList<T>::Add(const T * data)
|
||||
{
|
||||
if (m_size == 0)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
m_head = new CircularListElement<T>(*data);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_head = new CircularListElement<T>();
|
||||
}
|
||||
m_head->GetNext() = m_head->GetPrev() = m_head;
|
||||
}
|
||||
else
|
||||
{
|
||||
CircularListElement<T> * next = m_head->GetNext();
|
||||
CircularListElement<T> * element = m_head;
|
||||
if (data)
|
||||
{
|
||||
m_head = new CircularListElement<T>(*data);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_head = new CircularListElement<T>;
|
||||
}
|
||||
m_head->GetNext() = next;
|
||||
m_head->GetPrev() = element;
|
||||
element->GetNext() = m_head;
|
||||
next->GetPrev() = m_head;
|
||||
}
|
||||
m_size++;
|
||||
return m_head;
|
||||
}
|
||||
template < typename T >
|
||||
inline CircularListElement<T> * CircularList<T>::Add(const T & data)
|
||||
{
|
||||
const T * pData = &data;
|
||||
return Add(pData);
|
||||
}
|
||||
template < typename T >
|
||||
inline bool CircularList<T>::Next()
|
||||
{
|
||||
if (m_size == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_head = m_head->GetNext();
|
||||
return true;
|
||||
}
|
||||
template < typename T >
|
||||
inline bool CircularList<T>::Prev()
|
||||
{
|
||||
if (m_size == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_head = m_head->GetPrev();
|
||||
return true;
|
||||
}
|
||||
template < typename T >
|
||||
inline CircularList<T>::CircularList(const CircularList& rhs)
|
||||
{
|
||||
if (rhs.m_size > 0)
|
||||
{
|
||||
CircularListElement<T> * current = rhs.m_head;
|
||||
do
|
||||
{
|
||||
current = current->GetNext();
|
||||
Add(current->GetData());
|
||||
}
|
||||
while ( current != rhs.m_head );
|
||||
}
|
||||
}
|
||||
template < typename T >
|
||||
inline const CircularList<T>& CircularList<T>::operator=(const CircularList& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
Clear();
|
||||
if (rhs.m_size > 0)
|
||||
{
|
||||
CircularListElement<T> * current = rhs.m_head;
|
||||
do
|
||||
{
|
||||
current = current->GetNext();
|
||||
Add(current->GetData());
|
||||
}
|
||||
while ( current != rhs.m_head );
|
||||
}
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
290
Engine/lib/bullet/Extras/HACD/hacdGraph.cpp
Normal file
290
Engine/lib/bullet/Extras/HACD/hacdGraph.cpp
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
*/
|
||||
#include "hacdGraph.h"
|
||||
namespace HACD
|
||||
{
|
||||
GraphEdge::GraphEdge()
|
||||
{
|
||||
m_convexHull = 0;
|
||||
m_v1 = -1;
|
||||
m_v2 = -1;
|
||||
m_name = -1;
|
||||
m_error = 0;
|
||||
m_surf = 0;
|
||||
m_perimeter = 0;
|
||||
m_concavity = 0;
|
||||
m_volume = 0;
|
||||
m_deleted = false;
|
||||
}
|
||||
|
||||
GraphVertex::GraphVertex()
|
||||
{
|
||||
m_convexHull = 0;
|
||||
m_name = -1;
|
||||
m_cc = -1;
|
||||
m_error = 0;
|
||||
m_surf = 0;
|
||||
m_perimeter = 0;
|
||||
m_concavity = 0;
|
||||
m_volume = 0;
|
||||
m_deleted = false;
|
||||
}
|
||||
|
||||
bool GraphVertex::DeleteEdge(long name)
|
||||
{
|
||||
std::set<long>::iterator it = m_edges.find(name);
|
||||
if (it != m_edges.end())
|
||||
{
|
||||
m_edges.erase(it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Graph::Graph()
|
||||
{
|
||||
m_nV = 0;
|
||||
m_nE = 0;
|
||||
m_nCCs = 0;
|
||||
}
|
||||
|
||||
Graph::~Graph()
|
||||
{
|
||||
}
|
||||
|
||||
void Graph::Allocate(size_t nV, size_t nE)
|
||||
{
|
||||
m_nV = nV;
|
||||
m_edges.reserve(nE);
|
||||
m_vertices.resize(nV);
|
||||
for (size_t i = 0; i < nV; i++)
|
||||
{
|
||||
m_vertices[i].m_name = static_cast<long>(i);
|
||||
}
|
||||
}
|
||||
|
||||
long Graph::AddVertex()
|
||||
{
|
||||
size_t name = m_vertices.size();
|
||||
m_vertices.resize(name + 1);
|
||||
m_vertices[name].m_name = static_cast<long>(name);
|
||||
m_nV++;
|
||||
return static_cast<long>(name);
|
||||
}
|
||||
|
||||
long Graph::AddEdge(long v1, long v2)
|
||||
{
|
||||
size_t name = m_edges.size();
|
||||
m_edges.push_back(GraphEdge());
|
||||
m_edges[name].m_name = static_cast<long>(name);
|
||||
m_edges[name].m_v1 = v1;
|
||||
m_edges[name].m_v2 = v2;
|
||||
m_vertices[v1].AddEdge(static_cast<long>(name));
|
||||
m_vertices[v2].AddEdge(static_cast<long>(name));
|
||||
m_nE++;
|
||||
return static_cast<long>(name);
|
||||
}
|
||||
|
||||
bool Graph::DeleteEdge(long name)
|
||||
{
|
||||
if (name < static_cast<long>(m_edges.size()))
|
||||
{
|
||||
long v1 = m_edges[name].m_v1;
|
||||
long v2 = m_edges[name].m_v2;
|
||||
m_edges[name].m_deleted = true;
|
||||
m_vertices[v1].DeleteEdge(name);
|
||||
m_vertices[v2].DeleteEdge(name);
|
||||
delete m_edges[name].m_convexHull;
|
||||
m_edges[name].m_distPoints.clear();
|
||||
m_edges[name].m_boudaryEdges.clear();
|
||||
m_edges[name].m_convexHull = 0;
|
||||
m_nE--;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Graph::DeleteVertex(long name)
|
||||
{
|
||||
if (name < static_cast<long>(m_vertices.size()))
|
||||
{
|
||||
m_vertices[name].m_deleted = true;
|
||||
m_vertices[name].m_edges.clear();
|
||||
m_vertices[name].m_ancestors = std::vector<long>();
|
||||
delete m_vertices[name].m_convexHull;
|
||||
m_vertices[name].m_distPoints.clear();
|
||||
m_vertices[name].m_boudaryEdges.clear();
|
||||
m_vertices[name].m_convexHull = 0;
|
||||
m_nV--;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Graph::EdgeCollapse(long v1, long v2)
|
||||
{
|
||||
long edgeToDelete = GetEdgeID(v1, v2);
|
||||
if (edgeToDelete >= 0)
|
||||
{
|
||||
// delete the edge (v1, v2)
|
||||
DeleteEdge(edgeToDelete);
|
||||
// add v2 to v1 ancestors
|
||||
m_vertices[v1].m_ancestors.push_back(v2);
|
||||
// add v2's ancestors to v1's ancestors
|
||||
m_vertices[v1].m_ancestors.insert(m_vertices[v1].m_ancestors.begin(),
|
||||
m_vertices[v2].m_ancestors.begin(),
|
||||
m_vertices[v2].m_ancestors.end());
|
||||
// update adjacency information
|
||||
std::set<long>& v1Edges = m_vertices[v1].m_edges;
|
||||
std::set<long>::const_iterator ed(m_vertices[v2].m_edges.begin());
|
||||
std::set<long>::const_iterator itEnd(m_vertices[v2].m_edges.end());
|
||||
long b = -1;
|
||||
for (; ed != itEnd; ++ed)
|
||||
{
|
||||
if (m_edges[*ed].m_v1 == v2)
|
||||
{
|
||||
b = m_edges[*ed].m_v2;
|
||||
}
|
||||
else
|
||||
{
|
||||
b = m_edges[*ed].m_v1;
|
||||
}
|
||||
if (GetEdgeID(v1, b) >= 0)
|
||||
{
|
||||
m_edges[*ed].m_deleted = true;
|
||||
m_vertices[b].DeleteEdge(*ed);
|
||||
m_nE--;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_edges[*ed].m_v1 = v1;
|
||||
m_edges[*ed].m_v2 = b;
|
||||
v1Edges.insert(*ed);
|
||||
}
|
||||
}
|
||||
// delete the vertex v2
|
||||
DeleteVertex(v2);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
long Graph::GetEdgeID(long v1, long v2) const
|
||||
{
|
||||
if (v1 < static_cast<long>(m_vertices.size()) && !m_vertices[v1].m_deleted)
|
||||
{
|
||||
std::set<long>::const_iterator ed(m_vertices[v1].m_edges.begin());
|
||||
std::set<long>::const_iterator itEnd(m_vertices[v1].m_edges.end());
|
||||
for (; ed != itEnd; ++ed)
|
||||
{
|
||||
if ((m_edges[*ed].m_v1 == v2) ||
|
||||
(m_edges[*ed].m_v2 == v2))
|
||||
{
|
||||
return m_edges[*ed].m_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Graph::Print() const
|
||||
{
|
||||
std::cout << "-----------------------------" << std::endl;
|
||||
std::cout << "vertices (" << m_nV << ")" << std::endl;
|
||||
for (size_t v = 0; v < m_vertices.size(); ++v)
|
||||
{
|
||||
const GraphVertex& currentVertex = m_vertices[v];
|
||||
if (!m_vertices[v].m_deleted)
|
||||
{
|
||||
std::cout << currentVertex.m_name << "\t";
|
||||
std::set<long>::const_iterator ed(currentVertex.m_edges.begin());
|
||||
std::set<long>::const_iterator itEnd(currentVertex.m_edges.end());
|
||||
for (; ed != itEnd; ++ed)
|
||||
{
|
||||
std::cout << "(" << m_edges[*ed].m_v1 << "," << m_edges[*ed].m_v2 << ") ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "vertices (" << m_nE << ")" << std::endl;
|
||||
for (size_t e = 0; e < m_edges.size(); ++e)
|
||||
{
|
||||
const GraphEdge& currentEdge = m_edges[e];
|
||||
if (!m_edges[e].m_deleted)
|
||||
{
|
||||
std::cout << currentEdge.m_name << "\t("
|
||||
<< m_edges[e].m_v1 << ","
|
||||
<< m_edges[e].m_v2 << ") " << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
void Graph::Clear()
|
||||
{
|
||||
m_vertices.clear();
|
||||
m_edges.clear();
|
||||
m_nV = 0;
|
||||
m_nE = 0;
|
||||
}
|
||||
|
||||
long Graph::ExtractCCs()
|
||||
{
|
||||
// all CCs to -1
|
||||
for (size_t v = 0; v < m_vertices.size(); ++v)
|
||||
{
|
||||
if (!m_vertices[v].m_deleted)
|
||||
{
|
||||
m_vertices[v].m_cc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// we get the CCs
|
||||
m_nCCs = 0;
|
||||
long v2 = -1;
|
||||
std::vector<long> temp;
|
||||
for (size_t v = 0; v < m_vertices.size(); ++v)
|
||||
{
|
||||
if (!m_vertices[v].m_deleted && m_vertices[v].m_cc == -1)
|
||||
{
|
||||
m_vertices[v].m_cc = static_cast<long>(m_nCCs);
|
||||
temp.clear();
|
||||
temp.push_back(m_vertices[v].m_name);
|
||||
while (temp.size())
|
||||
{
|
||||
long vertex = temp[temp.size() - 1];
|
||||
temp.pop_back();
|
||||
std::set<long>::const_iterator ed(m_vertices[vertex].m_edges.begin());
|
||||
std::set<long>::const_iterator itEnd(m_vertices[vertex].m_edges.end());
|
||||
for (; ed != itEnd; ++ed)
|
||||
{
|
||||
if (m_edges[*ed].m_v1 == vertex)
|
||||
{
|
||||
v2 = m_edges[*ed].m_v2;
|
||||
}
|
||||
else
|
||||
{
|
||||
v2 = m_edges[*ed].m_v1;
|
||||
}
|
||||
if (!m_vertices[v2].m_deleted && m_vertices[v2].m_cc == -1)
|
||||
{
|
||||
m_vertices[v2].m_cc = static_cast<long>(m_nCCs);
|
||||
temp.push_back(v2);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_nCCs++;
|
||||
}
|
||||
}
|
||||
return static_cast<long>(m_nCCs);
|
||||
}
|
||||
} // namespace HACD
|
||||
119
Engine/lib/bullet/Extras/HACD/hacdGraph.h
Normal file
119
Engine/lib/bullet/Extras/HACD/hacdGraph.h
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_GRAPH_H
|
||||
#define HACD_GRAPH_H
|
||||
#include "hacdVersion.h"
|
||||
#include "hacdVector.h"
|
||||
#include "hacdICHull.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace HACD
|
||||
{
|
||||
class GraphVertex;
|
||||
class GraphEdge;
|
||||
class Graph;
|
||||
class HACD;
|
||||
|
||||
class GraphVertex
|
||||
{
|
||||
public:
|
||||
bool AddEdge(long name)
|
||||
{
|
||||
m_edges.insert(name);
|
||||
return true;
|
||||
}
|
||||
bool DeleteEdge(long name);
|
||||
GraphVertex();
|
||||
~GraphVertex() { delete m_convexHull; };
|
||||
|
||||
private:
|
||||
long m_name;
|
||||
long m_cc;
|
||||
std::set<long> m_edges;
|
||||
bool m_deleted;
|
||||
std::vector<long> m_ancestors;
|
||||
std::map<long, DPoint> m_distPoints;
|
||||
|
||||
Real m_error;
|
||||
double m_surf;
|
||||
double m_volume;
|
||||
double m_perimeter;
|
||||
double m_concavity;
|
||||
ICHull* m_convexHull;
|
||||
std::set<unsigned long long> m_boudaryEdges;
|
||||
|
||||
friend class GraphEdge;
|
||||
friend class Graph;
|
||||
friend class HACD;
|
||||
};
|
||||
|
||||
class GraphEdge
|
||||
{
|
||||
public:
|
||||
GraphEdge();
|
||||
~GraphEdge() { delete m_convexHull; };
|
||||
|
||||
private:
|
||||
long m_name;
|
||||
long m_v1;
|
||||
long m_v2;
|
||||
std::map<long, DPoint> m_distPoints;
|
||||
Real m_error;
|
||||
double m_surf;
|
||||
double m_volume;
|
||||
double m_perimeter;
|
||||
double m_concavity;
|
||||
ICHull* m_convexHull;
|
||||
std::set<unsigned long long> m_boudaryEdges;
|
||||
bool m_deleted;
|
||||
|
||||
friend class GraphVertex;
|
||||
friend class Graph;
|
||||
friend class HACD;
|
||||
};
|
||||
|
||||
class Graph
|
||||
{
|
||||
public:
|
||||
size_t GetNEdges() const { return m_nE; }
|
||||
size_t GetNVertices() const { return m_nV; }
|
||||
bool EdgeCollapse(long v1, long v2);
|
||||
long AddVertex();
|
||||
long AddEdge(long v1, long v2);
|
||||
bool DeleteEdge(long name);
|
||||
bool DeleteVertex(long name);
|
||||
long GetEdgeID(long v1, long v2) const;
|
||||
void Clear();
|
||||
void Print() const;
|
||||
long ExtractCCs();
|
||||
|
||||
Graph();
|
||||
virtual ~Graph();
|
||||
void Allocate(size_t nV, size_t nE);
|
||||
|
||||
private:
|
||||
size_t m_nCCs;
|
||||
size_t m_nV;
|
||||
size_t m_nE;
|
||||
std::vector<GraphEdge> m_edges;
|
||||
std::vector<GraphVertex> m_vertices;
|
||||
|
||||
friend class HACD;
|
||||
};
|
||||
} // namespace HACD
|
||||
#endif
|
||||
851
Engine/lib/bullet/Extras/HACD/hacdHACD.cpp
Normal file
851
Engine/lib/bullet/Extras/HACD/hacdHACD.cpp
Normal file
|
|
@ -0,0 +1,851 @@
|
|||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
*/
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif //_CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <sstream>
|
||||
#include "hacdGraph.h"
|
||||
#include "hacdHACD.h"
|
||||
#include "hacdICHull.h"
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include "assert.h"
|
||||
|
||||
bool gCancelRequest = false;
|
||||
namespace HACD
|
||||
{
|
||||
double HACD::Concavity(ICHull& ch, std::map<long, DPoint>& distPoints)
|
||||
{
|
||||
double concavity = 0.0;
|
||||
double distance = 0.0;
|
||||
std::map<long, DPoint>::iterator itDP(distPoints.begin());
|
||||
std::map<long, DPoint>::iterator itDPEnd(distPoints.end());
|
||||
for (; itDP != itDPEnd; ++itDP)
|
||||
{
|
||||
if (!(itDP->second).m_computed)
|
||||
{
|
||||
if (itDP->first >= 0)
|
||||
{
|
||||
distance = ch.ComputeDistance(itDP->first, m_points[itDP->first], m_normals[itDP->first], (itDP->second).m_computed, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = ch.ComputeDistance(itDP->first, m_facePoints[-itDP->first - 1], m_faceNormals[-itDP->first - 1], (itDP->second).m_computed, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = (itDP->second).m_dist;
|
||||
}
|
||||
if (concavity < distance)
|
||||
{
|
||||
concavity = distance;
|
||||
}
|
||||
}
|
||||
return concavity;
|
||||
}
|
||||
|
||||
void HACD::CreateGraph()
|
||||
{
|
||||
// vertex to triangle adjacency information
|
||||
std::vector<std::set<long> > vertexToTriangles;
|
||||
vertexToTriangles.resize(m_nPoints);
|
||||
for (size_t t = 0; t < m_nTriangles; ++t)
|
||||
{
|
||||
vertexToTriangles[m_triangles[t].X()].insert(static_cast<long>(t));
|
||||
vertexToTriangles[m_triangles[t].Y()].insert(static_cast<long>(t));
|
||||
vertexToTriangles[m_triangles[t].Z()].insert(static_cast<long>(t));
|
||||
}
|
||||
|
||||
m_graph.Clear();
|
||||
m_graph.Allocate(m_nTriangles, 5 * m_nTriangles);
|
||||
unsigned long long tr1[3];
|
||||
unsigned long long tr2[3];
|
||||
long i1, j1, k1, i2, j2, k2;
|
||||
long t1, t2;
|
||||
for (size_t v = 0; v < m_nPoints; v++)
|
||||
{
|
||||
std::set<long>::const_iterator it1(vertexToTriangles[v].begin()), itEnd(vertexToTriangles[v].end());
|
||||
for (; it1 != itEnd; ++it1)
|
||||
{
|
||||
t1 = *it1;
|
||||
i1 = m_triangles[t1].X();
|
||||
j1 = m_triangles[t1].Y();
|
||||
k1 = m_triangles[t1].Z();
|
||||
tr1[0] = GetEdgeIndex(i1, j1);
|
||||
tr1[1] = GetEdgeIndex(j1, k1);
|
||||
tr1[2] = GetEdgeIndex(k1, i1);
|
||||
std::set<long>::const_iterator it2(it1);
|
||||
for (++it2; it2 != itEnd; ++it2)
|
||||
{
|
||||
t2 = *it2;
|
||||
i2 = m_triangles[t2].X();
|
||||
j2 = m_triangles[t2].Y();
|
||||
k2 = m_triangles[t2].Z();
|
||||
tr2[0] = GetEdgeIndex(i2, j2);
|
||||
tr2[1] = GetEdgeIndex(j2, k2);
|
||||
tr2[2] = GetEdgeIndex(k2, i2);
|
||||
int shared = 0;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
if (tr1[i] == tr2[j])
|
||||
{
|
||||
shared++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shared == 1) // two triangles are connected if they share exactly one edge
|
||||
{
|
||||
m_graph.AddEdge(t1, t2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_ccConnectDist >= 0.0)
|
||||
{
|
||||
m_graph.ExtractCCs();
|
||||
if (m_graph.m_nCCs > 1)
|
||||
{
|
||||
std::vector<std::set<long> > cc2V;
|
||||
cc2V.resize(m_graph.m_nCCs);
|
||||
long cc;
|
||||
for (size_t t = 0; t < m_nTriangles; ++t)
|
||||
{
|
||||
cc = m_graph.m_vertices[t].m_cc;
|
||||
cc2V[cc].insert(m_triangles[t].X());
|
||||
cc2V[cc].insert(m_triangles[t].Y());
|
||||
cc2V[cc].insert(m_triangles[t].Z());
|
||||
}
|
||||
|
||||
for (size_t cc1 = 0; cc1 < m_graph.m_nCCs; ++cc1)
|
||||
{
|
||||
for (size_t cc2 = cc1 + 1; cc2 < m_graph.m_nCCs; ++cc2)
|
||||
{
|
||||
std::set<long>::const_iterator itV1(cc2V[cc1].begin()), itVEnd1(cc2V[cc1].end());
|
||||
for (; itV1 != itVEnd1; ++itV1)
|
||||
{
|
||||
double distC1C2 = std::numeric_limits<double>::max();
|
||||
double dist;
|
||||
t1 = -1;
|
||||
t2 = -1;
|
||||
std::set<long>::const_iterator itV2(cc2V[cc2].begin()), itVEnd2(cc2V[cc2].end());
|
||||
for (; itV2 != itVEnd2; ++itV2)
|
||||
{
|
||||
dist = (m_points[*itV1] - m_points[*itV2]).GetNorm();
|
||||
if (dist < distC1C2)
|
||||
{
|
||||
distC1C2 = dist;
|
||||
t1 = *vertexToTriangles[*itV1].begin();
|
||||
|
||||
std::set<long>::const_iterator it2(vertexToTriangles[*itV2].begin()),
|
||||
it2End(vertexToTriangles[*itV2].end());
|
||||
t2 = -1;
|
||||
for (; it2 != it2End; ++it2)
|
||||
{
|
||||
if (*it2 != t1)
|
||||
{
|
||||
t2 = *it2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (distC1C2 <= m_ccConnectDist && t1 > 0 && t2 > 0)
|
||||
{
|
||||
m_graph.AddEdge(t1, t2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void HACD::InitializeDualGraph()
|
||||
{
|
||||
long i, j, k;
|
||||
Vec3<Real> u, v, w, normal;
|
||||
delete[] m_normals;
|
||||
m_normals = new Vec3<Real>[m_nPoints];
|
||||
if (m_addFacesPoints)
|
||||
{
|
||||
delete[] m_facePoints;
|
||||
delete[] m_faceNormals;
|
||||
m_facePoints = new Vec3<Real>[m_nTriangles];
|
||||
m_faceNormals = new Vec3<Real>[m_nTriangles];
|
||||
}
|
||||
memset(m_normals, 0, sizeof(Vec3<Real>) * m_nPoints);
|
||||
for (unsigned long f = 0; f < m_nTriangles; f++)
|
||||
{
|
||||
if (m_callBack) (*m_callBack)("+ InitializeDualGraph\n", f, m_nTriangles, 0);
|
||||
|
||||
if (gCancelRequest)
|
||||
return;
|
||||
|
||||
i = m_triangles[f].X();
|
||||
j = m_triangles[f].Y();
|
||||
k = m_triangles[f].Z();
|
||||
|
||||
m_graph.m_vertices[f].m_distPoints[i].m_distOnly = false;
|
||||
m_graph.m_vertices[f].m_distPoints[j].m_distOnly = false;
|
||||
m_graph.m_vertices[f].m_distPoints[k].m_distOnly = false;
|
||||
|
||||
ICHull* ch = new ICHull;
|
||||
m_graph.m_vertices[f].m_convexHull = ch;
|
||||
ch->AddPoint(m_points[i], i);
|
||||
ch->AddPoint(m_points[j], j);
|
||||
ch->AddPoint(m_points[k], k);
|
||||
ch->SetDistPoints(&m_graph.m_vertices[f].m_distPoints);
|
||||
|
||||
u = m_points[j] - m_points[i];
|
||||
v = m_points[k] - m_points[i];
|
||||
w = m_points[k] - m_points[j];
|
||||
normal = u ^ v;
|
||||
|
||||
m_normals[i] += normal;
|
||||
m_normals[j] += normal;
|
||||
m_normals[k] += normal;
|
||||
|
||||
m_graph.m_vertices[f].m_surf = normal.GetNorm();
|
||||
m_graph.m_vertices[f].m_perimeter = u.GetNorm() + v.GetNorm() + w.GetNorm();
|
||||
|
||||
normal.Normalize();
|
||||
|
||||
m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(i, j));
|
||||
m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(j, k));
|
||||
m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(k, i));
|
||||
if (m_addFacesPoints)
|
||||
{
|
||||
m_faceNormals[f] = normal;
|
||||
m_facePoints[f] = (m_points[i] + m_points[j] + m_points[k]) / 3.0;
|
||||
m_graph.m_vertices[f].m_distPoints[-static_cast<long>(f) - 1].m_distOnly = true;
|
||||
}
|
||||
if (m_addExtraDistPoints)
|
||||
{ // we need a kd-tree structure to accelerate this part!
|
||||
long i1, j1, k1;
|
||||
Vec3<Real> u1, v1, normal1;
|
||||
normal = -normal;
|
||||
double distance = 0.0;
|
||||
double distMin = 0.0;
|
||||
size_t faceIndex = m_nTriangles;
|
||||
Vec3<Real> seedPoint((m_points[i] + m_points[j] + m_points[k]) / 3.0);
|
||||
long nhit = 0;
|
||||
for (size_t f1 = 0; f1 < m_nTriangles; f1++)
|
||||
{
|
||||
i1 = m_triangles[f1].X();
|
||||
j1 = m_triangles[f1].Y();
|
||||
k1 = m_triangles[f1].Z();
|
||||
u1 = m_points[j1] - m_points[i1];
|
||||
v1 = m_points[k1] - m_points[i1];
|
||||
normal1 = (u1 ^ v1);
|
||||
if (normal * normal1 > 0.0)
|
||||
{
|
||||
nhit = IntersectRayTriangle(Vec3<double>(seedPoint.X(), seedPoint.Y(), seedPoint.Z()),
|
||||
Vec3<double>(normal.X(), normal.Y(), normal.Z()),
|
||||
Vec3<double>(m_points[i1].X(), m_points[i1].Y(), m_points[i1].Z()),
|
||||
Vec3<double>(m_points[j1].X(), m_points[j1].Y(), m_points[j1].Z()),
|
||||
Vec3<double>(m_points[k1].X(), m_points[k1].Y(), m_points[k1].Z()),
|
||||
distance);
|
||||
if ((nhit == 1) && ((distMin > distance) || (faceIndex == m_nTriangles)))
|
||||
{
|
||||
distMin = distance;
|
||||
faceIndex = f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (faceIndex < m_nTriangles)
|
||||
{
|
||||
i1 = m_triangles[faceIndex].X();
|
||||
j1 = m_triangles[faceIndex].Y();
|
||||
k1 = m_triangles[faceIndex].Z();
|
||||
m_graph.m_vertices[f].m_distPoints[i1].m_distOnly = true;
|
||||
m_graph.m_vertices[f].m_distPoints[j1].m_distOnly = true;
|
||||
m_graph.m_vertices[f].m_distPoints[k1].m_distOnly = true;
|
||||
if (m_addFacesPoints)
|
||||
{
|
||||
m_graph.m_vertices[f].m_distPoints[-static_cast<long>(faceIndex) - 1].m_distOnly = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t v = 0; v < m_nPoints; v++)
|
||||
{
|
||||
m_normals[v].Normalize();
|
||||
}
|
||||
}
|
||||
|
||||
void HACD::NormalizeData()
|
||||
{
|
||||
if (m_nPoints == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_barycenter = m_points[0];
|
||||
Vec3<Real> min = m_points[0];
|
||||
Vec3<Real> max = m_points[0];
|
||||
Real x, y, z;
|
||||
for (size_t v = 1; v < m_nPoints; v++)
|
||||
{
|
||||
m_barycenter += m_points[v];
|
||||
x = m_points[v].X();
|
||||
y = m_points[v].Y();
|
||||
z = m_points[v].Z();
|
||||
if (x < min.X())
|
||||
min.X() = x;
|
||||
else if (x > max.X())
|
||||
max.X() = x;
|
||||
if (y < min.Y())
|
||||
min.Y() = y;
|
||||
else if (y > max.Y())
|
||||
max.Y() = y;
|
||||
if (z < min.Z())
|
||||
min.Z() = z;
|
||||
else if (z > max.Z())
|
||||
max.Z() = z;
|
||||
}
|
||||
m_barycenter /= static_cast<Real>(m_nPoints);
|
||||
m_diag = (max - min).GetNorm();
|
||||
const Real invDiag = static_cast<Real>(2.0 * m_scale / m_diag);
|
||||
if (m_diag != 0.0)
|
||||
{
|
||||
for (size_t v = 0; v < m_nPoints; v++)
|
||||
{
|
||||
m_points[v] = (m_points[v] - m_barycenter) * invDiag;
|
||||
}
|
||||
}
|
||||
}
|
||||
void HACD::DenormalizeData()
|
||||
{
|
||||
if (m_nPoints == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (m_diag != 0.0)
|
||||
{
|
||||
const Real diag = static_cast<Real>(m_diag / (2.0 * m_scale));
|
||||
for (size_t v = 0; v < m_nPoints; v++)
|
||||
{
|
||||
m_points[v] = m_points[v] * diag + m_barycenter;
|
||||
}
|
||||
}
|
||||
}
|
||||
HACD::HACD(void)
|
||||
{
|
||||
m_convexHulls = 0;
|
||||
m_triangles = 0;
|
||||
m_points = 0;
|
||||
m_normals = 0;
|
||||
m_nTriangles = 0;
|
||||
m_nPoints = 0;
|
||||
m_nClusters = 0;
|
||||
m_concavity = 0.0;
|
||||
m_diag = 1.0;
|
||||
m_barycenter = Vec3<Real>(0.0, 0.0, 0.0);
|
||||
m_alpha = 0.1;
|
||||
m_beta = 0.1;
|
||||
m_nVerticesPerCH = 30;
|
||||
m_callBack = 0;
|
||||
m_addExtraDistPoints = false;
|
||||
m_addNeighboursDistPoints = false;
|
||||
m_scale = 1000.0;
|
||||
m_partition = 0;
|
||||
m_nMinClusters = 3;
|
||||
m_facePoints = 0;
|
||||
m_faceNormals = 0;
|
||||
m_ccConnectDist = 30;
|
||||
}
|
||||
HACD::~HACD(void)
|
||||
{
|
||||
delete[] m_normals;
|
||||
delete[] m_convexHulls;
|
||||
delete[] m_partition;
|
||||
delete[] m_facePoints;
|
||||
delete[] m_faceNormals;
|
||||
}
|
||||
int iteration = 0;
|
||||
void HACD::ComputeEdgeCost(size_t e)
|
||||
{
|
||||
GraphEdge& gE = m_graph.m_edges[e];
|
||||
long v1 = gE.m_v1;
|
||||
long v2 = gE.m_v2;
|
||||
|
||||
if (m_graph.m_vertices[v2].m_distPoints.size() > m_graph.m_vertices[v1].m_distPoints.size())
|
||||
{
|
||||
gE.m_v1 = v2;
|
||||
gE.m_v2 = v1;
|
||||
//std::swap<long>(v1, v2);
|
||||
std::swap(v1, v2);
|
||||
}
|
||||
GraphVertex& gV1 = m_graph.m_vertices[v1];
|
||||
GraphVertex& gV2 = m_graph.m_vertices[v2];
|
||||
|
||||
// delete old convex-hull
|
||||
delete gE.m_convexHull;
|
||||
// create the edge's convex-hull
|
||||
ICHull* ch = new ICHull;
|
||||
gE.m_convexHull = ch;
|
||||
(*ch) = (*gV1.m_convexHull);
|
||||
|
||||
// update distPoints
|
||||
gE.m_distPoints = gV1.m_distPoints;
|
||||
std::map<long, DPoint>::iterator itDP(gV2.m_distPoints.begin());
|
||||
std::map<long, DPoint>::iterator itDPEnd(gV2.m_distPoints.end());
|
||||
std::map<long, DPoint>::iterator itDP1;
|
||||
|
||||
for (; itDP != itDPEnd; ++itDP)
|
||||
{
|
||||
itDP1 = gE.m_distPoints.find(itDP->first);
|
||||
if (itDP1 == gE.m_distPoints.end())
|
||||
{
|
||||
gE.m_distPoints[itDP->first].m_distOnly = (itDP->second).m_distOnly;
|
||||
if (!(itDP->second).m_distOnly)
|
||||
{
|
||||
ch->AddPoint(m_points[itDP->first], itDP->first);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((itDP1->second).m_distOnly && !(itDP->second).m_distOnly)
|
||||
{
|
||||
gE.m_distPoints[itDP->first].m_distOnly = false;
|
||||
ch->AddPoint(m_points[itDP->first], itDP->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ch->SetDistPoints(&gE.m_distPoints);
|
||||
// create the convex-hull
|
||||
while (ch->Process() == ICHullErrorInconsistent) // if we face problems when constructing the visual-hull. really ugly!!!!
|
||||
{
|
||||
// if (m_callBack) (*m_callBack)("\t Problem with convex-hull construction [HACD::ComputeEdgeCost]\n", 0.0, 0.0, 0);
|
||||
ch = new ICHull;
|
||||
CircularList<TMMVertex>& verticesCH = (gE.m_convexHull)->GetMesh().m_vertices;
|
||||
size_t nV = verticesCH.GetSize();
|
||||
long ptIndex = 0;
|
||||
verticesCH.Next();
|
||||
for (size_t v = 1; v < nV; ++v)
|
||||
{
|
||||
ptIndex = verticesCH.GetHead()->GetData().m_name;
|
||||
if (ptIndex != ICHull::sc_dummyIndex /* && ptIndex < m_nPoints*/)
|
||||
ch->AddPoint(m_points[ptIndex], ptIndex);
|
||||
verticesCH.Next();
|
||||
}
|
||||
delete gE.m_convexHull;
|
||||
gE.m_convexHull = ch;
|
||||
}
|
||||
double volume = 0.0;
|
||||
double concavity = 0.0;
|
||||
if (ch->IsFlat())
|
||||
{
|
||||
bool insideHull;
|
||||
std::map<long, DPoint>::iterator itDP(gE.m_distPoints.begin());
|
||||
std::map<long, DPoint>::iterator itDPEnd(gE.m_distPoints.end());
|
||||
for (; itDP != itDPEnd; ++itDP)
|
||||
{
|
||||
if (itDP->first >= 0)
|
||||
{
|
||||
concavity = std::max<double>(concavity, ch->ComputeDistance(itDP->first, m_points[itDP->first], m_normals[itDP->first], insideHull, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_addNeighboursDistPoints)
|
||||
{ // add distance points from adjacent clusters
|
||||
std::set<long> eEdges;
|
||||
std::set_union(gV1.m_edges.begin(),
|
||||
gV1.m_edges.end(),
|
||||
gV2.m_edges.begin(),
|
||||
gV2.m_edges.end(),
|
||||
std::inserter(eEdges, eEdges.begin()));
|
||||
|
||||
std::set<long>::const_iterator ed(eEdges.begin());
|
||||
std::set<long>::const_iterator itEnd(eEdges.end());
|
||||
long a, b, c;
|
||||
for (; ed != itEnd; ++ed)
|
||||
{
|
||||
a = m_graph.m_edges[*ed].m_v1;
|
||||
b = m_graph.m_edges[*ed].m_v2;
|
||||
if (a != v2 && a != v1)
|
||||
{
|
||||
c = a;
|
||||
}
|
||||
else if (b != v2 && b != v1)
|
||||
{
|
||||
c = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = -1;
|
||||
}
|
||||
if (c > 0)
|
||||
{
|
||||
GraphVertex& gVC = m_graph.m_vertices[c];
|
||||
std::map<long, DPoint>::iterator itDP(gVC.m_distPoints.begin());
|
||||
std::map<long, DPoint>::iterator itDPEnd(gVC.m_distPoints.end());
|
||||
std::map<long, DPoint>::iterator itDP1;
|
||||
for (; itDP != itDPEnd; ++itDP)
|
||||
{
|
||||
itDP1 = gE.m_distPoints.find(itDP->first);
|
||||
if (itDP1 == gE.m_distPoints.end())
|
||||
{
|
||||
if (itDP->first >= 0 && itDP1 == gE.m_distPoints.end() && ch->IsInside(m_points[itDP->first]))
|
||||
{
|
||||
gE.m_distPoints[itDP->first].m_distOnly = true;
|
||||
}
|
||||
else if (itDP->first < 0 && ch->IsInside(m_facePoints[-itDP->first - 1]))
|
||||
{
|
||||
gE.m_distPoints[itDP->first].m_distOnly = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
concavity = Concavity(*ch, gE.m_distPoints);
|
||||
}
|
||||
|
||||
// compute boudary edges
|
||||
double perimeter = 0.0;
|
||||
double surf = 1.0;
|
||||
if (m_alpha > 0.0)
|
||||
{
|
||||
gE.m_boudaryEdges.clear();
|
||||
std::set_symmetric_difference(gV1.m_boudaryEdges.begin(),
|
||||
gV1.m_boudaryEdges.end(),
|
||||
gV2.m_boudaryEdges.begin(),
|
||||
gV2.m_boudaryEdges.end(),
|
||||
std::inserter(gE.m_boudaryEdges,
|
||||
gE.m_boudaryEdges.begin()));
|
||||
|
||||
std::set<unsigned long long>::const_iterator itBE(gE.m_boudaryEdges.begin());
|
||||
std::set<unsigned long long>::const_iterator itBEEnd(gE.m_boudaryEdges.end());
|
||||
for (; itBE != itBEEnd; ++itBE)
|
||||
{
|
||||
perimeter += (m_points[static_cast<long>((*itBE) >> 32)] -
|
||||
m_points[static_cast<long>((*itBE) & 0xFFFFFFFFULL)])
|
||||
.GetNorm();
|
||||
}
|
||||
surf = gV1.m_surf + gV2.m_surf;
|
||||
}
|
||||
double ratio = perimeter * perimeter / (4.0 * sc_pi * surf);
|
||||
gE.m_volume = (m_beta == 0.0) ? 0.0 : ch->ComputeVolume() / pow(m_scale, 3.0); // cluster's volume
|
||||
gE.m_surf = surf; // cluster's area
|
||||
gE.m_perimeter = perimeter; // cluster's perimeter
|
||||
gE.m_concavity = concavity; // cluster's concavity
|
||||
gE.m_error = static_cast<Real>(concavity + m_alpha * ratio + m_beta * volume); // cluster's priority
|
||||
}
|
||||
bool HACD::InitializePriorityQueue()
|
||||
{
|
||||
m_pqueue.reserve(m_graph.m_nE + 100);
|
||||
for (size_t e = 0; e < m_graph.m_nE; ++e)
|
||||
{
|
||||
ComputeEdgeCost(static_cast<long>(e));
|
||||
m_pqueue.push(GraphEdgePriorityQueue(static_cast<long>(e), m_graph.m_edges[e].m_error));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void HACD::Simplify()
|
||||
{
|
||||
long v1 = -1;
|
||||
long v2 = -1;
|
||||
double progressOld = -1.0;
|
||||
double progress = 0.0;
|
||||
double globalConcavity = 0.0;
|
||||
char msg[1024];
|
||||
double ptgStep = 1.0;
|
||||
while ((globalConcavity < m_concavity) &&
|
||||
(m_graph.GetNVertices() > m_nMinClusters) &&
|
||||
(m_graph.GetNEdges() > 0))
|
||||
{
|
||||
progress = 100.0 - m_graph.GetNVertices() * 100.0 / m_nTriangles;
|
||||
if (fabs(progress - progressOld) > ptgStep && m_callBack)
|
||||
{
|
||||
sprintf(msg, "%3.2f %% V = %lu \t C = %f \t \t \r", progress, static_cast<unsigned long>(m_graph.GetNVertices()), globalConcavity);
|
||||
(*m_callBack)(msg, progress, globalConcavity, m_graph.GetNVertices());
|
||||
progressOld = progress;
|
||||
if (progress > 99.0)
|
||||
{
|
||||
ptgStep = 0.01;
|
||||
}
|
||||
else if (progress > 90.0)
|
||||
{
|
||||
ptgStep = 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
GraphEdgePriorityQueue currentEdge(0, 0.0);
|
||||
bool done = false;
|
||||
do
|
||||
{
|
||||
done = false;
|
||||
if (m_pqueue.size() == 0)
|
||||
{
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
currentEdge = m_pqueue.top();
|
||||
m_pqueue.pop();
|
||||
} while (m_graph.m_edges[currentEdge.m_name].m_deleted ||
|
||||
m_graph.m_edges[currentEdge.m_name].m_error != currentEdge.m_priority);
|
||||
|
||||
if (m_graph.m_edges[currentEdge.m_name].m_concavity < m_concavity && !done)
|
||||
{
|
||||
globalConcavity = std::max<double>(globalConcavity, m_graph.m_edges[currentEdge.m_name].m_concavity);
|
||||
v1 = m_graph.m_edges[currentEdge.m_name].m_v1;
|
||||
v2 = m_graph.m_edges[currentEdge.m_name].m_v2;
|
||||
// update vertex info
|
||||
m_graph.m_vertices[v1].m_error = m_graph.m_edges[currentEdge.m_name].m_error;
|
||||
m_graph.m_vertices[v1].m_surf = m_graph.m_edges[currentEdge.m_name].m_surf;
|
||||
m_graph.m_vertices[v1].m_volume = m_graph.m_edges[currentEdge.m_name].m_volume;
|
||||
m_graph.m_vertices[v1].m_concavity = m_graph.m_edges[currentEdge.m_name].m_concavity;
|
||||
m_graph.m_vertices[v1].m_perimeter = m_graph.m_edges[currentEdge.m_name].m_perimeter;
|
||||
m_graph.m_vertices[v1].m_distPoints = m_graph.m_edges[currentEdge.m_name].m_distPoints;
|
||||
(*m_graph.m_vertices[v1].m_convexHull) = (*m_graph.m_edges[currentEdge.m_name].m_convexHull);
|
||||
(m_graph.m_vertices[v1].m_convexHull)->SetDistPoints(&(m_graph.m_vertices[v1].m_distPoints));
|
||||
m_graph.m_vertices[v1].m_boudaryEdges = m_graph.m_edges[currentEdge.m_name].m_boudaryEdges;
|
||||
|
||||
// We apply the optimal ecol
|
||||
// std::cout << "v1 " << v1 << " v2 " << v2 << std::endl;
|
||||
m_graph.EdgeCollapse(v1, v2);
|
||||
// recompute the adjacent edges costs
|
||||
std::set<long>::const_iterator itE(m_graph.m_vertices[v1].m_edges.begin()),
|
||||
itEEnd(m_graph.m_vertices[v1].m_edges.end());
|
||||
for (; itE != itEEnd; ++itE)
|
||||
{
|
||||
size_t e = *itE;
|
||||
ComputeEdgeCost(static_cast<long>(e));
|
||||
m_pqueue.push(GraphEdgePriorityQueue(static_cast<long>(e), m_graph.m_edges[e].m_error));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!m_pqueue.empty())
|
||||
{
|
||||
m_pqueue.pop();
|
||||
}
|
||||
|
||||
m_cVertices.clear();
|
||||
m_nClusters = m_graph.GetNVertices();
|
||||
m_cVertices.reserve(m_nClusters);
|
||||
for (size_t p = 0, v = 0; v != m_graph.m_vertices.size(); ++v)
|
||||
{
|
||||
if (!m_graph.m_vertices[v].m_deleted)
|
||||
{
|
||||
if (m_callBack)
|
||||
{
|
||||
char msg[1024];
|
||||
sprintf(msg, "\t CH \t %lu \t %lf \t %lf\n", static_cast<unsigned long>(p), m_graph.m_vertices[v].m_concavity, m_graph.m_vertices[v].m_error);
|
||||
(*m_callBack)(msg, 0.0, 0.0, m_nClusters);
|
||||
p++;
|
||||
}
|
||||
m_cVertices.push_back(static_cast<long>(v));
|
||||
}
|
||||
}
|
||||
if (m_callBack)
|
||||
{
|
||||
sprintf(msg, "# clusters = %lu \t C = %f\n", static_cast<unsigned long>(m_nClusters), globalConcavity);
|
||||
(*m_callBack)(msg, progress, globalConcavity, m_graph.GetNVertices());
|
||||
}
|
||||
}
|
||||
|
||||
bool HACD::Compute(bool fullCH, bool exportDistPoints)
|
||||
{
|
||||
gCancelRequest = false;
|
||||
|
||||
if (!m_points || !m_triangles || !m_nPoints || !m_nTriangles)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
size_t nV = m_nTriangles;
|
||||
if (m_callBack)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << "+ Mesh" << std::endl;
|
||||
msg << "\t # vertices \t" << m_nPoints << std::endl;
|
||||
msg << "\t # triangles \t" << m_nTriangles << std::endl;
|
||||
msg << "+ Parameters" << std::endl;
|
||||
msg << "\t min # of clusters \t" << m_nMinClusters << std::endl;
|
||||
msg << "\t max concavity \t" << m_concavity << std::endl;
|
||||
msg << "\t compacity weigth \t" << m_alpha << std::endl;
|
||||
msg << "\t volume weigth \t" << m_beta << std::endl;
|
||||
msg << "\t # vertices per convex-hull \t" << m_nVerticesPerCH << std::endl;
|
||||
msg << "\t scale \t" << m_scale << std::endl;
|
||||
msg << "\t add extra distance points \t" << m_addExtraDistPoints << std::endl;
|
||||
msg << "\t add neighbours distance points \t" << m_addNeighboursDistPoints << std::endl;
|
||||
msg << "\t add face distance points \t" << m_addFacesPoints << std::endl;
|
||||
msg << "\t produce full convex-hulls \t" << fullCH << std::endl;
|
||||
msg << "\t max. distance to connect CCs \t" << m_ccConnectDist << std::endl;
|
||||
(*m_callBack)(msg.str().c_str(), 0.0, 0.0, nV);
|
||||
}
|
||||
if (m_callBack) (*m_callBack)("+ Normalizing Data\n", 0.0, 0.0, nV);
|
||||
NormalizeData();
|
||||
if (m_callBack) (*m_callBack)("+ Creating Graph\n", 0.0, 0.0, nV);
|
||||
CreateGraph();
|
||||
// Compute the surfaces and perimeters of all the faces
|
||||
if (m_callBack) (*m_callBack)("+ Initializing Dual Graph\n", 0.0, 0.0, nV);
|
||||
if (gCancelRequest)
|
||||
return false;
|
||||
|
||||
InitializeDualGraph();
|
||||
if (m_callBack) (*m_callBack)("+ Initializing Priority Queue\n", 0.0, 0.0, nV);
|
||||
if (gCancelRequest)
|
||||
return false;
|
||||
|
||||
InitializePriorityQueue();
|
||||
// we simplify the graph
|
||||
if (m_callBack) (*m_callBack)("+ Simplification ...\n", 0.0, 0.0, m_nTriangles);
|
||||
Simplify();
|
||||
if (m_callBack) (*m_callBack)("+ Denormalizing Data\n", 0.0, 0.0, m_nClusters);
|
||||
DenormalizeData();
|
||||
if (m_callBack) (*m_callBack)("+ Computing final convex-hulls\n", 0.0, 0.0, m_nClusters);
|
||||
delete[] m_convexHulls;
|
||||
m_convexHulls = new ICHull[m_nClusters];
|
||||
delete[] m_partition;
|
||||
m_partition = new long[m_nTriangles];
|
||||
for (size_t p = 0; p != m_cVertices.size(); ++p)
|
||||
{
|
||||
size_t v = m_cVertices[p];
|
||||
m_partition[v] = static_cast<long>(p);
|
||||
for (size_t a = 0; a < m_graph.m_vertices[v].m_ancestors.size(); a++)
|
||||
{
|
||||
m_partition[m_graph.m_vertices[v].m_ancestors[a]] = static_cast<long>(p);
|
||||
}
|
||||
// compute the convex-hull
|
||||
const std::map<long, DPoint>& pointsCH = m_graph.m_vertices[v].m_distPoints;
|
||||
std::map<long, DPoint>::const_iterator itCH(pointsCH.begin());
|
||||
std::map<long, DPoint>::const_iterator itCHEnd(pointsCH.end());
|
||||
for (; itCH != itCHEnd; ++itCH)
|
||||
{
|
||||
if (!(itCH->second).m_distOnly)
|
||||
{
|
||||
m_convexHulls[p].AddPoint(m_points[itCH->first], itCH->first);
|
||||
}
|
||||
}
|
||||
m_convexHulls[p].SetDistPoints(&m_graph.m_vertices[v].m_distPoints);
|
||||
if (fullCH)
|
||||
{
|
||||
m_convexHulls[p].Process();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_convexHulls[p].Process(static_cast<unsigned long>(m_nVerticesPerCH));
|
||||
}
|
||||
if (exportDistPoints)
|
||||
{
|
||||
itCH = pointsCH.begin();
|
||||
for (; itCH != itCHEnd; ++itCH)
|
||||
{
|
||||
if ((itCH->second).m_distOnly)
|
||||
{
|
||||
if (itCH->first >= 0)
|
||||
{
|
||||
m_convexHulls[p].AddPoint(m_points[itCH->first], itCH->first);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_convexHulls[p].AddPoint(m_facePoints[-itCH->first - 1], itCH->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t HACD::GetNTrianglesCH(size_t numCH) const
|
||||
{
|
||||
if (numCH >= m_nClusters)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return m_convexHulls[numCH].GetMesh().GetNTriangles();
|
||||
}
|
||||
size_t HACD::GetNPointsCH(size_t numCH) const
|
||||
{
|
||||
if (numCH >= m_nClusters)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return m_convexHulls[numCH].GetMesh().GetNVertices();
|
||||
}
|
||||
|
||||
bool HACD::GetCH(size_t numCH, Vec3<Real>* const points, Vec3<long>* const triangles)
|
||||
{
|
||||
if (numCH >= m_nClusters)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_convexHulls[numCH].GetMesh().GetIFS(points, triangles);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HACD::Save(const char* fileName, bool uniColor, long numCluster) const
|
||||
{
|
||||
std::ofstream fout(fileName);
|
||||
if (fout.is_open())
|
||||
{
|
||||
if (m_callBack)
|
||||
{
|
||||
char msg[1024];
|
||||
sprintf(msg, "Saving %s\n", fileName);
|
||||
(*m_callBack)(msg, 0.0, 0.0, m_graph.GetNVertices());
|
||||
}
|
||||
Material mat;
|
||||
if (numCluster < 0)
|
||||
{
|
||||
for (size_t p = 0; p != m_nClusters; ++p)
|
||||
{
|
||||
if (!uniColor)
|
||||
{
|
||||
mat.m_diffuseColor.X() = mat.m_diffuseColor.Y() = mat.m_diffuseColor.Z() = 0.0;
|
||||
while (mat.m_diffuseColor.X() == mat.m_diffuseColor.Y() ||
|
||||
mat.m_diffuseColor.Z() == mat.m_diffuseColor.Y() ||
|
||||
mat.m_diffuseColor.Z() == mat.m_diffuseColor.X())
|
||||
{
|
||||
mat.m_diffuseColor.X() = (rand() % 100) / 100.0;
|
||||
mat.m_diffuseColor.Y() = (rand() % 100) / 100.0;
|
||||
mat.m_diffuseColor.Z() = (rand() % 100) / 100.0;
|
||||
}
|
||||
}
|
||||
m_convexHulls[p].GetMesh().SaveVRML2(fout, mat);
|
||||
}
|
||||
}
|
||||
else if (numCluster < static_cast<long>(m_cVertices.size()))
|
||||
{
|
||||
m_convexHulls[numCluster].GetMesh().SaveVRML2(fout, mat);
|
||||
}
|
||||
fout.close();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_callBack)
|
||||
{
|
||||
char msg[1024];
|
||||
sprintf(msg, "Error saving %s\n", fileName);
|
||||
(*m_callBack)(msg, 0.0, 0.0, m_graph.GetNVertices());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace HACD
|
||||
285
Engine/lib/bullet/Extras/HACD/hacdHACD.h
Normal file
285
Engine/lib/bullet/Extras/HACD/hacdHACD.h
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_HACD_H
|
||||
#define HACD_HACD_H
|
||||
#include "hacdVersion.h"
|
||||
#include "hacdVector.h"
|
||||
#include "hacdGraph.h"
|
||||
#include "hacdICHull.h"
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <functional>
|
||||
|
||||
namespace HACD
|
||||
{
|
||||
const double sc_pi = 3.14159265;
|
||||
class HACD;
|
||||
|
||||
// just to be able to set the capcity of the container
|
||||
|
||||
template <class _Ty, class _Container = std::vector<_Ty>, class _Pr = std::less<typename _Container::value_type> >
|
||||
class reservable_priority_queue : public std::priority_queue<_Ty, _Container, _Pr>
|
||||
{
|
||||
typedef typename std::priority_queue<_Ty, _Container, _Pr>::size_type size_type;
|
||||
|
||||
public:
|
||||
reservable_priority_queue(size_type capacity = 0) { reserve(capacity); };
|
||||
void reserve(size_type capacity) { this->c.reserve(capacity); }
|
||||
size_type capacity() const { return this->c.capacity(); }
|
||||
};
|
||||
|
||||
//! priority queque element
|
||||
class GraphEdgePriorityQueue
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
//! @param name edge's id
|
||||
//! @param priority edge's priority
|
||||
GraphEdgePriorityQueue(long name, Real priority)
|
||||
{
|
||||
m_name = name;
|
||||
m_priority = priority;
|
||||
}
|
||||
//! Destructor
|
||||
~GraphEdgePriorityQueue(void) {}
|
||||
|
||||
private:
|
||||
long m_name; //!< edge name
|
||||
Real m_priority; //!< priority
|
||||
//! Operator < for GraphEdgePQ
|
||||
friend bool operator<(const GraphEdgePriorityQueue &lhs, const GraphEdgePriorityQueue &rhs);
|
||||
//! Operator > for GraphEdgePQ
|
||||
friend bool operator>(const GraphEdgePriorityQueue &lhs, const GraphEdgePriorityQueue &rhs);
|
||||
friend class HACD;
|
||||
};
|
||||
inline bool operator<(const GraphEdgePriorityQueue &lhs, const GraphEdgePriorityQueue &rhs)
|
||||
{
|
||||
return lhs.m_priority < rhs.m_priority;
|
||||
}
|
||||
inline bool operator>(const GraphEdgePriorityQueue &lhs, const GraphEdgePriorityQueue &rhs)
|
||||
{
|
||||
return lhs.m_priority > rhs.m_priority;
|
||||
}
|
||||
typedef bool (*CallBackFunction)(const char *, double, double, size_t);
|
||||
|
||||
//! Provides an implementation of the Hierarchical Approximate Convex Decomposition (HACD) technique described in "A Simple and Efficient Approach for 3D Mesh Approximate Convex Decomposition" Game Programming Gems 8 - Chapter 2.8, p.202. A short version of the chapter was published in ICIP09 and is available at ftp://ftp.elet.polimi.it/users/Stefano.Tubaro/ICIP_USB_Proceedings_v2/pdfs/0003501.pdf
|
||||
class HACD
|
||||
{
|
||||
public:
|
||||
//! Gives the triangles partitionas an array of size m_nTriangles where the i-th element specifies the cluster to which belong the i-th triangle
|
||||
//! @return triangles partition
|
||||
const long *GetPartition() const { return m_partition; }
|
||||
//! Sets the scale factor
|
||||
//! @param scale scale factor
|
||||
void SetScaleFactor(double scale) { m_scale = scale; }
|
||||
//! Gives the scale factor
|
||||
//! @return scale factor
|
||||
double GetScaleFactor() const { return m_scale; }
|
||||
//! Sets the call-back function
|
||||
//! @param callBack pointer to the call-back function
|
||||
void SetCallBack(CallBackFunction callBack) { m_callBack = callBack; }
|
||||
//! Gives the call-back function
|
||||
//! @return pointer to the call-back function
|
||||
CallBackFunction GetCallBack() const { return m_callBack; }
|
||||
|
||||
//! Specifies whether faces points should be added when computing the concavity
|
||||
//! @param addFacesPoints true = faces points should be added
|
||||
void SetAddFacesPoints(bool addFacesPoints) { m_addFacesPoints = addFacesPoints; }
|
||||
//! Specifies wheter faces points should be added when computing the concavity
|
||||
//! @return true = faces points should be added
|
||||
bool GetAddFacesPoints() const { return m_addFacesPoints; }
|
||||
//! Specifies whether extra points should be added when computing the concavity
|
||||
//! @param addExteraDistPoints true = extra points should be added
|
||||
void SetAddExtraDistPoints(bool addExtraDistPoints) { m_addExtraDistPoints = addExtraDistPoints; }
|
||||
//! Specifies wheter extra points should be added when computing the concavity
|
||||
//! @return true = extra points should be added
|
||||
bool GetAddExtraDistPoints() const { return m_addExtraDistPoints; }
|
||||
//! Specifies whether extra points should be added when computing the concavity
|
||||
//! @param addExteraDistPoints true = extra points should be added
|
||||
void SetAddNeighboursDistPoints(bool addNeighboursDistPoints) { m_addNeighboursDistPoints = addNeighboursDistPoints; }
|
||||
//! Specifies wheter extra points should be added when computing the concavity
|
||||
//! @return true = extra points should be added
|
||||
bool GetAddNeighboursDistPoints() const { return m_addNeighboursDistPoints; }
|
||||
//! Sets the points of the input mesh (Remark: the input points will be scaled and shifted. Use DenormalizeData() to invert those operations)
|
||||
//! @param points pointer to the input points
|
||||
void SetPoints(Vec3<Real> *points) { m_points = points; }
|
||||
//! Gives the points of the input mesh (Remark: the input points will be scaled and shifted. Use DenormalizeData() to invert those operations)
|
||||
//! @return pointer to the input points
|
||||
const Vec3<Real> *GetPoints() const { return m_points; }
|
||||
//! Sets the triangles of the input mesh.
|
||||
//! @param triangles points pointer to the input points
|
||||
void SetTriangles(Vec3<long> *triangles) { m_triangles = triangles; }
|
||||
//! Gives the triangles in the input mesh
|
||||
//! @return pointer to the input triangles
|
||||
const Vec3<long> *GetTriangles() const { return m_triangles; }
|
||||
//! Sets the number of points in the input mesh.
|
||||
//! @param nPoints number of points the input mesh
|
||||
void SetNPoints(size_t nPoints) { m_nPoints = nPoints; }
|
||||
//! Gives the number of points in the input mesh.
|
||||
//! @return number of points the input mesh
|
||||
size_t GetNPoints() const { return m_nPoints; }
|
||||
//! Sets the number of triangles in the input mesh.
|
||||
//! @param nTriangles number of triangles in the input mesh
|
||||
void SetNTriangles(size_t nTriangles) { m_nTriangles = nTriangles; }
|
||||
//! Gives the number of triangles in the input mesh.
|
||||
//! @return number of triangles the input mesh
|
||||
size_t GetNTriangles() const { return m_nTriangles; }
|
||||
//! Sets the minimum number of clusters to be generated.
|
||||
//! @param nClusters minimum number of clusters
|
||||
void SetNClusters(size_t nClusters) { m_nMinClusters = nClusters; }
|
||||
//! Gives the number of generated clusters.
|
||||
//! @return number of generated clusters
|
||||
size_t GetNClusters() const { return m_nClusters; }
|
||||
//! Sets the maximum allowed concavity.
|
||||
//! @param concavity maximum concavity
|
||||
void SetConcavity(double concavity) { m_concavity = concavity; }
|
||||
//! Gives the maximum allowed concavity.
|
||||
//! @return maximum concavity
|
||||
double GetConcavity() const { return m_concavity; }
|
||||
//! Sets the maximum allowed distance to get CCs connected.
|
||||
//! @param concavity maximum distance to get CCs connected
|
||||
void SetConnectDist(double ccConnectDist) { m_ccConnectDist = ccConnectDist; }
|
||||
//! Gives the maximum allowed distance to get CCs connected.
|
||||
//! @return maximum distance to get CCs connected
|
||||
double GetConnectDist() const { return m_ccConnectDist; }
|
||||
//! Sets the volume weight.
|
||||
//! @param beta volume weight
|
||||
void SetVolumeWeight(double beta) { m_beta = beta; }
|
||||
//! Gives the volume weight.
|
||||
//! @return volume weight
|
||||
double GetVolumeWeight() const { return m_beta; }
|
||||
//! Sets the compacity weight (i.e. parameter alpha in ftp://ftp.elet.polimi.it/users/Stefano.Tubaro/ICIP_USB_Proceedings_v2/pdfs/0003501.pdf).
|
||||
//! @param alpha compacity weight
|
||||
void SetCompacityWeight(double alpha) { m_alpha = alpha; }
|
||||
//! Gives the compacity weight (i.e. parameter alpha in ftp://ftp.elet.polimi.it/users/Stefano.Tubaro/ICIP_USB_Proceedings_v2/pdfs/0003501.pdf).
|
||||
//! @return compacity weight
|
||||
double GetCompacityWeight() const { return m_alpha; }
|
||||
//! Sets the maximum number of vertices for each generated convex-hull.
|
||||
//! @param nVerticesPerCH maximum # vertices per CH
|
||||
void SetNVerticesPerCH(size_t nVerticesPerCH) { m_nVerticesPerCH = nVerticesPerCH; }
|
||||
//! Gives the maximum number of vertices for each generated convex-hull.
|
||||
//! @return maximum # vertices per CH
|
||||
size_t GetNVerticesPerCH() const { return m_nVerticesPerCH; }
|
||||
//! Gives the number of vertices for the cluster number numCH.
|
||||
//! @return number of vertices
|
||||
size_t GetNPointsCH(size_t numCH) const;
|
||||
//! Gives the number of triangles for the cluster number numCH.
|
||||
//! @param numCH cluster's number
|
||||
//! @return number of triangles
|
||||
size_t GetNTrianglesCH(size_t numCH) const;
|
||||
//! Gives the vertices and the triangles of the cluster number numCH.
|
||||
//! @param numCH cluster's number
|
||||
//! @param points pointer to the vector of points to be filled
|
||||
//! @param triangles pointer to the vector of triangles to be filled
|
||||
//! @return true if sucess
|
||||
bool GetCH(size_t numCH, Vec3<Real> *const points, Vec3<long> *const triangles);
|
||||
//! Computes the HACD decomposition.
|
||||
//! @param fullCH specifies whether to generate convex-hulls with a full or limited (i.e. < m_nVerticesPerCH) number of vertices
|
||||
//! @param exportDistPoints specifies wheter distance points should ne exported or not (used only for debugging).
|
||||
//! @return true if sucess
|
||||
bool Compute(bool fullCH = false, bool exportDistPoints = false);
|
||||
//! Saves the generated convex-hulls in a VRML 2.0 file.
|
||||
//! @param fileName the output file name
|
||||
//! @param uniColor specifies whether the different convex-hulls should have the same color or not
|
||||
//! @param numCluster specifies the cluster to be saved, if numCluster < 0 export all clusters
|
||||
//! @return true if sucess
|
||||
bool Save(const char *fileName, bool uniColor, long numCluster = -1) const;
|
||||
//! Shifts and scales to the data to have all the coordinates between 0.0 and 1000.0.
|
||||
void NormalizeData();
|
||||
//! Inverse the operations applied by NormalizeData().
|
||||
void DenormalizeData();
|
||||
//! Constructor.
|
||||
HACD(void);
|
||||
//! Destructor.
|
||||
~HACD(void);
|
||||
|
||||
private:
|
||||
//! Gives the edge index.
|
||||
//! @param a first vertex id
|
||||
//! @param b second vertex id
|
||||
//! @return edge's index
|
||||
static unsigned long long GetEdgeIndex(unsigned long long a, unsigned long long b)
|
||||
{
|
||||
if (a > b)
|
||||
return (a << 32) + b;
|
||||
else
|
||||
return (b << 32) + a;
|
||||
}
|
||||
//! Computes the concavity of a cluster.
|
||||
//! @param ch the cluster's convex-hull
|
||||
//! @param distPoints the cluster's points
|
||||
//! @return cluster's concavity
|
||||
double Concavity(ICHull &ch, std::map<long, DPoint> &distPoints);
|
||||
//! Computes the perimeter of a cluster.
|
||||
//! @param triIndices the cluster's triangles
|
||||
//! @param distPoints the cluster's points
|
||||
//! @return cluster's perimeter
|
||||
double ComputePerimeter(const std::vector<long> &triIndices) const;
|
||||
//! Creates the Graph by associating to each mesh triangle a vertex in the graph and to each couple of adjacent triangles an edge in the graph.
|
||||
void CreateGraph();
|
||||
//! Initializes the graph costs and computes the vertices normals
|
||||
void InitializeDualGraph();
|
||||
//! Computes the cost of an edge
|
||||
//! @param e edge's id
|
||||
void ComputeEdgeCost(size_t e);
|
||||
//! Initializes the priority queue
|
||||
//! @param fast specifies whether fast mode is used
|
||||
//! @return true if success
|
||||
bool InitializePriorityQueue();
|
||||
//! Cleans the intersection between convex-hulls
|
||||
void CleanClusters();
|
||||
//! Computes convex-hulls from partition information
|
||||
//! @param fullCH specifies whether to generate convex-hulls with a full or limited (i.e. < m_nVerticesPerCH) number of vertices
|
||||
void ComputeConvexHulls(bool fullCH);
|
||||
//! Simplifies the graph
|
||||
//! @param fast specifies whether fast mode is used
|
||||
void Simplify();
|
||||
|
||||
private:
|
||||
double m_scale; //>! scale factor used for NormalizeData() and DenormalizeData()
|
||||
Vec3<long> *m_triangles; //>! pointer the triangles array
|
||||
Vec3<Real> *m_points; //>! pointer the points array
|
||||
Vec3<Real> *m_facePoints; //>! pointer to the faces points array
|
||||
Vec3<Real> *m_faceNormals; //>! pointer to the faces normals array
|
||||
Vec3<Real> *m_normals; //>! pointer the normals array
|
||||
size_t m_nTriangles; //>! number of triangles in the original mesh
|
||||
size_t m_nPoints; //>! number of vertices in the original mesh
|
||||
size_t m_nClusters; //>! number of clusters
|
||||
size_t m_nMinClusters; //>! minimum number of clusters
|
||||
double m_ccConnectDist; //>! maximum allowed distance to connect CCs
|
||||
double m_concavity; //>! maximum concavity
|
||||
double m_alpha; //>! compacity weigth
|
||||
double m_beta; //>! volume weigth
|
||||
double m_diag; //>! length of the BB diagonal
|
||||
Vec3<Real> m_barycenter; //>! barycenter of the mesh
|
||||
std::vector<long> m_cVertices; //>! array of vertices each belonging to a different cluster
|
||||
ICHull *m_convexHulls; //>! convex-hulls associated with the final HACD clusters
|
||||
Graph m_graph; //>! simplification graph
|
||||
size_t m_nVerticesPerCH; //>! maximum number of vertices per convex-hull
|
||||
reservable_priority_queue<GraphEdgePriorityQueue,
|
||||
std::vector<GraphEdgePriorityQueue>,
|
||||
std::greater<std::vector<GraphEdgePriorityQueue>::value_type> >
|
||||
m_pqueue; //!> priority queue
|
||||
HACD(const HACD &rhs);
|
||||
CallBackFunction m_callBack; //>! call-back function
|
||||
long *m_partition; //>! array of size m_nTriangles where the i-th element specifies the cluster to which belong the i-th triangle
|
||||
bool m_addFacesPoints; //>! specifies whether to add faces points or not
|
||||
bool m_addExtraDistPoints; //>! specifies whether to add extra points for concave shapes or not
|
||||
bool m_addNeighboursDistPoints; //>! specifies whether to add extra points from adjacent clusters or not
|
||||
};
|
||||
} // namespace HACD
|
||||
#endif
|
||||
1020
Engine/lib/bullet/Extras/HACD/hacdICHull.cpp
Normal file
1020
Engine/lib/bullet/Extras/HACD/hacdICHull.cpp
Normal file
File diff suppressed because it is too large
Load diff
120
Engine/lib/bullet/Extras/HACD/hacdICHull.h
Normal file
120
Engine/lib/bullet/Extras/HACD/hacdICHull.h
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_ICHULL_H
|
||||
#define HACD_ICHULL_H
|
||||
#include "hacdVersion.h"
|
||||
#include "hacdManifoldMesh.h"
|
||||
#include "hacdVector.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
namespace HACD
|
||||
{
|
||||
class DPoint;
|
||||
class HACD;
|
||||
//! Incremental Convex Hull algorithm (cf. http://maven.smith.edu/~orourke/books/ftp.html ).
|
||||
enum ICHullError
|
||||
{
|
||||
ICHullErrorOK = 0,
|
||||
ICHullErrorCoplanarPoints,
|
||||
ICHullErrorNoVolume,
|
||||
ICHullErrorInconsistent,
|
||||
ICHullErrorNotEnoughPoints
|
||||
};
|
||||
class ICHull
|
||||
{
|
||||
public:
|
||||
//!
|
||||
bool IsFlat() { return m_isFlat; }
|
||||
//!
|
||||
std::map<long, DPoint> *GetDistPoints() const { return m_distPoints; }
|
||||
//!
|
||||
void SetDistPoints(std::map<long, DPoint> *distPoints) { m_distPoints = distPoints; }
|
||||
//! Returns the computed mesh
|
||||
TMMesh &GetMesh() { return m_mesh; }
|
||||
//! Add one point to the convex-hull
|
||||
bool AddPoint(const Vec3<Real> &point) { return AddPoints(&point, 1); }
|
||||
//! Add one point to the convex-hull
|
||||
bool AddPoint(const Vec3<Real> &point, long id);
|
||||
//! Add points to the convex-hull
|
||||
bool AddPoints(const Vec3<Real> *points, size_t nPoints);
|
||||
bool AddPoints(std::vector<Vec3<Real> > points);
|
||||
//!
|
||||
ICHullError Process();
|
||||
//!
|
||||
ICHullError Process(unsigned long nPointsCH);
|
||||
//!
|
||||
double ComputeVolume();
|
||||
//!
|
||||
bool IsInside(const Vec3<Real> &pt0);
|
||||
//!
|
||||
double ComputeDistance(long name, const Vec3<Real> &pt, const Vec3<Real> &normal, bool &insideHull, bool updateIncidentPoints);
|
||||
//!
|
||||
const ICHull &operator=(ICHull &rhs);
|
||||
|
||||
//! Constructor
|
||||
ICHull(void);
|
||||
//! Destructor
|
||||
virtual ~ICHull(void){};
|
||||
|
||||
private:
|
||||
//! 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.
|
||||
ICHullError DoubleTriangle();
|
||||
//! MakeFace creates a new face structure from three vertices (in ccw order). It returns a pointer to the face.
|
||||
CircularListElement<TMMTriangle> *MakeFace(CircularListElement<TMMVertex> *v0,
|
||||
CircularListElement<TMMVertex> *v1,
|
||||
CircularListElement<TMMVertex> *v2,
|
||||
CircularListElement<TMMTriangle> *fold);
|
||||
//!
|
||||
CircularListElement<TMMTriangle> *MakeConeFace(CircularListElement<TMMEdge> *e, CircularListElement<TMMVertex> *v);
|
||||
//!
|
||||
bool ProcessPoint();
|
||||
//!
|
||||
bool ComputePointVolume(double &totalVolume, bool markVisibleFaces);
|
||||
//!
|
||||
bool FindMaxVolumePoint();
|
||||
//!
|
||||
bool CleanEdges();
|
||||
//!
|
||||
bool CleanVertices(unsigned long &addedPoints);
|
||||
//!
|
||||
bool CleanTriangles();
|
||||
//!
|
||||
bool CleanUp(unsigned long &addedPoints);
|
||||
//!
|
||||
bool MakeCCW(CircularListElement<TMMTriangle> *f,
|
||||
CircularListElement<TMMEdge> *e,
|
||||
CircularListElement<TMMVertex> *v);
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
static const long sc_dummyIndex;
|
||||
static const double sc_distMin;
|
||||
TMMesh m_mesh;
|
||||
std::vector<CircularListElement<TMMEdge> *> m_edgesToDelete;
|
||||
std::vector<CircularListElement<TMMEdge> *> m_edgesToUpdate;
|
||||
std::vector<CircularListElement<TMMTriangle> *> m_trianglesToDelete;
|
||||
std::map<long, DPoint> *m_distPoints;
|
||||
CircularListElement<TMMVertex> *m_dummyVertex;
|
||||
Vec3<Real> m_normal;
|
||||
bool m_isFlat;
|
||||
|
||||
ICHull(const ICHull &rhs);
|
||||
|
||||
friend class HACD;
|
||||
};
|
||||
|
||||
} // namespace HACD
|
||||
#endif
|
||||
582
Engine/lib/bullet/Extras/HACD/hacdManifoldMesh.cpp
Normal file
582
Engine/lib/bullet/Extras/HACD/hacdManifoldMesh.cpp
Normal file
|
|
@ -0,0 +1,582 @@
|
|||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
*/
|
||||
#include "hacdManifoldMesh.h"
|
||||
using namespace std;
|
||||
|
||||
namespace HACD
|
||||
{
|
||||
Material::Material(void)
|
||||
{
|
||||
m_diffuseColor.X() = 0.5;
|
||||
m_diffuseColor.Y() = 0.5;
|
||||
m_diffuseColor.Z() = 0.5;
|
||||
m_specularColor.X() = 0.5;
|
||||
m_specularColor.Y() = 0.5;
|
||||
m_specularColor.Z() = 0.5;
|
||||
m_ambientIntensity = 0.4;
|
||||
m_emissiveColor.X() = 0.0;
|
||||
m_emissiveColor.Y() = 0.0;
|
||||
m_emissiveColor.Z() = 0.0;
|
||||
m_shininess = 0.4;
|
||||
m_transparency = 0.0;
|
||||
}
|
||||
|
||||
TMMVertex::TMMVertex(void)
|
||||
{
|
||||
m_name = 0;
|
||||
m_id = 0;
|
||||
m_duplicate = 0;
|
||||
m_onHull = false;
|
||||
m_tag = false;
|
||||
}
|
||||
TMMVertex::~TMMVertex(void)
|
||||
{
|
||||
}
|
||||
TMMEdge::TMMEdge(void)
|
||||
{
|
||||
m_id = 0;
|
||||
m_triangles[0] = m_triangles[1] = m_newFace = 0;
|
||||
m_vertices[0] = m_vertices[1] = 0;
|
||||
}
|
||||
TMMEdge::~TMMEdge(void)
|
||||
{
|
||||
}
|
||||
TMMTriangle::TMMTriangle(void)
|
||||
{
|
||||
m_id = 0;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
m_edges[i] = 0;
|
||||
m_vertices[0] = 0;
|
||||
}
|
||||
m_visible = false;
|
||||
}
|
||||
TMMTriangle::~TMMTriangle(void)
|
||||
{
|
||||
}
|
||||
TMMesh::TMMesh(void)
|
||||
{
|
||||
m_barycenter = Vec3<Real>(0, 0, 0);
|
||||
m_diag = 1;
|
||||
}
|
||||
TMMesh::~TMMesh(void)
|
||||
{
|
||||
}
|
||||
|
||||
void TMMesh::Print()
|
||||
{
|
||||
size_t nV = m_vertices.GetSize();
|
||||
std::cout << "-----------------------------" << std::endl;
|
||||
std::cout << "vertices (" << nV << ")" << std::endl;
|
||||
for (size_t v = 0; v < nV; v++)
|
||||
{
|
||||
const TMMVertex ¤tVertex = m_vertices.GetData();
|
||||
std::cout << currentVertex.m_id << ", "
|
||||
<< currentVertex.m_pos.X() << ", "
|
||||
<< currentVertex.m_pos.Y() << ", "
|
||||
<< currentVertex.m_pos.Z() << std::endl;
|
||||
m_vertices.Next();
|
||||
}
|
||||
|
||||
size_t nE = m_edges.GetSize();
|
||||
std::cout << "edges (" << nE << ")" << std::endl;
|
||||
for (size_t e = 0; e < nE; e++)
|
||||
{
|
||||
const TMMEdge ¤tEdge = m_edges.GetData();
|
||||
const CircularListElement<TMMVertex> *v0 = currentEdge.m_vertices[0];
|
||||
const CircularListElement<TMMVertex> *v1 = currentEdge.m_vertices[1];
|
||||
const CircularListElement<TMMTriangle> *f0 = currentEdge.m_triangles[0];
|
||||
const CircularListElement<TMMTriangle> *f1 = currentEdge.m_triangles[1];
|
||||
|
||||
std::cout << "-> (" << v0->GetData().m_name << ", " << v1->GetData().m_name << ")" << std::endl;
|
||||
std::cout << "-> F0 (" << f0->GetData().m_vertices[0]->GetData().m_name << ", "
|
||||
<< f0->GetData().m_vertices[1]->GetData().m_name << ", "
|
||||
<< f0->GetData().m_vertices[2]->GetData().m_name << ")" << std::endl;
|
||||
std::cout << "-> F1 (" << f1->GetData().m_vertices[0]->GetData().m_name << ", "
|
||||
<< f1->GetData().m_vertices[1]->GetData().m_name << ", "
|
||||
<< f1->GetData().m_vertices[2]->GetData().m_name << ")" << std::endl;
|
||||
m_edges.Next();
|
||||
}
|
||||
size_t nT = m_triangles.GetSize();
|
||||
std::cout << "triangles (" << nT << ")" << std::endl;
|
||||
for (size_t t = 0; t < nT; t++)
|
||||
{
|
||||
const TMMTriangle ¤tTriangle = m_triangles.GetData();
|
||||
const CircularListElement<TMMVertex> *v0 = currentTriangle.m_vertices[0];
|
||||
const CircularListElement<TMMVertex> *v1 = currentTriangle.m_vertices[1];
|
||||
const CircularListElement<TMMVertex> *v2 = currentTriangle.m_vertices[2];
|
||||
const CircularListElement<TMMEdge> *e0 = currentTriangle.m_edges[0];
|
||||
const CircularListElement<TMMEdge> *e1 = currentTriangle.m_edges[1];
|
||||
const CircularListElement<TMMEdge> *e2 = currentTriangle.m_edges[2];
|
||||
|
||||
std::cout << "-> (" << v0->GetData().m_name << ", " << v1->GetData().m_name << ", " << v2->GetData().m_name << ")" << std::endl;
|
||||
|
||||
std::cout << "-> E0 (" << e0->GetData().m_vertices[0]->GetData().m_name << ", "
|
||||
<< e0->GetData().m_vertices[1]->GetData().m_name << ")" << std::endl;
|
||||
std::cout << "-> E1 (" << e1->GetData().m_vertices[0]->GetData().m_name << ", "
|
||||
<< e1->GetData().m_vertices[1]->GetData().m_name << ")" << std::endl;
|
||||
std::cout << "-> E2 (" << e2->GetData().m_vertices[0]->GetData().m_name << ", "
|
||||
<< e2->GetData().m_vertices[1]->GetData().m_name << ")" << std::endl;
|
||||
m_triangles.Next();
|
||||
}
|
||||
}
|
||||
bool TMMesh::Save(const char *fileName)
|
||||
{
|
||||
std::ofstream fout(fileName);
|
||||
std::cout << "Saving " << fileName << std::endl;
|
||||
if (SaveVRML2(fout))
|
||||
{
|
||||
fout.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool TMMesh::SaveVRML2(std::ofstream &fout)
|
||||
{
|
||||
return SaveVRML2(fout, Material());
|
||||
}
|
||||
bool TMMesh::SaveVRML2(std::ofstream &fout, const Material &material)
|
||||
{
|
||||
if (fout.is_open())
|
||||
{
|
||||
size_t nV = m_vertices.GetSize();
|
||||
size_t nT = m_triangles.GetSize();
|
||||
fout << "#VRML V2.0 utf8" << std::endl;
|
||||
fout << "" << std::endl;
|
||||
fout << "# Vertices: " << nV << std::endl;
|
||||
fout << "# Triangles: " << nT << std::endl;
|
||||
fout << "" << std::endl;
|
||||
fout << "Group {" << std::endl;
|
||||
fout << " children [" << std::endl;
|
||||
fout << " Shape {" << std::endl;
|
||||
fout << " appearance Appearance {" << std::endl;
|
||||
fout << " material Material {" << std::endl;
|
||||
fout << " diffuseColor " << material.m_diffuseColor.X() << " "
|
||||
<< material.m_diffuseColor.Y() << " "
|
||||
<< material.m_diffuseColor.Z() << std::endl;
|
||||
fout << " ambientIntensity " << material.m_ambientIntensity << std::endl;
|
||||
fout << " specularColor " << material.m_specularColor.X() << " "
|
||||
<< material.m_specularColor.Y() << " "
|
||||
<< material.m_specularColor.Z() << std::endl;
|
||||
fout << " emissiveColor " << material.m_emissiveColor.X() << " "
|
||||
<< material.m_emissiveColor.Y() << " "
|
||||
<< material.m_emissiveColor.Z() << std::endl;
|
||||
fout << " shininess " << material.m_shininess << std::endl;
|
||||
fout << " transparency " << material.m_transparency << std::endl;
|
||||
fout << " }" << std::endl;
|
||||
fout << " }" << std::endl;
|
||||
fout << " geometry IndexedFaceSet {" << std::endl;
|
||||
fout << " ccw TRUE" << std::endl;
|
||||
fout << " solid TRUE" << std::endl;
|
||||
fout << " convex TRUE" << std::endl;
|
||||
if (GetNVertices() > 0)
|
||||
{
|
||||
fout << " coord DEF co Coordinate {" << std::endl;
|
||||
fout << " point [" << std::endl;
|
||||
for (size_t v = 0; v < nV; v++)
|
||||
{
|
||||
TMMVertex ¤tVertex = m_vertices.GetData();
|
||||
fout << " " << currentVertex.m_pos.X() << " "
|
||||
<< currentVertex.m_pos.Y() << " "
|
||||
<< currentVertex.m_pos.Z() << "," << std::endl;
|
||||
currentVertex.m_id = v;
|
||||
m_vertices.Next();
|
||||
}
|
||||
fout << " ]" << std::endl;
|
||||
fout << " }" << std::endl;
|
||||
}
|
||||
if (GetNTriangles() > 0)
|
||||
{
|
||||
fout << " coordIndex [ " << std::endl;
|
||||
for (size_t f = 0; f < nT; f++)
|
||||
{
|
||||
TMMTriangle ¤tTriangle = m_triangles.GetData();
|
||||
fout << " " << currentTriangle.m_vertices[0]->GetData().m_id << ", "
|
||||
<< currentTriangle.m_vertices[1]->GetData().m_id << ", "
|
||||
<< currentTriangle.m_vertices[2]->GetData().m_id << ", -1," << std::endl;
|
||||
m_triangles.Next();
|
||||
}
|
||||
fout << " ]" << std::endl;
|
||||
}
|
||||
fout << " }" << std::endl;
|
||||
fout << " }" << std::endl;
|
||||
fout << " ]" << std::endl;
|
||||
fout << "}" << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void TMMesh::GetIFS(Vec3<Real> *const points, Vec3<long> *const triangles)
|
||||
{
|
||||
size_t nV = m_vertices.GetSize();
|
||||
size_t nT = m_triangles.GetSize();
|
||||
|
||||
for (size_t v = 0; v < nV; v++)
|
||||
{
|
||||
points[v] = m_vertices.GetData().m_pos;
|
||||
m_vertices.GetData().m_id = v;
|
||||
m_vertices.Next();
|
||||
}
|
||||
for (size_t f = 0; f < nT; f++)
|
||||
{
|
||||
TMMTriangle ¤tTriangle = m_triangles.GetData();
|
||||
triangles[f].X() = static_cast<long>(currentTriangle.m_vertices[0]->GetData().m_id);
|
||||
triangles[f].Y() = static_cast<long>(currentTriangle.m_vertices[1]->GetData().m_id);
|
||||
triangles[f].Z() = static_cast<long>(currentTriangle.m_vertices[2]->GetData().m_id);
|
||||
m_triangles.Next();
|
||||
}
|
||||
}
|
||||
void TMMesh::Clear()
|
||||
{
|
||||
m_vertices.Clear();
|
||||
m_edges.Clear();
|
||||
m_triangles.Clear();
|
||||
}
|
||||
void TMMesh::Copy(TMMesh &mesh)
|
||||
{
|
||||
Clear();
|
||||
// updating the id's
|
||||
size_t nV = mesh.m_vertices.GetSize();
|
||||
size_t nE = mesh.m_edges.GetSize();
|
||||
size_t nT = mesh.m_triangles.GetSize();
|
||||
for (size_t v = 0; v < nV; v++)
|
||||
{
|
||||
mesh.m_vertices.GetData().m_id = v;
|
||||
mesh.m_vertices.Next();
|
||||
}
|
||||
for (size_t e = 0; e < nE; e++)
|
||||
{
|
||||
mesh.m_edges.GetData().m_id = e;
|
||||
mesh.m_edges.Next();
|
||||
}
|
||||
for (size_t f = 0; f < nT; f++)
|
||||
{
|
||||
mesh.m_triangles.GetData().m_id = f;
|
||||
mesh.m_triangles.Next();
|
||||
}
|
||||
// copying data
|
||||
m_vertices = mesh.m_vertices;
|
||||
m_edges = mesh.m_edges;
|
||||
m_triangles = mesh.m_triangles;
|
||||
|
||||
// generating mapping
|
||||
CircularListElement<TMMVertex> **vertexMap = new CircularListElement<TMMVertex> *[nV];
|
||||
CircularListElement<TMMEdge> **edgeMap = new CircularListElement<TMMEdge> *[nE];
|
||||
CircularListElement<TMMTriangle> **triangleMap = new CircularListElement<TMMTriangle> *[nT];
|
||||
for (size_t v = 0; v < nV; v++)
|
||||
{
|
||||
vertexMap[v] = m_vertices.GetHead();
|
||||
m_vertices.Next();
|
||||
}
|
||||
for (size_t e = 0; e < nE; e++)
|
||||
{
|
||||
edgeMap[e] = m_edges.GetHead();
|
||||
m_edges.Next();
|
||||
}
|
||||
for (size_t f = 0; f < nT; f++)
|
||||
{
|
||||
triangleMap[f] = m_triangles.GetHead();
|
||||
m_triangles.Next();
|
||||
}
|
||||
|
||||
// updating pointers
|
||||
for (size_t v = 0; v < nV; v++)
|
||||
{
|
||||
if (vertexMap[v]->GetData().m_duplicate)
|
||||
{
|
||||
vertexMap[v]->GetData().m_duplicate = edgeMap[vertexMap[v]->GetData().m_duplicate->GetData().m_id];
|
||||
}
|
||||
}
|
||||
for (size_t e = 0; e < nE; e++)
|
||||
{
|
||||
if (edgeMap[e]->GetData().m_newFace)
|
||||
{
|
||||
edgeMap[e]->GetData().m_newFace = triangleMap[edgeMap[e]->GetData().m_newFace->GetData().m_id];
|
||||
}
|
||||
if (nT > 0)
|
||||
{
|
||||
for (int f = 0; f < 2; f++)
|
||||
{
|
||||
if (edgeMap[e]->GetData().m_triangles[f])
|
||||
{
|
||||
edgeMap[e]->GetData().m_triangles[f] = triangleMap[edgeMap[e]->GetData().m_triangles[f]->GetData().m_id];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int v = 0; v < 2; v++)
|
||||
{
|
||||
if (edgeMap[e]->GetData().m_vertices[v])
|
||||
{
|
||||
edgeMap[e]->GetData().m_vertices[v] = vertexMap[edgeMap[e]->GetData().m_vertices[v]->GetData().m_id];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t f = 0; f < nT; f++)
|
||||
{
|
||||
if (nE > 0)
|
||||
{
|
||||
for (int e = 0; e < 3; e++)
|
||||
{
|
||||
if (triangleMap[f]->GetData().m_edges[e])
|
||||
{
|
||||
triangleMap[f]->GetData().m_edges[e] = edgeMap[triangleMap[f]->GetData().m_edges[e]->GetData().m_id];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int v = 0; v < 3; v++)
|
||||
{
|
||||
if (triangleMap[f]->GetData().m_vertices[v])
|
||||
{
|
||||
triangleMap[f]->GetData().m_vertices[v] = vertexMap[triangleMap[f]->GetData().m_vertices[v]->GetData().m_id];
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] vertexMap;
|
||||
delete[] edgeMap;
|
||||
delete[] triangleMap;
|
||||
}
|
||||
long IntersectRayTriangle(const Vec3<double> &P0, const Vec3<double> &dir,
|
||||
const Vec3<double> &V0, const Vec3<double> &V1,
|
||||
const Vec3<double> &V2, double &t)
|
||||
{
|
||||
Vec3<double> edge1, edge2, edge3;
|
||||
double det, invDet;
|
||||
edge1 = V1 - V2;
|
||||
edge2 = V2 - V0;
|
||||
Vec3<double> pvec = dir ^ edge2;
|
||||
det = edge1 * pvec;
|
||||
if (det == 0.0)
|
||||
return 0;
|
||||
invDet = 1.0 / det;
|
||||
Vec3<double> tvec = P0 - V0;
|
||||
Vec3<double> qvec = tvec ^ edge1;
|
||||
t = (edge2 * qvec) * invDet;
|
||||
if (t < 0.0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
edge3 = V0 - V1;
|
||||
Vec3<double> I(P0 + t * dir);
|
||||
Vec3<double> s0 = (I - V0) ^ edge3;
|
||||
Vec3<double> s1 = (I - V1) ^ edge1;
|
||||
Vec3<double> s2 = (I - V2) ^ edge2;
|
||||
if (s0 * s1 > -1e-9 && s2 * s1 > -1e-9)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool IntersectLineLine(const Vec3<double> &p1, const Vec3<double> &p2,
|
||||
const Vec3<double> &p3, const Vec3<double> &p4,
|
||||
Vec3<double> &pa, Vec3<double> &pb,
|
||||
double &mua, double &mub)
|
||||
{
|
||||
Vec3<double> p13, p43, p21;
|
||||
double d1343, d4321, d1321, d4343, d2121;
|
||||
double numer, denom;
|
||||
|
||||
p13.X() = p1.X() - p3.X();
|
||||
p13.Y() = p1.Y() - p3.Y();
|
||||
p13.Z() = p1.Z() - p3.Z();
|
||||
p43.X() = p4.X() - p3.X();
|
||||
p43.Y() = p4.Y() - p3.Y();
|
||||
p43.Z() = p4.Z() - p3.Z();
|
||||
if (p43.X() == 0.0 && p43.Y() == 0.0 && p43.Z() == 0.0)
|
||||
return false;
|
||||
p21.X() = p2.X() - p1.X();
|
||||
p21.Y() = p2.Y() - p1.Y();
|
||||
p21.Z() = p2.Z() - p1.Z();
|
||||
if (p21.X() == 0.0 && p21.Y() == 0.0 && p21.Z() == 0.0)
|
||||
return false;
|
||||
|
||||
d1343 = p13.X() * p43.X() + p13.Y() * p43.Y() + p13.Z() * p43.Z();
|
||||
d4321 = p43.X() * p21.X() + p43.Y() * p21.Y() + p43.Z() * p21.Z();
|
||||
d1321 = p13.X() * p21.X() + p13.Y() * p21.Y() + p13.Z() * p21.Z();
|
||||
d4343 = p43.X() * p43.X() + p43.Y() * p43.Y() + p43.Z() * p43.Z();
|
||||
d2121 = p21.X() * p21.X() + p21.Y() * p21.Y() + p21.Z() * p21.Z();
|
||||
|
||||
denom = d2121 * d4343 - d4321 * d4321;
|
||||
if (denom == 0.0)
|
||||
return false;
|
||||
numer = d1343 * d4321 - d1321 * d4343;
|
||||
|
||||
mua = numer / denom;
|
||||
mub = (d1343 + d4321 * (mua)) / d4343;
|
||||
|
||||
pa.X() = p1.X() + mua * p21.X();
|
||||
pa.Y() = p1.Y() + mua * p21.Y();
|
||||
pa.Z() = p1.Z() + mua * p21.Z();
|
||||
pb.X() = p3.X() + mub * p43.X();
|
||||
pb.Y() = p3.Y() + mub * p43.Y();
|
||||
pb.Z() = p3.Z() + mub * p43.Z();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
long IntersectRayTriangle2(const Vec3<double> &P0, const Vec3<double> &dir,
|
||||
const Vec3<double> &V0, const Vec3<double> &V1,
|
||||
const Vec3<double> &V2, double &r)
|
||||
{
|
||||
Vec3<double> u, v, n; // triangle vectors
|
||||
Vec3<double> w0, w; // ray vectors
|
||||
double a, b; // params to calc ray-plane intersect
|
||||
|
||||
// get triangle edge vectors and plane normal
|
||||
u = V1 - V0;
|
||||
v = V2 - V0;
|
||||
n = u ^ v; // cross product
|
||||
if (n.GetNorm() == 0.0) // triangle is degenerate
|
||||
return -1; // do not deal with this case
|
||||
|
||||
w0 = P0 - V0;
|
||||
a = -n * w0;
|
||||
b = n * dir;
|
||||
if (fabs(b) <= 0.0)
|
||||
{ // ray is parallel to triangle plane
|
||||
if (a == 0.0) // ray lies in triangle plane
|
||||
return 2;
|
||||
else
|
||||
return 0; // ray disjoint from plane
|
||||
}
|
||||
|
||||
// get intersect point of ray with triangle plane
|
||||
r = a / b;
|
||||
if (r < 0.0) // ray goes away from triangle
|
||||
return 0; // => no intersect
|
||||
// for a segment, also test if (r > 1.0) => no intersect
|
||||
|
||||
Vec3<double> I = P0 + r * dir; // intersect point of ray and plane
|
||||
|
||||
// is I inside T?
|
||||
double uu, uv, vv, wu, wv, D;
|
||||
uu = u * u;
|
||||
uv = u * v;
|
||||
vv = v * v;
|
||||
w = I - V0;
|
||||
wu = w * u;
|
||||
wv = w * v;
|
||||
D = uv * uv - uu * vv;
|
||||
|
||||
// get and test parametric coords
|
||||
double s, t;
|
||||
s = (uv * wv - vv * wu) / D;
|
||||
if (s < 0.0 || s > 1.0) // I is outside T
|
||||
return 0;
|
||||
t = (uv * wu - uu * wv) / D;
|
||||
if (t < 0.0 || (s + t) > 1.0) // I is outside T
|
||||
return 0;
|
||||
return 1; // I is in T
|
||||
}
|
||||
|
||||
bool TMMesh::CheckConsistancy()
|
||||
{
|
||||
size_t nE = m_edges.GetSize();
|
||||
size_t nT = m_triangles.GetSize();
|
||||
for (size_t e = 0; e < nE; e++)
|
||||
{
|
||||
for (int f = 0; f < 2; f++)
|
||||
{
|
||||
if (!m_edges.GetHead()->GetData().m_triangles[f])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_edges.Next();
|
||||
}
|
||||
|
||||
for (size_t f = 0; f < nT; f++)
|
||||
{
|
||||
for (int e = 0; e < 3; e++)
|
||||
{
|
||||
int found = 0;
|
||||
for (int k = 0; k < 2; k++)
|
||||
{
|
||||
if (m_triangles.GetHead()->GetData().m_edges[e]->GetData().m_triangles[k] == m_triangles.GetHead())
|
||||
{
|
||||
found++;
|
||||
}
|
||||
}
|
||||
if (found != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_triangles.Next();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool TMMesh::Normalize()
|
||||
{
|
||||
size_t nV = m_vertices.GetSize();
|
||||
if (nV == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_barycenter = m_vertices.GetHead()->GetData().m_pos;
|
||||
Vec3<Real> min = m_barycenter;
|
||||
Vec3<Real> max = m_barycenter;
|
||||
Real x, y, z;
|
||||
for (size_t v = 1; v < nV; v++)
|
||||
{
|
||||
m_barycenter += m_vertices.GetHead()->GetData().m_pos;
|
||||
x = m_vertices.GetHead()->GetData().m_pos.X();
|
||||
y = m_vertices.GetHead()->GetData().m_pos.Y();
|
||||
z = m_vertices.GetHead()->GetData().m_pos.Z();
|
||||
if (x < min.X())
|
||||
min.X() = x;
|
||||
else if (x > max.X())
|
||||
max.X() = x;
|
||||
if (y < min.Y())
|
||||
min.Y() = y;
|
||||
else if (y > max.Y())
|
||||
max.Y() = y;
|
||||
if (z < min.Z())
|
||||
min.Z() = z;
|
||||
else if (z > max.Z())
|
||||
max.Z() = z;
|
||||
m_vertices.Next();
|
||||
}
|
||||
m_barycenter /= static_cast<Real>(nV);
|
||||
m_diag = static_cast<Real>(0.001 * (max - min).GetNorm());
|
||||
const Real invDiag = static_cast<Real>(1.0 / m_diag);
|
||||
if (m_diag != 0.0)
|
||||
{
|
||||
for (size_t v = 0; v < nV; v++)
|
||||
{
|
||||
m_vertices.GetHead()->GetData().m_pos = (m_vertices.GetHead()->GetData().m_pos - m_barycenter) * invDiag;
|
||||
m_vertices.Next();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool TMMesh::Denormalize()
|
||||
{
|
||||
size_t nV = m_vertices.GetSize();
|
||||
if (nV == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (m_diag != 0.0)
|
||||
{
|
||||
for (size_t v = 0; v < nV; v++)
|
||||
{
|
||||
m_vertices.GetHead()->GetData().m_pos = m_vertices.GetHead()->GetData().m_pos * m_diag + m_barycenter;
|
||||
m_vertices.Next();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace HACD
|
||||
251
Engine/lib/bullet/Extras/HACD/hacdManifoldMesh.h
Normal file
251
Engine/lib/bullet/Extras/HACD/hacdManifoldMesh.h
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_MANIFOLD_MESH_H
|
||||
#define HACD_MANIFOLD_MESH_H
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "hacdVersion.h"
|
||||
#include "hacdCircularList.h"
|
||||
#include "hacdVector.h"
|
||||
#include <set>
|
||||
namespace HACD
|
||||
{
|
||||
class TMMTriangle;
|
||||
class TMMEdge;
|
||||
class TMMesh;
|
||||
class ICHull;
|
||||
class HACD;
|
||||
|
||||
class DPoint
|
||||
{
|
||||
public:
|
||||
DPoint(Real dist = 0, bool computed = false, bool distOnly = false)
|
||||
: m_dist(dist),
|
||||
m_computed(computed),
|
||||
m_distOnly(distOnly){};
|
||||
~DPoint(){};
|
||||
|
||||
private:
|
||||
Real m_dist;
|
||||
bool m_computed;
|
||||
bool m_distOnly;
|
||||
friend class TMMTriangle;
|
||||
friend class TMMesh;
|
||||
friend class GraphVertex;
|
||||
friend class GraphEdge;
|
||||
friend class Graph;
|
||||
friend class ICHull;
|
||||
friend class HACD;
|
||||
};
|
||||
|
||||
//! Vertex data structure used in a triangular manifold mesh (TMM).
|
||||
class TMMVertex
|
||||
{
|
||||
public:
|
||||
TMMVertex(void);
|
||||
~TMMVertex(void);
|
||||
|
||||
private:
|
||||
Vec3<Real> m_pos;
|
||||
long m_name;
|
||||
size_t m_id;
|
||||
CircularListElement<TMMEdge> *m_duplicate; // pointer to incident cone edge (or NULL)
|
||||
bool m_onHull;
|
||||
bool m_tag;
|
||||
TMMVertex(const TMMVertex &rhs);
|
||||
|
||||
friend class HACD;
|
||||
friend class ICHull;
|
||||
friend class TMMesh;
|
||||
friend class TMMTriangle;
|
||||
friend class TMMEdge;
|
||||
};
|
||||
|
||||
//! Edge data structure used in a triangular manifold mesh (TMM).
|
||||
class TMMEdge
|
||||
{
|
||||
public:
|
||||
TMMEdge(void);
|
||||
~TMMEdge(void);
|
||||
|
||||
private:
|
||||
size_t m_id;
|
||||
CircularListElement<TMMTriangle> *m_triangles[2];
|
||||
CircularListElement<TMMVertex> *m_vertices[2];
|
||||
CircularListElement<TMMTriangle> *m_newFace;
|
||||
|
||||
TMMEdge(const TMMEdge &rhs);
|
||||
|
||||
friend class HACD;
|
||||
friend class ICHull;
|
||||
friend class TMMTriangle;
|
||||
friend class TMMVertex;
|
||||
friend class TMMesh;
|
||||
};
|
||||
|
||||
//! Triangle data structure used in a triangular manifold mesh (TMM).
|
||||
class TMMTriangle
|
||||
{
|
||||
public:
|
||||
TMMTriangle(void);
|
||||
~TMMTriangle(void);
|
||||
|
||||
private:
|
||||
size_t m_id;
|
||||
CircularListElement<TMMEdge> *m_edges[3];
|
||||
CircularListElement<TMMVertex> *m_vertices[3];
|
||||
std::set<long> m_incidentPoints;
|
||||
bool m_visible;
|
||||
|
||||
TMMTriangle(const TMMTriangle &rhs);
|
||||
|
||||
friend class HACD;
|
||||
friend class ICHull;
|
||||
friend class TMMesh;
|
||||
friend class TMMVertex;
|
||||
friend class TMMEdge;
|
||||
};
|
||||
|
||||
class Material
|
||||
{
|
||||
public:
|
||||
Material(void);
|
||||
~Material(void) {}
|
||||
// private:
|
||||
Vec3<double> m_diffuseColor;
|
||||
double m_ambientIntensity;
|
||||
Vec3<double> m_specularColor;
|
||||
Vec3<double> m_emissiveColor;
|
||||
double m_shininess;
|
||||
double m_transparency;
|
||||
|
||||
friend class TMMesh;
|
||||
friend class HACD;
|
||||
};
|
||||
|
||||
//! triangular manifold mesh data structure.
|
||||
class TMMesh
|
||||
{
|
||||
public:
|
||||
//! Returns the number of vertices>
|
||||
inline size_t GetNVertices() const { return m_vertices.GetSize(); }
|
||||
//! Returns the number of edges
|
||||
inline size_t GetNEdges() const { return m_edges.GetSize(); }
|
||||
//! Returns the number of triangles
|
||||
inline size_t GetNTriangles() const { return m_triangles.GetSize(); }
|
||||
//! Returns the vertices circular list
|
||||
inline const CircularList<TMMVertex> &GetVertices() const { return m_vertices; }
|
||||
//! Returns the edges circular list
|
||||
inline const CircularList<TMMEdge> &GetEdges() const { return m_edges; }
|
||||
//! Returns the triangles circular list
|
||||
inline const CircularList<TMMTriangle> &GetTriangles() const { return m_triangles; }
|
||||
//! Returns the vertices circular list
|
||||
inline CircularList<TMMVertex> &GetVertices() { return m_vertices; }
|
||||
//! Returns the edges circular list
|
||||
inline CircularList<TMMEdge> &GetEdges() { return m_edges; }
|
||||
//! Returns the triangles circular list
|
||||
inline CircularList<TMMTriangle> &GetTriangles() { return m_triangles; }
|
||||
//! Add vertex to the mesh
|
||||
CircularListElement<TMMVertex> *AddVertex() { return m_vertices.Add(); }
|
||||
//! Add vertex to the mesh
|
||||
CircularListElement<TMMEdge> *AddEdge() { return m_edges.Add(); }
|
||||
//! Add vertex to the mesh
|
||||
CircularListElement<TMMTriangle> *AddTriangle() { return m_triangles.Add(); }
|
||||
//! Print mesh information
|
||||
void Print();
|
||||
//!
|
||||
void GetIFS(Vec3<Real> *const points, Vec3<long> *const triangles);
|
||||
//! Save mesh
|
||||
bool Save(const char *fileName);
|
||||
//! Save mesh to VRML 2.0 format
|
||||
bool SaveVRML2(std::ofstream &fout);
|
||||
//! Save mesh to VRML 2.0 format
|
||||
bool SaveVRML2(std::ofstream &fout, const Material &material);
|
||||
//!
|
||||
void Clear();
|
||||
//!
|
||||
void Copy(TMMesh &mesh);
|
||||
//!
|
||||
bool CheckConsistancy();
|
||||
//!
|
||||
bool Normalize();
|
||||
//!
|
||||
bool Denormalize();
|
||||
//! Constructor
|
||||
TMMesh(void);
|
||||
//! Destructor
|
||||
virtual ~TMMesh(void);
|
||||
|
||||
private:
|
||||
CircularList<TMMVertex> m_vertices;
|
||||
CircularList<TMMEdge> m_edges;
|
||||
CircularList<TMMTriangle> m_triangles;
|
||||
Real m_diag; //>! length of the BB diagonal
|
||||
Vec3<Real> m_barycenter; //>! barycenter of the mesh
|
||||
|
||||
// not defined
|
||||
TMMesh(const TMMesh &rhs);
|
||||
friend class ICHull;
|
||||
friend class HACD;
|
||||
};
|
||||
//! IntersectRayTriangle(): intersect a ray with a 3D triangle
|
||||
//! Input: a ray R, and a triangle T
|
||||
//! Output: *I = intersection point (when it exists)
|
||||
//! 0 = disjoint (no intersect)
|
||||
//! 1 = intersect in unique point I1
|
||||
long IntersectRayTriangle(const Vec3<double> &P0, const Vec3<double> &dir,
|
||||
const Vec3<double> &V0, const Vec3<double> &V1,
|
||||
const Vec3<double> &V2, double &t);
|
||||
|
||||
// intersect_RayTriangle(): intersect a ray with a 3D triangle
|
||||
// Input: a ray R, and a triangle T
|
||||
// Output: *I = intersection point (when it exists)
|
||||
// Return: -1 = triangle is degenerate (a segment or point)
|
||||
// 0 = disjoint (no intersect)
|
||||
// 1 = intersect in unique point I1
|
||||
// 2 = are in the same plane
|
||||
long IntersectRayTriangle2(const Vec3<double> &P0, const Vec3<double> &dir,
|
||||
const Vec3<double> &V0, const Vec3<double> &V1,
|
||||
const Vec3<double> &V2, double &r);
|
||||
|
||||
/*
|
||||
Calculate the line segment PaPb that is the shortest route between
|
||||
two lines P1P2 and P3P4. Calculate also the values of mua and mub where
|
||||
Pa = P1 + mua (P2 - P1)
|
||||
Pb = P3 + mub (P4 - P3)
|
||||
Return FALSE if no solution exists.
|
||||
*/
|
||||
bool IntersectLineLine(const Vec3<double> &p1, const Vec3<double> &p2,
|
||||
const Vec3<double> &p3, const Vec3<double> &p4,
|
||||
Vec3<double> &pa, Vec3<double> &pb,
|
||||
double &mua, double &mub);
|
||||
} // namespace HACD
|
||||
#endif
|
||||
68
Engine/lib/bullet/Extras/HACD/hacdVector.h
Normal file
68
Engine/lib/bullet/Extras/HACD/hacdVector.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_VECTOR_H
|
||||
#define HACD_VECTOR_H
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include "hacdVersion.h"
|
||||
|
||||
namespace HACD
|
||||
{
|
||||
typedef double Real;
|
||||
//! Vector dim 3.
|
||||
template <typename T>
|
||||
class Vec3
|
||||
{
|
||||
public:
|
||||
T& X();
|
||||
T& Y();
|
||||
T& Z();
|
||||
const T& X() const;
|
||||
const T& Y() const;
|
||||
const T& Z() const;
|
||||
void Normalize();
|
||||
T GetNorm() const;
|
||||
void operator=(const Vec3& rhs);
|
||||
void operator+=(const Vec3& rhs);
|
||||
void operator-=(const Vec3& rhs);
|
||||
void operator-=(T a);
|
||||
void operator+=(T a);
|
||||
void operator/=(T a);
|
||||
void operator*=(T a);
|
||||
Vec3 operator^(const Vec3& rhs) const;
|
||||
T operator*(const Vec3& rhs) const;
|
||||
Vec3 operator+(const Vec3& rhs) const;
|
||||
Vec3 operator-(const Vec3& rhs) const;
|
||||
Vec3 operator-() const;
|
||||
Vec3 operator*(T rhs) const;
|
||||
Vec3 operator/(T rhs) const;
|
||||
Vec3();
|
||||
Vec3(T a);
|
||||
Vec3(T x, T y, T z);
|
||||
Vec3(const Vec3& rhs);
|
||||
/*virtual*/ ~Vec3(void);
|
||||
|
||||
private:
|
||||
T m_data[3];
|
||||
};
|
||||
template <typename T>
|
||||
bool Colinear(const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c);
|
||||
template <typename T>
|
||||
const T Volume(const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c, const Vec3<T>& d);
|
||||
|
||||
} // namespace HACD
|
||||
#include "hacdVector.inl" // template implementation
|
||||
#endif
|
||||
178
Engine/lib/bullet/Extras/HACD/hacdVector.inl
Normal file
178
Engine/lib/bullet/Extras/HACD/hacdVector.inl
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
#pragma once
|
||||
#ifndef HACD_VECTOR_INL
|
||||
#define HACD_VECTOR_INL
|
||||
namespace HACD
|
||||
{
|
||||
template <typename T>
|
||||
inline Vec3<T> operator*(T lhs, const Vec3<T> & rhs)
|
||||
{
|
||||
return Vec3<T>(lhs * rhs.X(), lhs * rhs.Y(), lhs * rhs.Z());
|
||||
}
|
||||
template <typename T>
|
||||
inline T & Vec3<T>::X()
|
||||
{
|
||||
return m_data[0];
|
||||
}
|
||||
template <typename T>
|
||||
inline T & Vec3<T>::Y()
|
||||
{
|
||||
return m_data[1];
|
||||
}
|
||||
template <typename T>
|
||||
inline T & Vec3<T>::Z()
|
||||
{
|
||||
return m_data[2];
|
||||
}
|
||||
template <typename T>
|
||||
inline const T & Vec3<T>::X() const
|
||||
{
|
||||
return m_data[0];
|
||||
}
|
||||
template <typename T>
|
||||
inline const T & Vec3<T>::Y() const
|
||||
{
|
||||
return m_data[1];
|
||||
}
|
||||
template <typename T>
|
||||
inline const T & Vec3<T>::Z() const
|
||||
{
|
||||
return m_data[2];
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::Normalize()
|
||||
{
|
||||
T n = sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]+m_data[2]*m_data[2]);
|
||||
if (n != 0.0) (*this) /= n;
|
||||
}
|
||||
template <typename T>
|
||||
inline T Vec3<T>::GetNorm() const
|
||||
{
|
||||
return sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]+m_data[2]*m_data[2]);
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator= (const Vec3 & rhs)
|
||||
{
|
||||
this->m_data[0] = rhs.m_data[0];
|
||||
this->m_data[1] = rhs.m_data[1];
|
||||
this->m_data[2] = rhs.m_data[2];
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator+=(const Vec3 & rhs)
|
||||
{
|
||||
this->m_data[0] += rhs.m_data[0];
|
||||
this->m_data[1] += rhs.m_data[1];
|
||||
this->m_data[2] += rhs.m_data[2];
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator-=(const Vec3 & rhs)
|
||||
{
|
||||
this->m_data[0] -= rhs.m_data[0];
|
||||
this->m_data[1] -= rhs.m_data[1];
|
||||
this->m_data[2] -= rhs.m_data[2];
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator-=(T a)
|
||||
{
|
||||
this->m_data[0] -= a;
|
||||
this->m_data[1] -= a;
|
||||
this->m_data[2] -= a;
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator+=(T a)
|
||||
{
|
||||
this->m_data[0] += a;
|
||||
this->m_data[1] += a;
|
||||
this->m_data[2] += a;
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator/=(T a)
|
||||
{
|
||||
this->m_data[0] /= a;
|
||||
this->m_data[1] /= a;
|
||||
this->m_data[2] /= a;
|
||||
}
|
||||
template <typename T>
|
||||
inline void Vec3<T>::operator*=(T a)
|
||||
{
|
||||
this->m_data[0] *= a;
|
||||
this->m_data[1] *= a;
|
||||
this->m_data[2] *= a;
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T> Vec3<T>::operator^ (const Vec3<T> & rhs) const
|
||||
{
|
||||
return Vec3<T>(m_data[1] * rhs.m_data[2] - m_data[2] * rhs.m_data[1],
|
||||
m_data[2] * rhs.m_data[0] - m_data[0] * rhs.m_data[2],
|
||||
m_data[0] * rhs.m_data[1] - m_data[1] * rhs.m_data[0]);
|
||||
}
|
||||
template <typename T>
|
||||
inline T Vec3<T>::operator*(const Vec3<T> & rhs) const
|
||||
{
|
||||
return (m_data[0] * rhs.m_data[0] + m_data[1] * rhs.m_data[1] + m_data[2] * rhs.m_data[2]);
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T> Vec3<T>::operator+(const Vec3<T> & rhs) const
|
||||
{
|
||||
return Vec3<T>(m_data[0] + rhs.m_data[0],m_data[1] + rhs.m_data[1],m_data[2] + rhs.m_data[2]);
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T> Vec3<T>::operator-(const Vec3<T> & rhs) const
|
||||
{
|
||||
return Vec3<T>(m_data[0] - rhs.m_data[0],m_data[1] - rhs.m_data[1],m_data[2] - rhs.m_data[2]) ;
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T> Vec3<T>::operator-() const
|
||||
{
|
||||
return Vec3<T>(-m_data[0],-m_data[1],-m_data[2]) ;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Vec3<T> Vec3<T>::operator*(T rhs) const
|
||||
{
|
||||
return Vec3<T>(rhs * this->m_data[0], rhs * this->m_data[1], rhs * this->m_data[2]);
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T> Vec3<T>::operator/ (T rhs) const
|
||||
{
|
||||
return Vec3<T>(m_data[0] / rhs, m_data[1] / rhs, m_data[2] / rhs);
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T>::Vec3(T a)
|
||||
{
|
||||
m_data[0] = m_data[1] = m_data[2] = a;
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T>::Vec3(T x, T y, T z)
|
||||
{
|
||||
m_data[0] = x;
|
||||
m_data[1] = y;
|
||||
m_data[2] = z;
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T>::Vec3(const Vec3 & rhs)
|
||||
{
|
||||
m_data[0] = rhs.m_data[0];
|
||||
m_data[1] = rhs.m_data[1];
|
||||
m_data[2] = rhs.m_data[2];
|
||||
}
|
||||
template <typename T>
|
||||
inline Vec3<T>::~Vec3(void){};
|
||||
|
||||
template <typename T>
|
||||
inline Vec3<T>::Vec3() {}
|
||||
|
||||
template<typename T>
|
||||
inline bool Colinear(const Vec3<T> & a, const Vec3<T> & b, const Vec3<T> & c)
|
||||
{
|
||||
return ((c.Z() - a.Z()) * (b.Y() - a.Y()) - (b.Z() - a.Z()) * (c.Y() - a.Y()) == 0.0 /*EPS*/) &&
|
||||
((b.Z() - a.Z()) * (c.X() - a.X()) - (b.X() - a.X()) * (c.Z() - a.Z()) == 0.0 /*EPS*/) &&
|
||||
((b.X() - a.X()) * (c.Y() - a.Y()) - (b.Y() - a.Y()) * (c.X() - a.X()) == 0.0 /*EPS*/);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline const T Volume(const Vec3<T> & a, const Vec3<T> & b, const Vec3<T> & c, const Vec3<T> & d)
|
||||
{
|
||||
return (a-d) * ((b-d) ^ (c-d));
|
||||
}
|
||||
}
|
||||
#endif //HACD_VECTOR_INL
|
||||
20
Engine/lib/bullet/Extras/HACD/hacdVersion.h
Normal file
20
Engine/lib/bullet/Extras/HACD/hacdVersion.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
|
||||
All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
|
||||
3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
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.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef HACD_VERSION_H
|
||||
#define HACD_VERSION_H
|
||||
#define HACD_VERSION_MAJOR 0
|
||||
#define HACD_VERSION_MINOR 0
|
||||
#endif
|
||||
12
Engine/lib/bullet/Extras/HACD/premake4.lua
Normal file
12
Engine/lib/bullet/Extras/HACD/premake4.lua
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
project "HACD"
|
||||
|
||||
kind "StaticLib"
|
||||
|
||||
includedirs {"."}
|
||||
if os.is("Linux") then
|
||||
buildoptions{"-fPIC"}
|
||||
end
|
||||
files {
|
||||
"**.cpp",
|
||||
"**.h"
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef BULLET_INVERSE_DYNAMICS_UTILS_COMMON_H
|
||||
#define BULLET_INVERSE_DYNAMICS_UTILS_COMMON_H
|
||||
#include "CoilCreator.hpp"
|
||||
#include "MultiBodyTreeCreator.hpp"
|
||||
#include "btMultiBodyFromURDF.hpp"
|
||||
#include "DillCreator.hpp"
|
||||
#include "MultiBodyTreeDebugGraph.hpp"
|
||||
#include "btMultiBodyTreeCreator.hpp"
|
||||
#include "IDRandomUtil.hpp"
|
||||
#include "SimpleTreeCreator.hpp"
|
||||
#include "invdyn_bullet_comparison.hpp"
|
||||
#include "MultiBodyNameMap.hpp"
|
||||
#include "User2InternalIndex.hpp"
|
||||
|
||||
#endif //BULLET_INVERSE_DYNAMICS_UTILS_COMMON_H
|
||||
50
Engine/lib/bullet/Extras/InverseDynamics/CMakeLists.txt
Normal file
50
Engine/lib/bullet/Extras/InverseDynamics/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
ADD_LIBRARY(
|
||||
BulletInverseDynamicsUtils
|
||||
CloneTreeCreator.cpp
|
||||
CoilCreator.cpp
|
||||
MultiBodyTreeCreator.cpp
|
||||
btMultiBodyTreeCreator.cpp
|
||||
DillCreator.cpp
|
||||
MultiBodyTreeDebugGraph.cpp
|
||||
invdyn_bullet_comparison.cpp
|
||||
IDRandomUtil.cpp
|
||||
RandomTreeCreator.cpp
|
||||
SimpleTreeCreator.cpp
|
||||
MultiBodyNameMap.cpp
|
||||
User2InternalIndex.cpp
|
||||
)
|
||||
|
||||
SET_TARGET_PROPERTIES(BulletInverseDynamicsUtils PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(BulletInverseDynamicsUtils PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
TARGET_LINK_LIBRARIES(BulletInverseDynamicsUtils BulletInverseDynamics BulletDynamics BulletCollision Bullet3Common LinearMath)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
IF (INSTALL_EXTRA_LIBS)
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
#FILES_MATCHING requires CMake 2.6
|
||||
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS BulletInverseDynamicsUtils DESTINATION .)
|
||||
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS BulletInverseDynamicsUtils
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib${LIB_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LIB_SUFFIX})
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
|
||||
".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(BulletInverseDynamicsUtils PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(BulletInverseDynamicsUtils PROPERTIES PUBLIC_HEADER "BulletInverseDynamicsUtilsCommon.h" )
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ENDIF (INSTALL_EXTRA_LIBS)
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#include "CloneTreeCreator.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
#define CHECK_NULLPTR() \
|
||||
do \
|
||||
{ \
|
||||
if (m_reference == 0x0) \
|
||||
{ \
|
||||
bt_id_error_message("m_reference == 0x0\n"); \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TRY(x) \
|
||||
do \
|
||||
{ \
|
||||
if (x == -1) \
|
||||
{ \
|
||||
bt_id_error_message("error calling " #x "\n"); \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
CloneTreeCreator::CloneTreeCreator(const MultiBodyTree* reference)
|
||||
{
|
||||
m_reference = reference;
|
||||
}
|
||||
|
||||
CloneTreeCreator::~CloneTreeCreator() {}
|
||||
|
||||
int CloneTreeCreator::getNumBodies(int* num_bodies) const
|
||||
{
|
||||
CHECK_NULLPTR();
|
||||
*num_bodies = m_reference->numBodies();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CloneTreeCreator::getBody(const int body_index, int* parent_index, JointType* joint_type,
|
||||
vec3* parent_r_parent_body_ref, mat33* body_T_parent_ref,
|
||||
vec3* body_axis_of_motion, idScalar* mass, vec3* body_r_body_com,
|
||||
mat33* body_I_body, int* user_int, void** user_ptr) const
|
||||
{
|
||||
CHECK_NULLPTR();
|
||||
TRY(m_reference->getParentIndex(body_index, parent_index));
|
||||
TRY(m_reference->getJointType(body_index, joint_type));
|
||||
TRY(m_reference->getParentRParentBodyRef(body_index, parent_r_parent_body_ref));
|
||||
TRY(m_reference->getBodyTParentRef(body_index, body_T_parent_ref));
|
||||
TRY(m_reference->getBodyAxisOfMotion(body_index, body_axis_of_motion));
|
||||
TRY(m_reference->getBodyMass(body_index, mass));
|
||||
TRY(m_reference->getBodyFirstMassMoment(body_index, body_r_body_com));
|
||||
TRY(m_reference->getBodySecondMassMoment(body_index, body_I_body));
|
||||
TRY(m_reference->getUserInt(body_index, user_int));
|
||||
TRY(m_reference->getUserPtr(body_index, user_ptr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace btInverseDynamics
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef CLONETREE_CREATOR_HPP_
|
||||
#define CLONETREE_CREATOR_HPP_
|
||||
|
||||
#include "BulletInverseDynamics/IDConfig.hpp"
|
||||
#include "MultiBodyTreeCreator.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
/// Generate an identical multibody tree from a reference system.
|
||||
class CloneTreeCreator : public MultiBodyTreeCreator
|
||||
{
|
||||
public:
|
||||
/// ctor
|
||||
/// @param reference the MultiBodyTree to clone
|
||||
CloneTreeCreator(const MultiBodyTree* reference);
|
||||
~CloneTreeCreator();
|
||||
///\copydoc MultiBodyTreeCreator::getNumBodies
|
||||
int getNumBodies(int* num_bodies) const;
|
||||
///\copydoc MultiBodyTreeCreator::getBody
|
||||
int getBody(const int body_index, int* parent_index, JointType* joint_type,
|
||||
vec3* parent_r_parent_body_ref, mat33* body_T_parent_ref, vec3* body_axis_of_motion,
|
||||
idScalar* mass, vec3* body_r_body_com, mat33* body_I_body, int* user_int,
|
||||
void** user_ptr) const;
|
||||
|
||||
private:
|
||||
const MultiBodyTree* m_reference;
|
||||
};
|
||||
} // namespace btInverseDynamics
|
||||
#endif // CLONETREE_CREATOR_HPP_
|
||||
73
Engine/lib/bullet/Extras/InverseDynamics/CoilCreator.cpp
Normal file
73
Engine/lib/bullet/Extras/InverseDynamics/CoilCreator.cpp
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#include <cmath>
|
||||
|
||||
#include "CoilCreator.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
CoilCreator::CoilCreator(int n) : m_num_bodies(n), m_parent(n)
|
||||
{
|
||||
for (int i = 0; i < m_num_bodies; i++)
|
||||
{
|
||||
m_parent[i] = i - 1;
|
||||
}
|
||||
|
||||
// DH parameters (that's what's in the paper ...)
|
||||
const idScalar theta_DH = 0;
|
||||
const idScalar d_DH = 0.0;
|
||||
const idScalar a_DH = 1.0 / m_num_bodies;
|
||||
const idScalar alpha_DH = 5.0 * BT_ID_PI / m_num_bodies;
|
||||
getVecMatFromDH(theta_DH, d_DH, a_DH, alpha_DH, &m_parent_r_parent_body_ref,
|
||||
&m_body_T_parent_ref);
|
||||
// always z-axis
|
||||
m_body_axis_of_motion(0) = 0.0;
|
||||
m_body_axis_of_motion(1) = 0.0;
|
||||
m_body_axis_of_motion(2) = 1.0;
|
||||
|
||||
m_mass = 1.0 / m_num_bodies;
|
||||
m_body_r_body_com(0) = 1.0 / (2.0 * m_num_bodies);
|
||||
m_body_r_body_com(1) = 0.0;
|
||||
m_body_r_body_com(2) = 0.0;
|
||||
|
||||
m_body_I_body(0, 0) = 1e-4 / (2.0 * m_num_bodies);
|
||||
m_body_I_body(0, 1) = 0.0;
|
||||
m_body_I_body(0, 2) = 0.0;
|
||||
m_body_I_body(1, 0) = 0.0;
|
||||
m_body_I_body(1, 1) = (3e-4 + 4.0 / BT_ID_POW(m_num_bodies, 2)) / (12.0 * m_num_bodies);
|
||||
m_body_I_body(1, 2) = 0.0;
|
||||
m_body_I_body(2, 0) = 0.0;
|
||||
m_body_I_body(2, 1) = 0.0;
|
||||
m_body_I_body(2, 2) = m_body_I_body(1, 1);
|
||||
}
|
||||
|
||||
CoilCreator::~CoilCreator() {}
|
||||
|
||||
int CoilCreator::getNumBodies(int* num_bodies) const
|
||||
{
|
||||
*num_bodies = m_num_bodies;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CoilCreator::getBody(int body_index, int* parent_index, JointType* joint_type,
|
||||
vec3* parent_r_parent_body_ref, mat33* body_T_parent_ref,
|
||||
vec3* body_axis_of_motion, idScalar* mass, vec3* body_r_body_com,
|
||||
mat33* body_I_body, int* user_int, void** user_ptr) const
|
||||
{
|
||||
if (body_index < 0 || body_index >= m_num_bodies)
|
||||
{
|
||||
bt_id_error_message("invalid body index %d\n", body_index);
|
||||
return -1;
|
||||
}
|
||||
*parent_index = m_parent[body_index];
|
||||
*joint_type = REVOLUTE;
|
||||
*parent_r_parent_body_ref = m_parent_r_parent_body_ref;
|
||||
*body_T_parent_ref = m_body_T_parent_ref;
|
||||
*body_axis_of_motion = m_body_axis_of_motion;
|
||||
*mass = m_mass;
|
||||
*body_r_body_com = m_body_r_body_com;
|
||||
*body_I_body = m_body_I_body;
|
||||
|
||||
*user_int = 0;
|
||||
*user_ptr = 0;
|
||||
return 0;
|
||||
}
|
||||
} // namespace btInverseDynamics
|
||||
41
Engine/lib/bullet/Extras/InverseDynamics/CoilCreator.hpp
Normal file
41
Engine/lib/bullet/Extras/InverseDynamics/CoilCreator.hpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef COILCREATOR_HPP_
|
||||
#define COILCREATOR_HPP_
|
||||
|
||||
#include "MultiBodyTreeCreator.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
/// Creator class for building a "coil" system as intruduced as benchmark example in
|
||||
/// Featherstone (1999), "A Divide-and-Conquer Articulated-Body Algorithm for Parallel O(log(n))
|
||||
/// Calculation of Rigid-Body Dynamics. Part 2: Trees, Loops, and Accuracy.", The International
|
||||
/// Journal of Robotics Research 18 (9): 876–892. doi : 10.1177 / 02783649922066628.
|
||||
///
|
||||
/// This is a serial chain, with an initial configuration resembling a coil.
|
||||
class CoilCreator : public MultiBodyTreeCreator
|
||||
{
|
||||
public:
|
||||
/// ctor.
|
||||
/// @param n the number of bodies in the system
|
||||
CoilCreator(int n);
|
||||
/// dtor
|
||||
~CoilCreator();
|
||||
// \copydoc MultiBodyTreeCreator::getNumBodies
|
||||
int getNumBodies(int* num_bodies) const;
|
||||
// \copydoc MultiBodyTreeCreator::getBody
|
||||
int getBody(const int body_index, int* parent_index, JointType* joint_type,
|
||||
vec3* parent_r_parent_body_ref, mat33* body_T_parent_ref, vec3* body_axis_of_motion,
|
||||
idScalar* mass, vec3* body_r_body_com, mat33* body_I_body, int* user_int,
|
||||
void** user_ptr) const;
|
||||
|
||||
private:
|
||||
int m_num_bodies;
|
||||
std::vector<int> m_parent;
|
||||
vec3 m_parent_r_parent_body_ref;
|
||||
mat33 m_body_T_parent_ref;
|
||||
vec3 m_body_axis_of_motion;
|
||||
idScalar m_mass;
|
||||
vec3 m_body_r_body_com;
|
||||
mat33 m_body_I_body;
|
||||
};
|
||||
} // namespace btInverseDynamics
|
||||
#endif
|
||||
136
Engine/lib/bullet/Extras/InverseDynamics/DillCreator.cpp
Normal file
136
Engine/lib/bullet/Extras/InverseDynamics/DillCreator.cpp
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
#include "DillCreator.hpp"
|
||||
#include <cmath>
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
DillCreator::DillCreator(int level)
|
||||
: m_level(level),
|
||||
m_num_bodies(BT_ID_POW(2, level))
|
||||
{
|
||||
m_parent.resize(m_num_bodies);
|
||||
m_parent_r_parent_body_ref.resize(m_num_bodies);
|
||||
m_body_T_parent_ref.resize(m_num_bodies);
|
||||
m_body_axis_of_motion.resize(m_num_bodies);
|
||||
m_mass.resize(m_num_bodies);
|
||||
m_body_r_body_com.resize(m_num_bodies);
|
||||
m_body_I_body.resize(m_num_bodies);
|
||||
|
||||
// generate names (for debugging)
|
||||
for (int i = 0; i < m_num_bodies; i++)
|
||||
{
|
||||
m_parent[i] = i - 1;
|
||||
|
||||
// all z-axis (DH convention)
|
||||
m_body_axis_of_motion[i](0) = 0.0;
|
||||
m_body_axis_of_motion[i](1) = 0.0;
|
||||
m_body_axis_of_motion[i](2) = 1.0;
|
||||
}
|
||||
|
||||
// recursively build data structures
|
||||
m_current_body = 0;
|
||||
const int parent = -1;
|
||||
const idScalar d_DH = 0.0;
|
||||
const idScalar a_DH = 0.0;
|
||||
const idScalar alpha_DH = 0.0;
|
||||
|
||||
if (-1 == recurseDill(m_level, parent, d_DH, a_DH, alpha_DH))
|
||||
{
|
||||
bt_id_error_message("recurseDill failed\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
DillCreator::~DillCreator() {}
|
||||
|
||||
int DillCreator::getNumBodies(int* num_bodies) const
|
||||
{
|
||||
*num_bodies = m_num_bodies;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DillCreator::getBody(const int body_index, int* parent_index, JointType* joint_type,
|
||||
vec3* parent_r_parent_body_ref, mat33* body_T_parent_ref,
|
||||
vec3* body_axis_of_motion, idScalar* mass, vec3* body_r_body_com,
|
||||
mat33* body_I_body, int* user_int, void** user_ptr) const
|
||||
{
|
||||
if (body_index < 0 || body_index >= m_num_bodies)
|
||||
{
|
||||
bt_id_error_message("invalid body index %d\n", body_index);
|
||||
return -1;
|
||||
}
|
||||
*parent_index = m_parent[body_index];
|
||||
*joint_type = REVOLUTE;
|
||||
*parent_r_parent_body_ref = m_parent_r_parent_body_ref[body_index];
|
||||
*body_T_parent_ref = m_body_T_parent_ref[body_index];
|
||||
*body_axis_of_motion = m_body_axis_of_motion[body_index];
|
||||
*mass = m_mass[body_index];
|
||||
*body_r_body_com = m_body_r_body_com[body_index];
|
||||
*body_I_body = m_body_I_body[body_index];
|
||||
|
||||
*user_int = 0;
|
||||
*user_ptr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DillCreator::recurseDill(const int level, const int parent, const idScalar d_DH_in,
|
||||
const idScalar a_DH_in, const idScalar alpha_DH_in)
|
||||
{
|
||||
if (level < 0)
|
||||
{
|
||||
bt_id_error_message("invalid level parameter (%d)\n", level);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (m_current_body >= m_num_bodies || m_current_body < 0)
|
||||
{
|
||||
bt_id_error_message("invalid body parameter (%d, num_bodies: %d)\n", m_current_body,
|
||||
m_num_bodies);
|
||||
return -1;
|
||||
}
|
||||
|
||||
idScalar size = BT_ID_MAX(level, 1);
|
||||
const int body = m_current_body;
|
||||
// length = 0.1 * size;
|
||||
// with = 2 * 0.01 * size;
|
||||
|
||||
/// these parameters are from the paper ...
|
||||
/// TODO: add proper citation
|
||||
m_parent[body] = parent;
|
||||
m_mass[body] = 0.1 * BT_ID_POW(size, 3);
|
||||
m_body_r_body_com[body](0) = 0.05 * size;
|
||||
m_body_r_body_com[body](1) = 0;
|
||||
m_body_r_body_com[body](2) = 0;
|
||||
// initialization
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
m_parent_r_parent_body_ref[body](i) = 0;
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
m_body_I_body[body](i, j) = 0.0;
|
||||
m_body_T_parent_ref[body](i, j) = 0.0;
|
||||
}
|
||||
}
|
||||
const idScalar size_5 = std::pow(size, 5);
|
||||
m_body_I_body[body](0, 0) = size_5 / 0.2e6;
|
||||
m_body_I_body[body](1, 1) = size_5 * 403 / 1.2e6;
|
||||
m_body_I_body[body](2, 2) = m_body_I_body[body](1, 1);
|
||||
|
||||
getVecMatFromDH(0, 0, a_DH_in, alpha_DH_in, &m_parent_r_parent_body_ref[body],
|
||||
&m_body_T_parent_ref[body]);
|
||||
|
||||
// attach "level" Dill systems of levels 1...level
|
||||
for (int i = 1; i <= level; i++)
|
||||
{
|
||||
idScalar d_DH = 0.01 * size;
|
||||
if (i == level)
|
||||
{
|
||||
d_DH = 0.0;
|
||||
}
|
||||
const idScalar a_DH = i * 0.1;
|
||||
const idScalar alpha_DH = i * BT_ID_PI / 3.0;
|
||||
m_current_body++;
|
||||
recurseDill(i - 1, body, d_DH, a_DH, alpha_DH);
|
||||
}
|
||||
|
||||
return 0; // ok!
|
||||
}
|
||||
} // namespace btInverseDynamics
|
||||
47
Engine/lib/bullet/Extras/InverseDynamics/DillCreator.hpp
Normal file
47
Engine/lib/bullet/Extras/InverseDynamics/DillCreator.hpp
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef DILLCREATOR_HPP_
|
||||
#define DILLCREATOR_HPP_
|
||||
|
||||
#include "MultiBodyTreeCreator.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
/// Creator class for building a "Dill" system as intruduced as benchmark example in
|
||||
/// Featherstone (1999), "A Divide-and-Conquer Articulated-Body Algorithm for Parallel O(log(n))
|
||||
/// Calculation of Rigid-Body Dynamics. Part 2: Trees, Loops, and Accuracy.", The International
|
||||
/// Journal of Robotics Research 18 (9): 876–892. doi : 10.1177 / 02783649922066628.
|
||||
///
|
||||
/// This is a self-similar branched tree, somewhat resembling a dill plant
|
||||
class DillCreator : public MultiBodyTreeCreator
|
||||
{
|
||||
public:
|
||||
/// ctor
|
||||
/// @param levels the number of dill levels
|
||||
DillCreator(int levels);
|
||||
/// dtor
|
||||
~DillCreator();
|
||||
///\copydoc MultiBodyTreeCreator::getNumBodies
|
||||
int getNumBodies(int* num_bodies) const;
|
||||
///\copydoc MultiBodyTreeCreator::getBody
|
||||
int getBody(const int body_index, int* parent_index, JointType* joint_type,
|
||||
vec3* parent_r_parent_body_ref, mat33* body_T_parent_ref, vec3* body_axis_of_motion,
|
||||
idScalar* mass, vec3* body_r_body_com, mat33* body_I_body, int* user_int,
|
||||
void** user_ptr) const;
|
||||
|
||||
private:
|
||||
/// recursively generate dill bodies.
|
||||
/// TODO better documentation
|
||||
int recurseDill(const int levels, const int parent, const idScalar d_DH_in,
|
||||
const idScalar a_DH_in, const idScalar alpha_DH_in);
|
||||
int m_level;
|
||||
int m_num_bodies;
|
||||
idArray<int>::type m_parent;
|
||||
idArray<vec3>::type m_parent_r_parent_body_ref;
|
||||
idArray<mat33>::type m_body_T_parent_ref;
|
||||
idArray<vec3>::type m_body_axis_of_motion;
|
||||
idArray<idScalar>::type m_mass;
|
||||
idArray<vec3>::type m_body_r_body_com;
|
||||
idArray<mat33>::type m_body_I_body;
|
||||
int m_current_body;
|
||||
};
|
||||
} // namespace btInverseDynamics
|
||||
#endif
|
||||
76
Engine/lib/bullet/Extras/InverseDynamics/IDRandomUtil.cpp
Normal file
76
Engine/lib/bullet/Extras/InverseDynamics/IDRandomUtil.cpp
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
#include "BulletInverseDynamics/IDConfig.hpp"
|
||||
#include "BulletInverseDynamics/IDMath.hpp"
|
||||
#include "IDRandomUtil.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
// constants for random mass and inertia generation
|
||||
// these are arbitrary positive values.
|
||||
static const float mass_min = 0.001;
|
||||
static const float mass_max = 1.0;
|
||||
|
||||
void randomInit() { srand(time(NULL)); }
|
||||
void randomInit(unsigned seed) { srand(seed); }
|
||||
|
||||
int randomInt(int low, int high) { return rand() % (high + 1 - low) + low; }
|
||||
|
||||
float randomFloat(float low, float high)
|
||||
{
|
||||
return low + static_cast<float>(rand()) / RAND_MAX * (high - low);
|
||||
}
|
||||
|
||||
float randomMass() { return randomFloat(mass_min, mass_max); }
|
||||
|
||||
vec3 randomInertiaPrincipal()
|
||||
{
|
||||
vec3 inertia;
|
||||
do
|
||||
{
|
||||
inertia(0) = randomFloat(mass_min, mass_max);
|
||||
inertia(1) = randomFloat(mass_min, mass_max);
|
||||
inertia(2) = randomFloat(mass_min, mass_max);
|
||||
} while (inertia(0) + inertia(1) < inertia(2) || inertia(0) + inertia(2) < inertia(1) ||
|
||||
inertia(1) + inertia(2) < inertia(0));
|
||||
return inertia;
|
||||
}
|
||||
|
||||
mat33 randomInertiaMatrix()
|
||||
{
|
||||
// generate random valid inertia matrix by first getting valid components
|
||||
// along major axes and then rotating by random amount
|
||||
vec3 principal = randomInertiaPrincipal();
|
||||
mat33 rot(transformX(randomFloat(-BT_ID_PI, BT_ID_PI)) * transformY(randomFloat(-BT_ID_PI, BT_ID_PI)) *
|
||||
transformZ(randomFloat(-BT_ID_PI, BT_ID_PI)));
|
||||
mat33 inertia;
|
||||
inertia(0, 0) = principal(0);
|
||||
inertia(0, 1) = 0;
|
||||
inertia(0, 2) = 0;
|
||||
inertia(1, 0) = 0;
|
||||
inertia(1, 1) = principal(1);
|
||||
inertia(1, 2) = 0;
|
||||
inertia(2, 0) = 0;
|
||||
inertia(2, 1) = 0;
|
||||
inertia(2, 2) = principal(2);
|
||||
return rot * inertia * rot.transpose();
|
||||
}
|
||||
|
||||
vec3 randomAxis()
|
||||
{
|
||||
vec3 axis;
|
||||
idScalar length;
|
||||
do
|
||||
{
|
||||
axis(0) = randomFloat(-1.0, 1.0);
|
||||
axis(1) = randomFloat(-1.0, 1.0);
|
||||
axis(2) = randomFloat(-1.0, 1.0);
|
||||
|
||||
length = BT_ID_SQRT(BT_ID_POW(axis(0), 2) + BT_ID_POW(axis(1), 2) + BT_ID_POW(axis(2), 2));
|
||||
} while (length < 0.01);
|
||||
|
||||
return axis / length;
|
||||
}
|
||||
} // namespace btInverseDynamics
|
||||
37
Engine/lib/bullet/Extras/InverseDynamics/IDRandomUtil.hpp
Normal file
37
Engine/lib/bullet/Extras/InverseDynamics/IDRandomUtil.hpp
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef ID_RANDOM_UTIL_HPP_
|
||||
#define ID_RANDOM_UTIL_HPP_
|
||||
#include "BulletInverseDynamics/IDConfig.hpp"
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
/// seed random number generator using time()
|
||||
void randomInit();
|
||||
/// seed random number generator with identical value to get repeatable results
|
||||
void randomInit(unsigned seed);
|
||||
/// Generate (not quite) uniformly distributed random integers in [low, high]
|
||||
/// Note: this is a low-quality implementation using only rand(), as
|
||||
/// C++11 <random> is not supported in bullet.
|
||||
/// The results will *not* be perfectly uniform.
|
||||
/// \param low is the lower bound (inclusive)
|
||||
/// \param high is the lower bound (inclusive)
|
||||
/// \return a random number within [\param low, \param high]
|
||||
int randomInt(int low, int high);
|
||||
/// Generate a (not quite) uniformly distributed random floats in [low, high]
|
||||
/// Note: this is a low-quality implementation using only rand(), as
|
||||
/// C++11 <random> is not supported in bullet.
|
||||
/// The results will *not* be perfectly uniform.
|
||||
/// \param low is the lower bound (inclusive)
|
||||
/// \param high is the lower bound (inclusive)
|
||||
/// \return a random number within [\param low, \param high]
|
||||
float randomFloat(float low, float high);
|
||||
|
||||
/// generate a random valid mass value
|
||||
/// \returns random mass
|
||||
float randomMass();
|
||||
/// generate a random valid vector of principal moments of inertia
|
||||
vec3 randomInertiaPrincipal();
|
||||
/// generate a random valid moment of inertia matrix
|
||||
mat33 randomInertiaMatrix();
|
||||
/// generate a random unit vector
|
||||
vec3 randomAxis();
|
||||
} // namespace btInverseDynamics
|
||||
#endif
|
||||
12
Engine/lib/bullet/Extras/InverseDynamics/LICENSE.txt
Normal file
12
Engine/lib/bullet/Extras/InverseDynamics/LICENSE.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
Bullet Continuous Collision Detection and Physics Library
|
||||
http://bulletphysics.org
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
#include "MultiBodyNameMap.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
MultiBodyNameMap::MultiBodyNameMap() {}
|
||||
|
||||
int MultiBodyNameMap::addBody(const int index, const std::string& name)
|
||||
{
|
||||
if (m_index_to_body_name.count(index) > 0)
|
||||
{
|
||||
bt_id_error_message("trying to add index %d again\n", index);
|
||||
return -1;
|
||||
}
|
||||
if (m_body_name_to_index.count(name) > 0)
|
||||
{
|
||||
bt_id_error_message("trying to add name %s again\n", name.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_index_to_body_name[index] = name;
|
||||
m_body_name_to_index[name] = index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MultiBodyNameMap::addJoint(const int index, const std::string& name)
|
||||
{
|
||||
if (m_index_to_joint_name.count(index) > 0)
|
||||
{
|
||||
bt_id_error_message("trying to add index %d again\n", index);
|
||||
return -1;
|
||||
}
|
||||
if (m_joint_name_to_index.count(name) > 0)
|
||||
{
|
||||
bt_id_error_message("trying to add name %s again\n", name.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_index_to_joint_name[index] = name;
|
||||
m_joint_name_to_index[name] = index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MultiBodyNameMap::getBodyName(const int index, std::string* name) const
|
||||
{
|
||||
std::map<int, std::string>::const_iterator it = m_index_to_body_name.find(index);
|
||||
if (it == m_index_to_body_name.end())
|
||||
{
|
||||
bt_id_error_message("index %d not known\n", index);
|
||||
return -1;
|
||||
}
|
||||
*name = it->second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MultiBodyNameMap::getJointName(const int index, std::string* name) const
|
||||
{
|
||||
std::map<int, std::string>::const_iterator it = m_index_to_joint_name.find(index);
|
||||
if (it == m_index_to_joint_name.end())
|
||||
{
|
||||
bt_id_error_message("index %d not known\n", index);
|
||||
return -1;
|
||||
}
|
||||
*name = it->second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MultiBodyNameMap::getBodyIndex(const std::string& name, int* index) const
|
||||
{
|
||||
std::map<std::string, int>::const_iterator it = m_body_name_to_index.find(name);
|
||||
if (it == m_body_name_to_index.end())
|
||||
{
|
||||
bt_id_error_message("name %s not known\n", name.c_str());
|
||||
return -1;
|
||||
}
|
||||
*index = it->second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MultiBodyNameMap::getJointIndex(const std::string& name, int* index) const
|
||||
{
|
||||
std::map<std::string, int>::const_iterator it = m_joint_name_to_index.find(name);
|
||||
if (it == m_joint_name_to_index.end())
|
||||
{
|
||||
bt_id_error_message("name %s not known\n", name.c_str());
|
||||
return -1;
|
||||
}
|
||||
*index = it->second;
|
||||
return 0;
|
||||
}
|
||||
} // namespace btInverseDynamics
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef MULTIBODYNAMEMAP_HPP_
|
||||
#define MULTIBODYNAMEMAP_HPP_
|
||||
|
||||
#include "BulletInverseDynamics/IDConfig.hpp"
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
/// \brief The MultiBodyNameMap class
|
||||
/// Utility class that stores a maps from body/joint indices to/from body and joint names
|
||||
class MultiBodyNameMap
|
||||
{
|
||||
public:
|
||||
MultiBodyNameMap();
|
||||
/// add a body to the map
|
||||
/// @param index of the body
|
||||
/// @param name name of the body
|
||||
/// @return 0 on success, -1 on failure
|
||||
int addBody(const int index, const std::string& name);
|
||||
/// add a joint to the map
|
||||
/// @param index of the joint
|
||||
/// @param name name of the joint
|
||||
/// @return 0 on success, -1 on failure
|
||||
int addJoint(const int index, const std::string& name);
|
||||
/// get body name from index
|
||||
/// @param index of the body
|
||||
/// @param body_name name of the body
|
||||
/// @return 0 on success, -1 on failure
|
||||
int getBodyName(const int index, std::string* name) const;
|
||||
/// get joint name from index
|
||||
/// @param index of the joint
|
||||
/// @param joint_name name of the joint
|
||||
/// @return 0 on success, -1 on failure
|
||||
int getJointName(const int index, std::string* name) const;
|
||||
/// get body index from name
|
||||
/// @param index of the body
|
||||
/// @param name name of the body
|
||||
/// @return 0 on success, -1 on failure
|
||||
int getBodyIndex(const std::string& name, int* index) const;
|
||||
/// get joint index from name
|
||||
/// @param index of the joint
|
||||
/// @param name name of the joint
|
||||
/// @return 0 on success, -1 on failure
|
||||
int getJointIndex(const std::string& name, int* index) const;
|
||||
|
||||
private:
|
||||
std::map<int, std::string> m_index_to_joint_name;
|
||||
std::map<int, std::string> m_index_to_body_name;
|
||||
|
||||
std::map<std::string, int> m_joint_name_to_index;
|
||||
std::map<std::string, int> m_body_name_to_index;
|
||||
};
|
||||
} // namespace btInverseDynamics
|
||||
#endif // MULTIBODYNAMEMAP_HPP_
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
#include "MultiBodyTreeCreator.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
MultiBodyTree* CreateMultiBodyTree(const MultiBodyTreeCreator& creator)
|
||||
{
|
||||
int num_bodies;
|
||||
int parent_index;
|
||||
JointType joint_type;
|
||||
vec3 body_r_parent_body_ref;
|
||||
mat33 body_R_parent_ref;
|
||||
vec3 body_axis_of_motion;
|
||||
idScalar mass;
|
||||
vec3 body_r_body_com;
|
||||
mat33 body_I_body;
|
||||
int user_int;
|
||||
void* user_ptr;
|
||||
|
||||
MultiBodyTree* tree = new MultiBodyTree();
|
||||
if (0x0 == tree)
|
||||
{
|
||||
bt_id_error_message("cannot allocate tree\n");
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
// TODO: move to some policy argument
|
||||
tree->setAcceptInvalidMassParameters(false);
|
||||
|
||||
// get number of bodies in the system
|
||||
if (-1 == creator.getNumBodies(&num_bodies))
|
||||
{
|
||||
bt_id_error_message("getting body indices\n");
|
||||
delete tree;
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
// get data for all bodies
|
||||
for (int index = 0; index < num_bodies; index++)
|
||||
{
|
||||
// get body parameters from user callbacks
|
||||
if (-1 ==
|
||||
creator.getBody(index, &parent_index, &joint_type, &body_r_parent_body_ref,
|
||||
&body_R_parent_ref, &body_axis_of_motion, &mass, &body_r_body_com,
|
||||
&body_I_body, &user_int, &user_ptr))
|
||||
{
|
||||
bt_id_error_message("getting data for body %d\n", index);
|
||||
delete tree;
|
||||
return 0x0;
|
||||
}
|
||||
// add body to system
|
||||
if (-1 ==
|
||||
tree->addBody(index, parent_index, joint_type, body_r_parent_body_ref,
|
||||
body_R_parent_ref, body_axis_of_motion, mass, body_r_body_com,
|
||||
body_I_body, user_int, user_ptr))
|
||||
{
|
||||
bt_id_error_message("adding body %d\n", index);
|
||||
delete tree;
|
||||
return 0x0;
|
||||
}
|
||||
}
|
||||
// finalize initialization
|
||||
if (-1 == tree->finalize())
|
||||
{
|
||||
bt_id_error_message("building system\n");
|
||||
delete tree;
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
} // namespace btInverseDynamics
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef MULTI_BODY_TREE_CREATOR_HPP_
|
||||
#define MULTI_BODY_TREE_CREATOR_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "BulletInverseDynamics/IDConfig.hpp"
|
||||
#include "BulletInverseDynamics/IDMath.hpp"
|
||||
#include "BulletInverseDynamics/MultiBodyTree.hpp"
|
||||
#include "MultiBodyNameMap.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
/// Interface class for initializing a MultiBodyTree instance.
|
||||
/// Data to be provided is modeled on the URDF specification.
|
||||
/// The user can derive from this class in order to programmatically
|
||||
/// initialize a system.
|
||||
class MultiBodyTreeCreator
|
||||
{
|
||||
public:
|
||||
/// the dtor
|
||||
virtual ~MultiBodyTreeCreator() {}
|
||||
/// Get the number of bodies in the system
|
||||
/// @param num_bodies write number of bodies here
|
||||
/// @return 0 on success, -1 on error
|
||||
virtual int getNumBodies(int* num_bodies) const = 0;
|
||||
/// Interface for accessing link mass properties.
|
||||
/// For detailed description of data, @sa MultiBodyTree::addBody
|
||||
/// \copydoc MultiBodyTree::addBody
|
||||
virtual int getBody(const int body_index, int* parent_index, JointType* joint_type,
|
||||
vec3* parent_r_parent_body_ref, mat33* body_T_parent_ref,
|
||||
vec3* body_axis_of_motion, idScalar* mass, vec3* body_r_body_com,
|
||||
mat33* body_I_body, int* user_int, void** user_ptr) const = 0;
|
||||
/// @return a pointer to a name mapping utility class, or 0x0 if not available
|
||||
virtual const MultiBodyNameMap* getNameMap() const { return 0x0; }
|
||||
};
|
||||
|
||||
/// Create a multibody object.
|
||||
/// @param creator an object implementing the MultiBodyTreeCreator interface
|
||||
/// that returns data defining the system
|
||||
/// @return A pointer to an allocated multibodytree instance, or
|
||||
/// 0x0 if an error occured.
|
||||
MultiBodyTree* CreateMultiBodyTree(const MultiBodyTreeCreator& creator);
|
||||
} // namespace btInverseDynamics
|
||||
|
||||
// does urdf have gravity direction ??
|
||||
|
||||
#endif // MULTI_BODY_TREE_CREATOR_HPP_
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
#include "MultiBodyTreeDebugGraph.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
int writeGraphvizDotFile(const MultiBodyTree* tree, const MultiBodyNameMap* map,
|
||||
const char* filename)
|
||||
{
|
||||
if (0x0 == tree)
|
||||
{
|
||||
bt_id_error_message("tree pointer is null\n");
|
||||
return -1;
|
||||
}
|
||||
if (0x0 == filename)
|
||||
{
|
||||
bt_id_error_message("filename is null\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE* fp = fopen(filename, "w");
|
||||
if (NULL == fp)
|
||||
{
|
||||
bt_id_error_message("cannot open file %s for writing\n", filename);
|
||||
return -1;
|
||||
}
|
||||
fprintf(fp,
|
||||
"// to generate postscript file, run dot -Tps %s -o %s.ps\n"
|
||||
"// details see graphviz documentation at http://graphviz.org\n"
|
||||
"digraph tree {\n",
|
||||
filename, filename);
|
||||
|
||||
for (int body = 0; body < tree->numBodies(); body++)
|
||||
{
|
||||
std::string name;
|
||||
if (0x0 != map)
|
||||
{
|
||||
if (-1 == map->getBodyName(body, &name))
|
||||
{
|
||||
bt_id_error_message("can't get name of body %d\n", body);
|
||||
return -1;
|
||||
}
|
||||
fprintf(fp, " %d [label=\"%d/%s\"];\n", body, body, name.c_str());
|
||||
}
|
||||
}
|
||||
for (int body = 0; body < tree->numBodies(); body++)
|
||||
{
|
||||
int parent;
|
||||
const char* joint_type;
|
||||
int qi;
|
||||
if (-1 == tree->getParentIndex(body, &parent))
|
||||
{
|
||||
bt_id_error_message("indexing error\n");
|
||||
return -1;
|
||||
}
|
||||
if (-1 == tree->getJointTypeStr(body, &joint_type))
|
||||
{
|
||||
bt_id_error_message("indexing error\n");
|
||||
return -1;
|
||||
}
|
||||
if (-1 == tree->getDoFOffset(body, &qi))
|
||||
{
|
||||
bt_id_error_message("indexing error\n");
|
||||
return -1;
|
||||
}
|
||||
if (-1 != parent)
|
||||
{
|
||||
fprintf(fp, " %d -> %d [label= \"type:%s, q=%d\"];\n", parent, body,
|
||||
joint_type, qi);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(fp, "}\n");
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
} // namespace btInverseDynamics
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef MULTIBODYTREEDEBUGGRAPH_HPP_
|
||||
#define MULTIBODYTREEDEBUGGRAPH_HPP_
|
||||
#include "BulletInverseDynamics/IDConfig.hpp"
|
||||
#include "BulletInverseDynamics/MultiBodyTree.hpp"
|
||||
#include "MultiBodyNameMap.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
/// generate a dot-file of the multibody tree for generating a graph using graphviz' dot tool
|
||||
/// @param tree the multibody tree
|
||||
/// @param map to add names of links (if 0x0, no names will be added)
|
||||
/// @param filename name for the output file
|
||||
/// @return 0 on success, -1 on error
|
||||
int writeGraphvizDotFile(const MultiBodyTree* tree, const MultiBodyNameMap* map,
|
||||
const char* filename);
|
||||
} // namespace btInverseDynamics
|
||||
|
||||
#endif // MULTIBODYTREEDEBUGGRAPH_HPP
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
#include "RandomTreeCreator.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "IDRandomUtil.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
RandomTreeCreator::RandomTreeCreator(const int max_bodies, bool random_seed)
|
||||
{
|
||||
// seed generator
|
||||
if (random_seed)
|
||||
{
|
||||
randomInit(); // seeds with time()
|
||||
}
|
||||
else
|
||||
{
|
||||
randomInit(1); // seeds with 1
|
||||
}
|
||||
m_num_bodies = randomInt(1, max_bodies);
|
||||
}
|
||||
|
||||
RandomTreeCreator::~RandomTreeCreator() {}
|
||||
|
||||
int RandomTreeCreator::getNumBodies(int* num_bodies) const
|
||||
{
|
||||
*num_bodies = m_num_bodies;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RandomTreeCreator::getBody(const int body_index, int* parent_index, JointType* joint_type,
|
||||
vec3* parent_r_parent_body_ref, mat33* body_T_parent_ref,
|
||||
vec3* body_axis_of_motion, idScalar* mass, vec3* body_r_body_com,
|
||||
mat33* body_I_body, int* user_int, void** user_ptr) const
|
||||
{
|
||||
if (0 == body_index)
|
||||
{ //root body
|
||||
*parent_index = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*parent_index = randomInt(0, body_index - 1);
|
||||
}
|
||||
|
||||
switch (randomInt(0, 3))
|
||||
{
|
||||
case 0:
|
||||
*joint_type = FIXED;
|
||||
break;
|
||||
case 1:
|
||||
*joint_type = REVOLUTE;
|
||||
break;
|
||||
case 2:
|
||||
*joint_type = PRISMATIC;
|
||||
break;
|
||||
case 3:
|
||||
*joint_type = FLOATING;
|
||||
break;
|
||||
default:
|
||||
bt_id_error_message("randomInt() result out of range\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
(*parent_r_parent_body_ref)(0) = randomFloat(-1.0, 1.0);
|
||||
(*parent_r_parent_body_ref)(1) = randomFloat(-1.0, 1.0);
|
||||
(*parent_r_parent_body_ref)(2) = randomFloat(-1.0, 1.0);
|
||||
|
||||
bodyTParentFromAxisAngle(randomAxis(), randomFloat(-BT_ID_PI, BT_ID_PI), body_T_parent_ref);
|
||||
|
||||
*body_axis_of_motion = randomAxis();
|
||||
*mass = randomMass();
|
||||
(*body_r_body_com)(0) = randomFloat(-1.0, 1.0);
|
||||
(*body_r_body_com)(1) = randomFloat(-1.0, 1.0);
|
||||
(*body_r_body_com)(2) = randomFloat(-1.0, 1.0);
|
||||
const double a = randomFloat(-BT_ID_PI, BT_ID_PI);
|
||||
const double b = randomFloat(-BT_ID_PI, BT_ID_PI);
|
||||
const double c = randomFloat(-BT_ID_PI, BT_ID_PI);
|
||||
vec3 ii = randomInertiaPrincipal();
|
||||
mat33 ii_diag;
|
||||
setZero(ii_diag);
|
||||
ii_diag(0, 0) = ii(0);
|
||||
ii_diag(1, 1) = ii(1);
|
||||
ii_diag(2, 2) = ii(2);
|
||||
*body_I_body = transformX(a) * transformY(b) * transformZ(c) * ii_diag *
|
||||
transformZ(-c) * transformY(-b) * transformX(-a);
|
||||
*user_int = 0;
|
||||
*user_ptr = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace btInverseDynamics
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef RANDOMTREE_CREATOR_HPP_
|
||||
#define RANDOMTREE_CREATOR_HPP_
|
||||
|
||||
#include "BulletInverseDynamics/IDConfig.hpp"
|
||||
#include "MultiBodyTreeCreator.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
/// Generate a random MultiBodyTree with fixed or floating base and fixed, prismatic or revolute
|
||||
/// joints
|
||||
/// Uses a pseudo random number generator seeded from a random device.
|
||||
class RandomTreeCreator : public MultiBodyTreeCreator
|
||||
{
|
||||
public:
|
||||
/// ctor
|
||||
/// @param max_bodies maximum number of bodies
|
||||
/// @param gravity gravitational acceleration
|
||||
/// @param use_seed if true, seed random number generator
|
||||
RandomTreeCreator(const int max_bodies, bool use_seed = false);
|
||||
~RandomTreeCreator();
|
||||
///\copydoc MultiBodyTreeCreator::getNumBodies
|
||||
int getNumBodies(int* num_bodies) const;
|
||||
///\copydoc MultiBodyTreeCreator::getBody
|
||||
int getBody(const int body_index, int* parent_index, JointType* joint_type,
|
||||
vec3* parent_r_parent_body_ref, mat33* body_T_parent_ref, vec3* body_axis_of_motion,
|
||||
idScalar* mass, vec3* body_r_body_com, mat33* body_I_body, int* user_int,
|
||||
void** user_ptr) const;
|
||||
|
||||
private:
|
||||
int m_num_bodies;
|
||||
};
|
||||
} // namespace btInverseDynamics
|
||||
#endif // RANDOMTREE_CREATOR_HPP_
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
#include "SimpleTreeCreator.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
/// minimal "tree" (chain)
|
||||
SimpleTreeCreator::SimpleTreeCreator(int dim) : m_num_bodies(dim)
|
||||
{
|
||||
m_mass = 1.0;
|
||||
m_body_T_parent_ref(0, 0) = 1;
|
||||
m_body_T_parent_ref(0, 1) = 0;
|
||||
m_body_T_parent_ref(0, 2) = 0;
|
||||
m_body_T_parent_ref(1, 0) = 0;
|
||||
m_body_T_parent_ref(1, 1) = 1;
|
||||
m_body_T_parent_ref(1, 2) = 0;
|
||||
m_body_T_parent_ref(2, 0) = 0;
|
||||
m_body_T_parent_ref(2, 1) = 0;
|
||||
m_body_T_parent_ref(2, 2) = 1;
|
||||
|
||||
m_parent_r_parent_body_ref(0) = 1.0;
|
||||
m_parent_r_parent_body_ref(1) = 0.0;
|
||||
m_parent_r_parent_body_ref(2) = 0.0;
|
||||
|
||||
m_body_r_body_com(0) = 0.5;
|
||||
m_body_r_body_com(1) = 0.0;
|
||||
m_body_r_body_com(2) = 0.0;
|
||||
|
||||
m_body_I_body(0, 0) = 1;
|
||||
m_body_I_body(0, 1) = 0;
|
||||
m_body_I_body(0, 2) = 0;
|
||||
m_body_I_body(1, 0) = 0;
|
||||
m_body_I_body(1, 1) = 1;
|
||||
m_body_I_body(1, 2) = 0;
|
||||
m_body_I_body(2, 0) = 0;
|
||||
m_body_I_body(2, 1) = 0;
|
||||
m_body_I_body(2, 2) = 1;
|
||||
|
||||
m_axis(0) = 0;
|
||||
m_axis(1) = 0;
|
||||
m_axis(2) = 1;
|
||||
}
|
||||
int SimpleTreeCreator::getNumBodies(int* num_bodies) const
|
||||
{
|
||||
*num_bodies = m_num_bodies;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SimpleTreeCreator::getBody(const int body_index, int* parent_index, JointType* joint_type,
|
||||
vec3* parent_r_parent_body_ref, mat33* body_T_parent_ref,
|
||||
vec3* body_axis_of_motion, idScalar* mass, vec3* body_r_body_com,
|
||||
mat33* body_I_body, int* user_int, void** user_ptr) const
|
||||
{
|
||||
*parent_index = body_index - 1;
|
||||
if (body_index % 2)
|
||||
{
|
||||
*joint_type = PRISMATIC;
|
||||
}
|
||||
else
|
||||
{
|
||||
*joint_type = REVOLUTE;
|
||||
}
|
||||
*parent_r_parent_body_ref = m_parent_r_parent_body_ref;
|
||||
if (0 == body_index)
|
||||
{
|
||||
(*parent_r_parent_body_ref)(2) = 1.0;
|
||||
}
|
||||
*body_T_parent_ref = m_body_T_parent_ref;
|
||||
*body_axis_of_motion = m_axis;
|
||||
*mass = m_mass;
|
||||
*body_r_body_com = m_body_r_body_com;
|
||||
*body_I_body = m_body_I_body;
|
||||
*user_int = 0;
|
||||
*user_ptr = 0;
|
||||
return 0;
|
||||
}
|
||||
} // namespace btInverseDynamics
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef SIMPLETREECREATOR_HPP_
|
||||
#define SIMPLETREECREATOR_HPP_
|
||||
|
||||
#include "MultiBodyTreeCreator.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
/// minimal "tree" (chain)
|
||||
class SimpleTreeCreator : public MultiBodyTreeCreator
|
||||
{
|
||||
public:
|
||||
/// ctor
|
||||
/// @param dim number of bodies
|
||||
SimpleTreeCreator(int dim);
|
||||
// dtor
|
||||
~SimpleTreeCreator() {}
|
||||
///\copydoc MultiBodyTreeCreator::getNumBodies
|
||||
int getNumBodies(int* num_bodies) const;
|
||||
///\copydoc MultiBodyTreeCreator::getBody
|
||||
int getBody(const int body_index, int* parent_index, JointType* joint_type,
|
||||
vec3* parent_r_parent_body_ref, mat33* body_T_parent_ref, vec3* body_axis_of_motion,
|
||||
idScalar* mass, vec3* body_r_body_com, mat33* body_I_body, int* user_int,
|
||||
void** user_ptr) const;
|
||||
|
||||
private:
|
||||
int m_num_bodies;
|
||||
idScalar m_mass;
|
||||
mat33 m_body_T_parent_ref;
|
||||
vec3 m_parent_r_parent_body_ref;
|
||||
vec3 m_body_r_body_com;
|
||||
mat33 m_body_I_body;
|
||||
vec3 m_axis;
|
||||
};
|
||||
} // namespace btInverseDynamics
|
||||
#endif // SIMPLETREECREATOR_HPP_
|
||||
121
Engine/lib/bullet/Extras/InverseDynamics/User2InternalIndex.cpp
Normal file
121
Engine/lib/bullet/Extras/InverseDynamics/User2InternalIndex.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
#include "User2InternalIndex.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
User2InternalIndex::User2InternalIndex() : m_map_built(false) {}
|
||||
|
||||
void User2InternalIndex::addBody(const int body, const int parent)
|
||||
{
|
||||
m_user_parent_index_map[body] = parent;
|
||||
}
|
||||
|
||||
int User2InternalIndex::findRoot(int index)
|
||||
{
|
||||
if (0 == m_user_parent_index_map.count(index))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
return findRoot(m_user_parent_index_map[index]);
|
||||
}
|
||||
|
||||
// modelled after URDF2Bullet.cpp:void ComputeParentIndices(const
|
||||
// URDFImporterInterface& u2b, URDF2BulletCachedData& cache, int urdfLinkIndex,
|
||||
// int urdfParentIndex)
|
||||
void User2InternalIndex::recurseIndexSets(const int user_body_index)
|
||||
{
|
||||
m_user_to_internal[user_body_index] = m_current_index;
|
||||
m_current_index++;
|
||||
for (size_t i = 0; i < m_user_child_indices[user_body_index].size(); i++)
|
||||
{
|
||||
recurseIndexSets(m_user_child_indices[user_body_index][i]);
|
||||
}
|
||||
}
|
||||
|
||||
int User2InternalIndex::buildMapping()
|
||||
{
|
||||
// find root index
|
||||
int user_root_index = -1;
|
||||
for (std::map<int, int>::iterator it = m_user_parent_index_map.begin();
|
||||
it != m_user_parent_index_map.end(); it++)
|
||||
{
|
||||
int current_root_index = findRoot(it->second);
|
||||
if (it == m_user_parent_index_map.begin())
|
||||
{
|
||||
user_root_index = current_root_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (user_root_index != current_root_index)
|
||||
{
|
||||
bt_id_error_message("multiple roots (at least) %d and %d\n", user_root_index,
|
||||
current_root_index);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build child index map
|
||||
for (std::map<int, int>::iterator it = m_user_parent_index_map.begin();
|
||||
it != m_user_parent_index_map.end(); it++)
|
||||
{
|
||||
m_user_child_indices[it->second].push_back(it->first);
|
||||
}
|
||||
|
||||
m_current_index = -1;
|
||||
// build internal index set
|
||||
m_user_to_internal[user_root_index] = -1; // add map for root link
|
||||
recurseIndexSets(user_root_index);
|
||||
|
||||
// reverse mapping
|
||||
for (std::map<int, int>::iterator it = m_user_to_internal.begin();
|
||||
it != m_user_to_internal.end(); it++)
|
||||
{
|
||||
m_internal_to_user[it->second] = it->first;
|
||||
}
|
||||
|
||||
m_map_built = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int User2InternalIndex::user2internal(const int user, int *internal) const
|
||||
{
|
||||
if (!m_map_built)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::map<int, int>::const_iterator it;
|
||||
it = m_user_to_internal.find(user);
|
||||
if (it != m_user_to_internal.end())
|
||||
{
|
||||
*internal = it->second;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bt_id_error_message("no user index %d\n", user);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int User2InternalIndex::internal2user(const int internal, int *user) const
|
||||
{
|
||||
if (!m_map_built)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::map<int, int>::const_iterator it;
|
||||
it = m_internal_to_user.find(internal);
|
||||
if (it != m_internal_to_user.end())
|
||||
{
|
||||
*user = it->second;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bt_id_error_message("no internal index %d\n", internal);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} // namespace btInverseDynamics
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef USER2INTERNALINDEX_HPP
|
||||
#define USER2INTERNALINDEX_HPP
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "BulletInverseDynamics/IDConfig.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
/// Convert arbitrary indexing scheme to internal indexing
|
||||
/// used for MultiBodyTree
|
||||
class User2InternalIndex
|
||||
{
|
||||
public:
|
||||
/// Ctor
|
||||
User2InternalIndex();
|
||||
/// add body to index maps
|
||||
/// @param body index of body to add (external)
|
||||
/// @param parent index of parent body (external)
|
||||
void addBody(const int body, const int parent);
|
||||
/// build mapping from external to internal indexing
|
||||
/// @return 0 on success, -1 on failure
|
||||
int buildMapping();
|
||||
/// get internal index from external index
|
||||
/// @param user external (user) index
|
||||
/// @param internal pointer for storage of corresponding internal index
|
||||
/// @return 0 on success, -1 on failure
|
||||
int user2internal(const int user, int *internal) const;
|
||||
/// get internal index from external index
|
||||
/// @param user external (user) index
|
||||
/// @param internal pointer for storage of corresponding internal index
|
||||
/// @return 0 on success, -1 on failure
|
||||
int internal2user(const int internal, int *user) const;
|
||||
|
||||
private:
|
||||
int findRoot(int index);
|
||||
void recurseIndexSets(const int user_body_index);
|
||||
bool m_map_built;
|
||||
std::map<int, int> m_user_parent_index_map;
|
||||
std::map<int, int> m_user_to_internal;
|
||||
std::map<int, int> m_internal_to_user;
|
||||
std::map<int, std::vector<int> > m_user_child_indices;
|
||||
int m_current_index;
|
||||
};
|
||||
} // namespace btInverseDynamics
|
||||
|
||||
#endif // USER2INTERNALINDEX_HPP
|
||||
101
Engine/lib/bullet/Extras/InverseDynamics/btMultiBodyFromURDF.hpp
Normal file
101
Engine/lib/bullet/Extras/InverseDynamics/btMultiBodyFromURDF.hpp
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#ifndef BTMULTIBODYFROMURDF_HPP
|
||||
#define BTMULTIBODYFROMURDF_HPP
|
||||
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
|
||||
#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
|
||||
#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
|
||||
#include "BulletDynamics/Featherstone/btMultiBodyPoint2Point.h"
|
||||
#include "../../examples/CommonInterfaces/CommonGUIHelperInterface.h"
|
||||
#include "../../examples/Importers/ImportURDFDemo/BulletUrdfImporter.h"
|
||||
#include "../../examples/Importers/ImportURDFDemo/URDF2Bullet.h"
|
||||
#include "../../examples/Importers/ImportURDFDemo/MyMultiBodyCreator.h"
|
||||
#include "../../examples/Importers/ImportURDFDemo/URDF2Bullet.h"
|
||||
#include "../../examples/Utils/b3BulletDefaultFileIO.h"
|
||||
/// Create a btMultiBody model from URDF.
|
||||
/// This is adapted from Bullet URDF loader example
|
||||
class MyBtMultiBodyFromURDF
|
||||
{
|
||||
public:
|
||||
/// ctor
|
||||
/// @param gravity gravitational acceleration (in world frame)
|
||||
/// @param base_fixed if true, the root body is treated as fixed,
|
||||
/// if false, it is treated as floating
|
||||
MyBtMultiBodyFromURDF(const btVector3 &gravity, const bool base_fixed)
|
||||
: m_gravity(gravity), m_base_fixed(base_fixed)
|
||||
{
|
||||
m_broadphase = 0x0;
|
||||
m_dispatcher = 0x0;
|
||||
m_solver = 0x0;
|
||||
m_collisionConfiguration = 0x0;
|
||||
m_dynamicsWorld = 0x0;
|
||||
m_multibody = 0x0;
|
||||
m_flag = 0x0;
|
||||
}
|
||||
/// dtor
|
||||
~MyBtMultiBodyFromURDF()
|
||||
{
|
||||
delete m_dynamicsWorld;
|
||||
delete m_solver;
|
||||
delete m_broadphase;
|
||||
delete m_dispatcher;
|
||||
delete m_collisionConfiguration;
|
||||
delete m_multibody;
|
||||
}
|
||||
/// @param name path to urdf file
|
||||
void setFileName(const std::string name) { m_filename = name; }
|
||||
void setFlag(int flag) { m_flag = flag; }
|
||||
/// load urdf file and build btMultiBody model
|
||||
void init()
|
||||
{
|
||||
this->createEmptyDynamicsWorld();
|
||||
m_dynamicsWorld->setGravity(m_gravity);
|
||||
b3BulletDefaultFileIO fileIO;
|
||||
BulletURDFImporter urdf_importer(&m_nogfx, 0, &fileIO, 1, 0);
|
||||
URDFImporterInterface &u2b(urdf_importer);
|
||||
bool loadOk = u2b.loadURDF(m_filename.c_str(), m_base_fixed);
|
||||
|
||||
if (loadOk)
|
||||
{
|
||||
btTransform identityTrans;
|
||||
identityTrans.setIdentity();
|
||||
MyMultiBodyCreator creation(&m_nogfx);
|
||||
const bool use_multibody = true;
|
||||
ConvertURDF2Bullet(u2b, creation, identityTrans, m_dynamicsWorld, use_multibody,
|
||||
u2b.getPathPrefix(), m_flag);
|
||||
m_multibody = creation.getBulletMultiBody();
|
||||
m_dynamicsWorld->stepSimulation(1. / 240., 0);
|
||||
}
|
||||
}
|
||||
/// @return pointer to the btMultiBody model
|
||||
btMultiBody *getBtMultiBody() { return m_multibody; }
|
||||
|
||||
private:
|
||||
// internal utility function
|
||||
void createEmptyDynamicsWorld()
|
||||
{
|
||||
m_collisionConfiguration = new btDefaultCollisionConfiguration();
|
||||
|
||||
/// use the default collision dispatcher. For parallel processing you can use a diffent
|
||||
/// dispatcher (see Extras/BulletMultiThreaded)
|
||||
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
|
||||
m_broadphase = new btDbvtBroadphase();
|
||||
m_solver = new btMultiBodyConstraintSolver;
|
||||
m_dynamicsWorld = new btMultiBodyDynamicsWorld(m_dispatcher, m_broadphase, m_solver,
|
||||
m_collisionConfiguration);
|
||||
m_dynamicsWorld->setGravity(m_gravity);
|
||||
}
|
||||
|
||||
btBroadphaseInterface *m_broadphase;
|
||||
btCollisionDispatcher *m_dispatcher;
|
||||
btMultiBodyConstraintSolver *m_solver;
|
||||
btDefaultCollisionConfiguration *m_collisionConfiguration;
|
||||
btMultiBodyDynamicsWorld *m_dynamicsWorld;
|
||||
std::string m_filename;
|
||||
DummyGUIHelper m_nogfx;
|
||||
btMultiBody *m_multibody;
|
||||
const btVector3 m_gravity;
|
||||
const bool m_base_fixed;
|
||||
int m_flag;
|
||||
};
|
||||
#endif // BTMULTIBODYFROMURDF_HPP
|
||||
|
|
@ -0,0 +1,306 @@
|
|||
#include "btMultiBodyTreeCreator.hpp"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
btMultiBodyTreeCreator::btMultiBodyTreeCreator() : m_initialized(false) {}
|
||||
|
||||
int btMultiBodyTreeCreator::createFromBtMultiBody(const btMultiBody *btmb, const bool verbose)
|
||||
{
|
||||
if (0x0 == btmb)
|
||||
{
|
||||
bt_id_error_message("cannot create MultiBodyTree from null pointer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// in case this is a second call, discard old data
|
||||
m_data.clear();
|
||||
m_initialized = false;
|
||||
|
||||
// btMultiBody treats base link separately
|
||||
m_data.resize(1 + btmb->getNumLinks());
|
||||
|
||||
// add base link data
|
||||
{
|
||||
LinkData &link = m_data[0];
|
||||
|
||||
link.parent_index = -1;
|
||||
if (btmb->hasFixedBase())
|
||||
{
|
||||
link.joint_type = FIXED;
|
||||
}
|
||||
else
|
||||
{
|
||||
link.joint_type = FLOATING;
|
||||
}
|
||||
btTransform transform = (btmb->getBaseWorldTransform());
|
||||
//compute inverse dynamics in body-fixed frame
|
||||
transform.setIdentity();
|
||||
|
||||
link.parent_r_parent_body_ref(0) = transform.getOrigin()[0];
|
||||
link.parent_r_parent_body_ref(1) = transform.getOrigin()[1];
|
||||
link.parent_r_parent_body_ref(2) = transform.getOrigin()[2];
|
||||
|
||||
link.body_T_parent_ref(0, 0) = transform.getBasis()[0][0];
|
||||
link.body_T_parent_ref(0, 1) = transform.getBasis()[0][1];
|
||||
link.body_T_parent_ref(0, 2) = transform.getBasis()[0][2];
|
||||
|
||||
link.body_T_parent_ref(1, 0) = transform.getBasis()[1][0];
|
||||
link.body_T_parent_ref(1, 1) = transform.getBasis()[1][1];
|
||||
link.body_T_parent_ref(1, 2) = transform.getBasis()[1][2];
|
||||
|
||||
link.body_T_parent_ref(2, 0) = transform.getBasis()[2][0];
|
||||
link.body_T_parent_ref(2, 1) = transform.getBasis()[2][1];
|
||||
link.body_T_parent_ref(2, 2) = transform.getBasis()[2][2];
|
||||
|
||||
// random unit vector. value not used for fixed or floating joints.
|
||||
link.body_axis_of_motion(0) = 0;
|
||||
link.body_axis_of_motion(1) = 0;
|
||||
link.body_axis_of_motion(2) = 1;
|
||||
|
||||
link.mass = btmb->getBaseMass();
|
||||
// link frame in the center of mass
|
||||
link.body_r_body_com(0) = 0;
|
||||
link.body_r_body_com(1) = 0;
|
||||
link.body_r_body_com(2) = 0;
|
||||
// BulletDynamics uses body-fixed frame in the cog, aligned with principal axes
|
||||
link.body_I_body(0, 0) = btmb->getBaseInertia()[0];
|
||||
link.body_I_body(0, 1) = 0.0;
|
||||
link.body_I_body(0, 2) = 0.0;
|
||||
link.body_I_body(1, 0) = 0.0;
|
||||
link.body_I_body(1, 1) = btmb->getBaseInertia()[1];
|
||||
link.body_I_body(1, 2) = 0.0;
|
||||
link.body_I_body(2, 0) = 0.0;
|
||||
link.body_I_body(2, 1) = 0.0;
|
||||
link.body_I_body(2, 2) = btmb->getBaseInertia()[2];
|
||||
// shift reference point to link origin (in joint axis)
|
||||
mat33 tilde_r_com = tildeOperator(link.body_r_body_com);
|
||||
link.body_I_body = link.body_I_body - link.mass * tilde_r_com * tilde_r_com;
|
||||
if (verbose)
|
||||
{
|
||||
id_printf(
|
||||
"base: mass= %f, bt_inertia= [%f %f %f]\n"
|
||||
"Io= [%f %f %f;\n"
|
||||
" %f %f %f;\n"
|
||||
" %f %f %f]\n",
|
||||
link.mass, btmb->getBaseInertia()[0], btmb->getBaseInertia()[1],
|
||||
btmb->getBaseInertia()[2], link.body_I_body(0, 0), link.body_I_body(0, 1),
|
||||
link.body_I_body(0, 2), link.body_I_body(1, 0), link.body_I_body(1, 1),
|
||||
link.body_I_body(1, 2), link.body_I_body(2, 0), link.body_I_body(2, 1),
|
||||
link.body_I_body(2, 2));
|
||||
}
|
||||
}
|
||||
|
||||
for (int bt_index = 0; bt_index < btmb->getNumLinks(); bt_index++)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
id_printf("bt->id: converting link %d\n", bt_index);
|
||||
}
|
||||
const btMultibodyLink &bt_link = btmb->getLink(bt_index);
|
||||
LinkData &link = m_data[bt_index + 1];
|
||||
|
||||
link.parent_index = bt_link.m_parent + 1;
|
||||
|
||||
link.mass = bt_link.m_mass;
|
||||
if (verbose)
|
||||
{
|
||||
id_printf("mass= %f\n", link.mass);
|
||||
}
|
||||
// from this body's pivot to this body's com in this body's frame
|
||||
link.body_r_body_com[0] = bt_link.m_dVector[0];
|
||||
link.body_r_body_com[1] = bt_link.m_dVector[1];
|
||||
link.body_r_body_com[2] = bt_link.m_dVector[2];
|
||||
if (verbose)
|
||||
{
|
||||
id_printf("com= %f %f %f\n", link.body_r_body_com[0], link.body_r_body_com[1],
|
||||
link.body_r_body_com[2]);
|
||||
}
|
||||
// BulletDynamics uses a body-fixed frame in the CoM, aligned with principal axes
|
||||
link.body_I_body(0, 0) = bt_link.m_inertiaLocal[0];
|
||||
link.body_I_body(0, 1) = 0.0;
|
||||
link.body_I_body(0, 2) = 0.0;
|
||||
link.body_I_body(1, 0) = 0.0;
|
||||
link.body_I_body(1, 1) = bt_link.m_inertiaLocal[1];
|
||||
link.body_I_body(1, 2) = 0.0;
|
||||
link.body_I_body(2, 0) = 0.0;
|
||||
link.body_I_body(2, 1) = 0.0;
|
||||
link.body_I_body(2, 2) = bt_link.m_inertiaLocal[2];
|
||||
// shift reference point to link origin (in joint axis)
|
||||
mat33 tilde_r_com = tildeOperator(link.body_r_body_com);
|
||||
link.body_I_body = link.body_I_body - link.mass * tilde_r_com * tilde_r_com;
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
id_printf(
|
||||
"link %d: mass= %f, bt_inertia= [%f %f %f]\n"
|
||||
"Io= [%f %f %f;\n"
|
||||
" %f %f %f;\n"
|
||||
" %f %f %f]\n",
|
||||
bt_index, link.mass, bt_link.m_inertiaLocal[0], bt_link.m_inertiaLocal[1],
|
||||
bt_link.m_inertiaLocal[2], link.body_I_body(0, 0), link.body_I_body(0, 1),
|
||||
link.body_I_body(0, 2), link.body_I_body(1, 0), link.body_I_body(1, 1),
|
||||
link.body_I_body(1, 2), link.body_I_body(2, 0), link.body_I_body(2, 1),
|
||||
link.body_I_body(2, 2));
|
||||
}
|
||||
// transform for vectors written in parent frame to this link's body-fixed frame
|
||||
btMatrix3x3 basis = btTransform(bt_link.m_zeroRotParentToThis).getBasis();
|
||||
link.body_T_parent_ref(0, 0) = basis[0][0];
|
||||
link.body_T_parent_ref(0, 1) = basis[0][1];
|
||||
link.body_T_parent_ref(0, 2) = basis[0][2];
|
||||
link.body_T_parent_ref(1, 0) = basis[1][0];
|
||||
link.body_T_parent_ref(1, 1) = basis[1][1];
|
||||
link.body_T_parent_ref(1, 2) = basis[1][2];
|
||||
link.body_T_parent_ref(2, 0) = basis[2][0];
|
||||
link.body_T_parent_ref(2, 1) = basis[2][1];
|
||||
link.body_T_parent_ref(2, 2) = basis[2][2];
|
||||
if (verbose)
|
||||
{
|
||||
id_printf(
|
||||
"body_T_parent_ref= %f %f %f\n"
|
||||
" %f %f %f\n"
|
||||
" %f %f %f\n",
|
||||
basis[0][0], basis[0][1], basis[0][2], basis[1][0], basis[1][1], basis[1][2],
|
||||
basis[2][0], basis[2][1], basis[2][2]);
|
||||
}
|
||||
switch (bt_link.m_jointType)
|
||||
{
|
||||
case btMultibodyLink::eRevolute:
|
||||
link.joint_type = REVOLUTE;
|
||||
if (verbose)
|
||||
{
|
||||
id_printf("type= revolute\n");
|
||||
}
|
||||
link.body_axis_of_motion(0) = bt_link.m_axes[0].m_topVec[0];
|
||||
link.body_axis_of_motion(1) = bt_link.m_axes[0].m_topVec[1];
|
||||
link.body_axis_of_motion(2) = bt_link.m_axes[0].m_topVec[2];
|
||||
|
||||
// for revolute joints, m_eVector = parentComToThisPivotOffset
|
||||
// m_dVector = thisPivotToThisComOffset
|
||||
// from parent com to pivot, in parent frame
|
||||
link.parent_r_parent_body_ref(0) = bt_link.m_eVector[0];
|
||||
link.parent_r_parent_body_ref(1) = bt_link.m_eVector[1];
|
||||
link.parent_r_parent_body_ref(2) = bt_link.m_eVector[2];
|
||||
break;
|
||||
case btMultibodyLink::ePrismatic:
|
||||
link.joint_type = PRISMATIC;
|
||||
if (verbose)
|
||||
{
|
||||
id_printf("type= prismatic\n");
|
||||
}
|
||||
link.body_axis_of_motion(0) = bt_link.m_axes[0].m_bottomVec[0];
|
||||
link.body_axis_of_motion(1) = bt_link.m_axes[0].m_bottomVec[1];
|
||||
link.body_axis_of_motion(2) = bt_link.m_axes[0].m_bottomVec[2];
|
||||
|
||||
// for prismatic joints, eVector
|
||||
// according to documentation :
|
||||
// parentComToThisComOffset
|
||||
// but seems to be: from parent's com to parent's
|
||||
// pivot ??
|
||||
// m_dVector = thisPivotToThisComOffset
|
||||
link.parent_r_parent_body_ref(0) = bt_link.m_eVector[0];
|
||||
link.parent_r_parent_body_ref(1) = bt_link.m_eVector[1];
|
||||
link.parent_r_parent_body_ref(2) = bt_link.m_eVector[2];
|
||||
break;
|
||||
case btMultibodyLink::eSpherical:
|
||||
link.joint_type = SPHERICAL;
|
||||
link.parent_r_parent_body_ref(0) = bt_link.m_eVector[0];
|
||||
link.parent_r_parent_body_ref(1) = bt_link.m_eVector[1];
|
||||
link.parent_r_parent_body_ref(2) = bt_link.m_eVector[2];
|
||||
// random unit vector
|
||||
link.body_axis_of_motion(0) = 0;
|
||||
link.body_axis_of_motion(1) = 1;
|
||||
link.body_axis_of_motion(2) = 0;
|
||||
break;
|
||||
case btMultibodyLink::ePlanar:
|
||||
bt_id_error_message("planar joints not implemented\n");
|
||||
return -1;
|
||||
case btMultibodyLink::eFixed:
|
||||
link.joint_type = FIXED;
|
||||
// random unit vector
|
||||
link.body_axis_of_motion(0) = 0;
|
||||
link.body_axis_of_motion(1) = 0;
|
||||
link.body_axis_of_motion(2) = 1;
|
||||
|
||||
// for fixed joints, m_dVector = thisPivotToThisComOffset;
|
||||
// m_eVector = parentComToThisPivotOffset;
|
||||
link.parent_r_parent_body_ref(0) = bt_link.m_eVector[0];
|
||||
link.parent_r_parent_body_ref(1) = bt_link.m_eVector[1];
|
||||
link.parent_r_parent_body_ref(2) = bt_link.m_eVector[2];
|
||||
break;
|
||||
default:
|
||||
bt_id_error_message("unknown btMultiBody::eFeatherstoneJointType %d\n",
|
||||
bt_link.m_jointType);
|
||||
return -1;
|
||||
}
|
||||
if (link.parent_index > 0)
|
||||
{ // parent body isn't the root
|
||||
const btMultibodyLink &bt_parent_link = btmb->getLink(link.parent_index - 1);
|
||||
// from parent pivot to parent com, in parent frame
|
||||
link.parent_r_parent_body_ref(0) += bt_parent_link.m_dVector[0];
|
||||
link.parent_r_parent_body_ref(1) += bt_parent_link.m_dVector[1];
|
||||
link.parent_r_parent_body_ref(2) += bt_parent_link.m_dVector[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
// parent is root body. btMultiBody only knows 6-DoF or 0-DoF root bodies,
|
||||
// whose link frame is in the CoM (ie, no notion of a pivot point)
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
id_printf("parent_r_parent_body_ref= %f %f %f\n", link.parent_r_parent_body_ref[0],
|
||||
link.parent_r_parent_body_ref[1], link.parent_r_parent_body_ref[2]);
|
||||
}
|
||||
}
|
||||
|
||||
m_initialized = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btMultiBodyTreeCreator::getNumBodies(int *num_bodies) const
|
||||
{
|
||||
if (false == m_initialized)
|
||||
{
|
||||
bt_id_error_message("btMultiBody not converted yet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*num_bodies = static_cast<int>(m_data.size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btMultiBodyTreeCreator::getBody(const int body_index, int *parent_index, JointType *joint_type,
|
||||
vec3 *parent_r_parent_body_ref, mat33 *body_T_parent_ref,
|
||||
vec3 *body_axis_of_motion, idScalar *mass,
|
||||
vec3 *body_r_body_com, mat33 *body_I_body, int *user_int,
|
||||
void **user_ptr) const
|
||||
{
|
||||
if (false == m_initialized)
|
||||
{
|
||||
bt_id_error_message("MultiBodyTree not created yet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (body_index < 0 || body_index >= static_cast<int>(m_data.size()))
|
||||
{
|
||||
bt_id_error_message("index out of range (got %d but only %zu bodies)\n", body_index,
|
||||
m_data.size());
|
||||
return -1;
|
||||
}
|
||||
|
||||
*parent_index = m_data[body_index].parent_index;
|
||||
*joint_type = m_data[body_index].joint_type;
|
||||
*parent_r_parent_body_ref = m_data[body_index].parent_r_parent_body_ref;
|
||||
*body_T_parent_ref = m_data[body_index].body_T_parent_ref;
|
||||
*body_axis_of_motion = m_data[body_index].body_axis_of_motion;
|
||||
*mass = m_data[body_index].mass;
|
||||
*body_r_body_com = m_data[body_index].body_r_body_com;
|
||||
*body_I_body = m_data[body_index].body_I_body;
|
||||
|
||||
*user_int = -1;
|
||||
*user_ptr = 0x0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace btInverseDynamics
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef BTMULTIBODYTREECREATOR_HPP_
|
||||
#define BTMULTIBODYTREECREATOR_HPP_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "BulletInverseDynamics/IDConfig.hpp"
|
||||
#include "MultiBodyTreeCreator.hpp"
|
||||
#include "BulletDynamics/Featherstone/btMultiBody.h"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
/// MultiBodyTreeCreator implementation for converting
|
||||
/// a btMultiBody forward dynamics model into a MultiBodyTree inverse dynamics model
|
||||
class btMultiBodyTreeCreator : public MultiBodyTreeCreator
|
||||
{
|
||||
public:
|
||||
/// ctor
|
||||
btMultiBodyTreeCreator();
|
||||
/// dtor
|
||||
~btMultiBodyTreeCreator() {}
|
||||
/// extract model data from a btMultiBody
|
||||
/// @param btmb pointer to btMultiBody to convert
|
||||
/// @param verbose if true, some information is printed
|
||||
/// @return -1 on error, 0 on success
|
||||
int createFromBtMultiBody(const btMultiBody *btmb, const bool verbose = false);
|
||||
/// \copydoc MultiBodyTreeCreator::getNumBodies
|
||||
int getNumBodies(int *num_bodies) const;
|
||||
///\copydoc MultiBodyTreeCreator::getBody
|
||||
int getBody(const int body_index, int *parent_index, JointType *joint_type,
|
||||
vec3 *parent_r_parent_body_ref, mat33 *body_T_parent_ref,
|
||||
vec3 *body_axis_of_motion, idScalar *mass, vec3 *body_r_body_com,
|
||||
mat33 *body_I_body, int *user_int, void **user_ptr) const;
|
||||
|
||||
private:
|
||||
// internal struct holding data extracted from btMultiBody
|
||||
struct LinkData
|
||||
{
|
||||
int parent_index;
|
||||
JointType joint_type;
|
||||
vec3 parent_r_parent_body_ref;
|
||||
mat33 body_T_parent_ref;
|
||||
vec3 body_axis_of_motion;
|
||||
idScalar mass;
|
||||
vec3 body_r_body_com;
|
||||
mat33 body_I_body;
|
||||
};
|
||||
idArray<LinkData>::type m_data;
|
||||
bool m_initialized;
|
||||
};
|
||||
} // namespace btInverseDynamics
|
||||
|
||||
#endif // BTMULTIBODYTREECREATOR_HPP_
|
||||
|
|
@ -0,0 +1,361 @@
|
|||
#include "invdyn_bullet_comparison.hpp"
|
||||
#include <cmath>
|
||||
#include "BulletInverseDynamics/IDConfig.hpp"
|
||||
#include "BulletInverseDynamics/MultiBodyTree.hpp"
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
|
||||
#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
|
||||
#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
|
||||
#include "BulletDynamics/Featherstone/btMultiBodyPoint2Point.h"
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
int compareInverseAndForwardDynamics(vecx &q, vecx &u, vecx &dot_u, btVector3 &gravity, bool verbose,
|
||||
btMultiBody *btmb, MultiBodyTree *id_tree, double *pos_error,
|
||||
double *acc_error)
|
||||
{
|
||||
// call function and return -1 if it does, printing an bt_id_error_message
|
||||
#define RETURN_ON_FAILURE(x) \
|
||||
do \
|
||||
{ \
|
||||
if (-1 == x) \
|
||||
{ \
|
||||
bt_id_error_message("calling " #x "\n"); \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
printf("\n ===================================== \n");
|
||||
}
|
||||
vecx joint_forces(q.size());
|
||||
|
||||
// set positions and velocities for btMultiBody
|
||||
// base link
|
||||
mat33 world_T_base;
|
||||
vec3 world_pos_base;
|
||||
btTransform base_transform;
|
||||
vec3 base_velocity;
|
||||
vec3 base_angular_velocity;
|
||||
|
||||
RETURN_ON_FAILURE(id_tree->setGravityInWorldFrame(gravity));
|
||||
RETURN_ON_FAILURE(id_tree->getBodyOrigin(0, &world_pos_base));
|
||||
RETURN_ON_FAILURE(id_tree->getBodyTransform(0, &world_T_base));
|
||||
RETURN_ON_FAILURE(id_tree->getBodyAngularVelocity(0, &base_angular_velocity));
|
||||
RETURN_ON_FAILURE(id_tree->getBodyLinearVelocityCoM(0, &base_velocity));
|
||||
|
||||
base_transform.setBasis(world_T_base);
|
||||
base_transform.setOrigin(world_pos_base);
|
||||
btmb->setBaseWorldTransform(base_transform);
|
||||
btmb->setBaseOmega(base_angular_velocity);
|
||||
btmb->setBaseVel(base_velocity);
|
||||
btmb->setLinearDamping(0);
|
||||
btmb->setAngularDamping(0);
|
||||
|
||||
// remaining links
|
||||
int q_index;
|
||||
if (btmb->hasFixedBase())
|
||||
{
|
||||
q_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
q_index = 6;
|
||||
}
|
||||
if (verbose)
|
||||
{
|
||||
printf("bt:num_links= %d, num_dofs= %d\n", btmb->getNumLinks(), btmb->getNumDofs());
|
||||
}
|
||||
for (int l = 0; l < btmb->getNumLinks(); l++)
|
||||
{
|
||||
const btMultibodyLink &link = btmb->getLink(l);
|
||||
if (verbose)
|
||||
{
|
||||
printf("link %d, pos_var_count= %d, dof_count= %d\n", l, link.m_posVarCount,
|
||||
link.m_dofCount);
|
||||
}
|
||||
if (link.m_posVarCount == 1)
|
||||
{
|
||||
btmb->setJointPosMultiDof(l, &q(q_index));
|
||||
btmb->setJointVelMultiDof(l, &u(q_index));
|
||||
if (verbose)
|
||||
{
|
||||
printf("set q[%d]= %f, u[%d]= %f\n", q_index, q(q_index), q_index, u(q_index));
|
||||
}
|
||||
q_index++;
|
||||
}
|
||||
}
|
||||
// sanity check
|
||||
if (q_index != q.size())
|
||||
{
|
||||
bt_id_error_message("error in number of dofs for btMultibody and MultiBodyTree\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// run inverse dynamics to determine joint_forces for given q, u, dot_u
|
||||
if (-1 == id_tree->calculateInverseDynamics(q, u, dot_u, &joint_forces))
|
||||
{
|
||||
bt_id_error_message("calculating inverse dynamics\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set up bullet forward dynamics model
|
||||
btScalar dt = 0;
|
||||
btAlignedObjectArray<btScalar> scratch_r;
|
||||
btAlignedObjectArray<btVector3> scratch_v;
|
||||
btAlignedObjectArray<btMatrix3x3> scratch_m;
|
||||
// this triggers switch between using either appliedConstraintForce or appliedForce
|
||||
bool isConstraintPass = false;
|
||||
// apply gravity forces for btMultiBody model. Must be done manually.
|
||||
btmb->addBaseForce(btmb->getBaseMass() * gravity);
|
||||
|
||||
for (int link = 0; link < btmb->getNumLinks(); link++)
|
||||
{
|
||||
btmb->addLinkForce(link, gravity * btmb->getLinkMass(link));
|
||||
if (verbose)
|
||||
{
|
||||
printf("link %d, applying gravity %f %f %f\n", link,
|
||||
gravity[0] * btmb->getLinkMass(link), gravity[1] * btmb->getLinkMass(link),
|
||||
gravity[2] * btmb->getLinkMass(link));
|
||||
}
|
||||
}
|
||||
|
||||
// apply generalized forces
|
||||
if (btmb->hasFixedBase())
|
||||
{
|
||||
q_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vec3 base_force;
|
||||
base_force(0) = joint_forces(3);
|
||||
base_force(1) = joint_forces(4);
|
||||
base_force(2) = joint_forces(5);
|
||||
|
||||
vec3 base_moment;
|
||||
base_moment(0) = joint_forces(0);
|
||||
base_moment(1) = joint_forces(1);
|
||||
base_moment(2) = joint_forces(2);
|
||||
|
||||
btmb->addBaseForce(world_T_base * base_force);
|
||||
btmb->addBaseTorque(world_T_base * base_moment);
|
||||
if (verbose)
|
||||
{
|
||||
printf("base force from id: %f %f %f\n", joint_forces(3), joint_forces(4),
|
||||
joint_forces(5));
|
||||
printf("base moment from id: %f %f %f\n", joint_forces(0), joint_forces(1),
|
||||
joint_forces(2));
|
||||
}
|
||||
q_index = 6;
|
||||
}
|
||||
|
||||
for (int l = 0; l < btmb->getNumLinks(); l++)
|
||||
{
|
||||
const btMultibodyLink &link = btmb->getLink(l);
|
||||
if (link.m_posVarCount == 1)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
printf("id:joint_force[%d]= %f, applied to link %d\n", q_index,
|
||||
joint_forces(q_index), l);
|
||||
}
|
||||
btmb->addJointTorque(l, joint_forces(q_index));
|
||||
q_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// sanity check
|
||||
if (q_index != q.size())
|
||||
{
|
||||
bt_id_error_message("error in number of dofs for btMultibody and MultiBodyTree\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// run forward kinematics & forward dynamics
|
||||
btAlignedObjectArray<btQuaternion> world_to_local;
|
||||
btAlignedObjectArray<btVector3> local_origin;
|
||||
btmb->forwardKinematics(world_to_local, local_origin);
|
||||
btmb->computeAccelerationsArticulatedBodyAlgorithmMultiDof(dt, scratch_r, scratch_v, scratch_m, isConstraintPass, false, false);
|
||||
|
||||
// read generalized accelerations back from btMultiBody
|
||||
// the mapping from scratch variables to accelerations is taken from the implementation
|
||||
// of stepVelocitiesMultiDof
|
||||
btScalar *base_accel = &scratch_r[btmb->getNumDofs()];
|
||||
btScalar *joint_accel = base_accel + 6;
|
||||
*acc_error = 0;
|
||||
int dot_u_offset = 0;
|
||||
if (btmb->hasFixedBase())
|
||||
{
|
||||
dot_u_offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
dot_u_offset = 6;
|
||||
}
|
||||
|
||||
if (true == btmb->hasFixedBase())
|
||||
{
|
||||
for (int i = 0; i < btmb->getNumDofs(); i++)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
printf("bt:ddot_q[%d]= %f, id:ddot_q= %e, diff= %e\n", i, joint_accel[i],
|
||||
dot_u(i + dot_u_offset), joint_accel[i] - dot_u(i));
|
||||
}
|
||||
*acc_error += BT_ID_POW(joint_accel[i] - dot_u(i + dot_u_offset), 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vec3 base_dot_omega;
|
||||
vec3 world_dot_omega;
|
||||
world_dot_omega(0) = base_accel[0];
|
||||
world_dot_omega(1) = base_accel[1];
|
||||
world_dot_omega(2) = base_accel[2];
|
||||
base_dot_omega = world_T_base.transpose() * world_dot_omega;
|
||||
|
||||
// com happens to coincide with link origin here. If that changes, we need to calculate
|
||||
// ddot_com
|
||||
vec3 base_ddot_com;
|
||||
vec3 world_ddot_com;
|
||||
world_ddot_com(0) = base_accel[3];
|
||||
world_ddot_com(1) = base_accel[4];
|
||||
world_ddot_com(2) = base_accel[5];
|
||||
base_ddot_com = world_T_base.transpose() * world_ddot_com;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
printf("bt::base_dot_omega(%d)= %e dot_u[%d]= %e, diff= %e\n", i, base_dot_omega(i),
|
||||
i, dot_u[i], base_dot_omega(i) - dot_u[i]);
|
||||
}
|
||||
*acc_error += BT_ID_POW(base_dot_omega(i) - dot_u(i), 2);
|
||||
}
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
printf("bt::base_ddot_com(%d)= %e dot_u[%d]= %e, diff= %e\n", i, base_ddot_com(i),
|
||||
i, dot_u[i + 3], base_ddot_com(i) - dot_u[i + 3]);
|
||||
}
|
||||
*acc_error += BT_ID_POW(base_ddot_com(i) - dot_u(i + 3), 2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < btmb->getNumDofs(); i++)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
printf("bt:ddot_q[%d]= %f, id:ddot_q= %e, diff= %e\n", i, joint_accel[i],
|
||||
dot_u(i + 6), joint_accel[i] - dot_u(i + 6));
|
||||
}
|
||||
*acc_error += BT_ID_POW(joint_accel[i] - dot_u(i + 6), 2);
|
||||
}
|
||||
}
|
||||
*acc_error = std::sqrt(*acc_error);
|
||||
if (verbose)
|
||||
{
|
||||
printf("======dynamics-err: %e\n", *acc_error);
|
||||
}
|
||||
*pos_error = 0.0;
|
||||
|
||||
{
|
||||
mat33 world_T_body;
|
||||
if (-1 == id_tree->getBodyTransform(0, &world_T_body))
|
||||
{
|
||||
bt_id_error_message("getting transform for body %d\n", 0);
|
||||
return -1;
|
||||
}
|
||||
vec3 world_com;
|
||||
if (-1 == id_tree->getBodyCoM(0, &world_com))
|
||||
{
|
||||
bt_id_error_message("getting com for body %d\n", 0);
|
||||
return -1;
|
||||
}
|
||||
if (verbose)
|
||||
{
|
||||
printf("id:com: %f %f %f\n", world_com(0), world_com(1), world_com(2));
|
||||
|
||||
printf(
|
||||
"id:transform: %f %f %f\n"
|
||||
" %f %f %f\n"
|
||||
" %f %f %f\n",
|
||||
world_T_body(0, 0), world_T_body(0, 1), world_T_body(0, 2), world_T_body(1, 0),
|
||||
world_T_body(1, 1), world_T_body(1, 2), world_T_body(2, 0), world_T_body(2, 1),
|
||||
world_T_body(2, 2));
|
||||
}
|
||||
}
|
||||
|
||||
for (int l = 0; l < btmb->getNumLinks(); l++)
|
||||
{
|
||||
const btMultibodyLink &bt_link = btmb->getLink(l);
|
||||
|
||||
vec3 bt_origin = bt_link.m_cachedWorldTransform.getOrigin();
|
||||
mat33 bt_basis = bt_link.m_cachedWorldTransform.getBasis();
|
||||
if (verbose)
|
||||
{
|
||||
printf("------------- link %d\n", l + 1);
|
||||
printf("bt:com: %f %f %f\n", bt_origin(0), bt_origin(1), bt_origin(2));
|
||||
printf(
|
||||
"bt:transform: %f %f %f\n"
|
||||
" %f %f %f\n"
|
||||
" %f %f %f\n",
|
||||
bt_basis(0, 0), bt_basis(0, 1), bt_basis(0, 2), bt_basis(1, 0), bt_basis(1, 1),
|
||||
bt_basis(1, 2), bt_basis(2, 0), bt_basis(2, 1), bt_basis(2, 2));
|
||||
}
|
||||
mat33 id_world_T_body;
|
||||
vec3 id_world_com;
|
||||
|
||||
if (-1 == id_tree->getBodyTransform(l + 1, &id_world_T_body))
|
||||
{
|
||||
bt_id_error_message("getting transform for body %d\n", l);
|
||||
return -1;
|
||||
}
|
||||
if (-1 == id_tree->getBodyCoM(l + 1, &id_world_com))
|
||||
{
|
||||
bt_id_error_message("getting com for body %d\n", l);
|
||||
return -1;
|
||||
}
|
||||
if (verbose)
|
||||
{
|
||||
printf("id:com: %f %f %f\n", id_world_com(0), id_world_com(1), id_world_com(2));
|
||||
|
||||
printf(
|
||||
"id:transform: %f %f %f\n"
|
||||
" %f %f %f\n"
|
||||
" %f %f %f\n",
|
||||
id_world_T_body(0, 0), id_world_T_body(0, 1), id_world_T_body(0, 2),
|
||||
id_world_T_body(1, 0), id_world_T_body(1, 1), id_world_T_body(1, 2),
|
||||
id_world_T_body(2, 0), id_world_T_body(2, 1), id_world_T_body(2, 2));
|
||||
}
|
||||
vec3 diff_com = bt_origin - id_world_com;
|
||||
mat33 diff_basis = bt_basis - id_world_T_body;
|
||||
if (verbose)
|
||||
{
|
||||
printf("diff-com: %e %e %e\n", diff_com(0), diff_com(1), diff_com(2));
|
||||
|
||||
printf("diff-transform: %e %e %e %e %e %e %e %e %e\n", diff_basis(0, 0),
|
||||
diff_basis(0, 1), diff_basis(0, 2), diff_basis(1, 0), diff_basis(1, 1),
|
||||
diff_basis(1, 2), diff_basis(2, 0), diff_basis(2, 1), diff_basis(2, 2));
|
||||
}
|
||||
double total_pos_err =
|
||||
BT_ID_SQRT(BT_ID_POW(diff_com(0), 2) + BT_ID_POW(diff_com(1), 2) +
|
||||
BT_ID_POW(diff_com(2), 2) + BT_ID_POW(diff_basis(0, 0), 2) +
|
||||
BT_ID_POW(diff_basis(0, 1), 2) + BT_ID_POW(diff_basis(0, 2), 2) +
|
||||
BT_ID_POW(diff_basis(1, 0), 2) + BT_ID_POW(diff_basis(1, 1), 2) +
|
||||
BT_ID_POW(diff_basis(1, 2), 2) + BT_ID_POW(diff_basis(2, 0), 2) +
|
||||
BT_ID_POW(diff_basis(2, 1), 2) + BT_ID_POW(diff_basis(2, 2), 2));
|
||||
if (verbose)
|
||||
{
|
||||
printf("======kin-pos-err: %e\n", total_pos_err);
|
||||
}
|
||||
if (total_pos_err > *pos_error)
|
||||
{
|
||||
*pos_error = total_pos_err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace btInverseDynamics
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef INVDYN_BULLET_COMPARISON_HPP
|
||||
#define INVDYN_BULLET_COMPARISON_HPP
|
||||
|
||||
#include "BulletInverseDynamics/IDConfig.hpp"
|
||||
|
||||
class btMultiBody;
|
||||
class btVector3;
|
||||
|
||||
namespace btInverseDynamics
|
||||
{
|
||||
class MultiBodyTree;
|
||||
|
||||
/// this function compares the forward dynamics computations implemented in btMultiBody to
|
||||
/// the inverse dynamics implementation in MultiBodyTree. This is done in three steps
|
||||
/// 1. run inverse dynamics for (q, u, dot_u) to obtain joint forces f
|
||||
/// 2. run forward dynamics (btMultiBody) for (q,u,f) to obtain dot_u_bullet
|
||||
/// 3. compare dot_u with dot_u_bullet for cross check of forward and inverse dynamics computations
|
||||
/// @param btmb the bullet forward dynamics model
|
||||
/// @param id_tree the inverse dynamics model
|
||||
/// @param q vector of generalized coordinates (matches id_tree)
|
||||
/// @param u vector of generalized speeds (matches id_tree)
|
||||
/// @param gravity gravitational acceleration in world frame
|
||||
/// @param dot_u vector of generalized accelerations (matches id_tree)
|
||||
/// @param gravity gravitational acceleration in world frame
|
||||
/// @param base_fixed set base joint to fixed or
|
||||
/// @param pos_error is set to the maximum of the euclidean norm of position+rotation errors of all
|
||||
/// center of gravity positions and link frames
|
||||
/// @param acc_error is set to the square root of the sum of squared differences of generalized
|
||||
/// accelerations
|
||||
/// computed in step 3 relative to dot_u
|
||||
/// @return -1 on error, 0 on success
|
||||
int compareInverseAndForwardDynamics(vecx &q, vecx &u, vecx &dot_u, btVector3 &gravity, bool verbose,
|
||||
btMultiBody *btmb, MultiBodyTree *id_tree, double *pos_error,
|
||||
double *acc_error);
|
||||
} // namespace btInverseDynamics
|
||||
#endif // INVDYN_BULLET_COMPARISON_HPP
|
||||
15
Engine/lib/bullet/Extras/InverseDynamics/premake4.lua
Normal file
15
Engine/lib/bullet/Extras/InverseDynamics/premake4.lua
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
project "BulletInverseDynamicsUtils"
|
||||
|
||||
kind "StaticLib"
|
||||
|
||||
includedirs {
|
||||
"../../src"
|
||||
}
|
||||
|
||||
if os.is("Linux") then
|
||||
buildoptions{"-fPIC"}
|
||||
end
|
||||
files {
|
||||
"*.cpp",
|
||||
"*.hpp"
|
||||
}
|
||||
95
Engine/lib/bullet/Extras/Makefile.am
Normal file
95
Engine/lib/bullet/Extras/Makefile.am
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
noinst_LIBRARIES = libgimpactutils.a libconvexdecomposition.a libHACD.a libglui.a
|
||||
|
||||
libglui_a_CXXFLAGS = ${CXXFLAGS} -Iglui
|
||||
libglui_a_SOURCES =\
|
||||
glui/glui_spinner.cpp\
|
||||
glui/glui_treepanel.cpp\
|
||||
glui/arcball.cpp\
|
||||
glui/glui_scrollbar.cpp\
|
||||
glui/glui_filebrowser.cpp\
|
||||
glui/glui_node.cpp\
|
||||
glui/glui_edittext.cpp\
|
||||
glui/glui_statictext.cpp\
|
||||
glui/glui_bitmaps.cpp\
|
||||
glui/algebra3.cpp\
|
||||
glui/glui_string.cpp\
|
||||
glui/glui_button.cpp\
|
||||
glui/glui_add_controls.cpp\
|
||||
glui/glui_control.cpp\
|
||||
glui/glui.cpp\
|
||||
glui/glui_listbox.cpp\
|
||||
glui/glui_checkbox.cpp\
|
||||
glui/glui_commandline.cpp\
|
||||
glui/glui_textbox.cpp\
|
||||
glui/glui_column.cpp\
|
||||
glui/glui_mouse_iaction.cpp\
|
||||
glui/glui_radio.cpp\
|
||||
glui/glui_translation.cpp\
|
||||
glui/glui_tree.cpp\
|
||||
glui/glui_rotation.cpp\
|
||||
glui/glui_panel.cpp\
|
||||
glui/glui_rollout.cpp\
|
||||
glui/glui_separator.cpp\
|
||||
glui/glui_bitmap_img_data.cpp\
|
||||
glui/quaternion.cpp\
|
||||
glui/glui_window.cpp\
|
||||
glui/glui_list.cpp\
|
||||
glui/GL/glui.h\
|
||||
glui/quaternion.h\
|
||||
glui/glui_internal.h\
|
||||
glui/glui_internal_control.h\
|
||||
glui/arcball.h\
|
||||
glui/algebra3.h
|
||||
|
||||
libconvexdecomposition_a_CXXFLAGS = ${CXXFLAGS} -IConvexDecomposition/ -I../src
|
||||
libconvexdecomposition_a_SOURCES =\
|
||||
ConvexDecomposition/concavity.cpp\
|
||||
ConvexDecomposition/ConvexDecomposition.cpp\
|
||||
ConvexDecomposition/vlookup.cpp\
|
||||
ConvexDecomposition/bestfit.cpp\
|
||||
ConvexDecomposition/ConvexBuilder.cpp\
|
||||
ConvexDecomposition/cd_hull.cpp\
|
||||
ConvexDecomposition/raytri.cpp\
|
||||
ConvexDecomposition/splitplane.cpp\
|
||||
ConvexDecomposition/float_math.cpp\
|
||||
ConvexDecomposition/planetri.cpp\
|
||||
ConvexDecomposition/cd_wavefront.cpp\
|
||||
ConvexDecomposition/bestfitobb.cpp\
|
||||
ConvexDecomposition/meshvolume.cpp\
|
||||
ConvexDecomposition/fitsphere.cpp\
|
||||
ConvexDecomposition/fitsphere.h\
|
||||
ConvexDecomposition/vlookup.h\
|
||||
ConvexDecomposition/concavity.h\
|
||||
ConvexDecomposition/ConvexDecomposition.h\
|
||||
ConvexDecomposition/bestfit.h\
|
||||
ConvexDecomposition/cd_vector.h\
|
||||
ConvexDecomposition/ConvexBuilder.h\
|
||||
ConvexDecomposition/cd_hull.h\
|
||||
ConvexDecomposition/raytri.h\
|
||||
ConvexDecomposition/splitplane.h\
|
||||
ConvexDecomposition/float_math.h\
|
||||
ConvexDecomposition/planetri.h\
|
||||
ConvexDecomposition/cd_wavefront.h\
|
||||
ConvexDecomposition/bestfitobb.h\
|
||||
ConvexDecomposition/meshvolume.h
|
||||
|
||||
libHACD_a_CXXFLAGS = ${CXXFLAGS} -IHACD/ -I../src
|
||||
libHACD_a_SOURCES =\
|
||||
HACD/hacdGraph.cpp\
|
||||
HACD/hacdHACD.cpp\
|
||||
HACD/hacdICHull.cpp\
|
||||
HACD/hacdManifoldMesh.cpp\
|
||||
HACD/hacdCircularList.h\
|
||||
HACD/hacdGraph.h\
|
||||
HACD/hacdHACD.h\
|
||||
HACD/hacdICHull.h\
|
||||
HACD/hacdManifoldMesh.h\
|
||||
HACD/hacdVector.h\
|
||||
HACD/hacdVersion.h\
|
||||
HACD/hacdCircularList.inl\
|
||||
HACD/hacdVector.inl
|
||||
|
||||
|
||||
libgimpactutils_a_CXXFLAGS = ${CXXFLAGS} -I../src -IGIMPACTUtils -IConvexDecomposition
|
||||
libgimpactutils_a_SOURCES = GIMPACTUtils/btGImpactConvexDecompositionShape.cpp GIMPACTUtils/btGImpactConvexDecompositionShape.h
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BulletFileLoader
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/Extras/Serialize/BlenderSerialize
|
||||
)
|
||||
|
||||
ADD_LIBRARY(BlenderSerialize dna249.cpp dna249-64bit.cpp bBlenderFile.cpp bBlenderFile.h bMain.cpp bMain.h )
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "bBlenderFile.h"
|
||||
#include "bMain.h"
|
||||
#include "bDefines.h"
|
||||
#include "bDNA.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// 32 && 64 bit versions
|
||||
extern unsigned char DNAstr[];
|
||||
extern int DNAlen;
|
||||
|
||||
extern unsigned char DNAstr64[];
|
||||
extern int DNAlen64;
|
||||
|
||||
using namespace bParse;
|
||||
|
||||
bBlenderFile::bBlenderFile(const char *fileName)
|
||||
: bFile(fileName, "BLENDER")
|
||||
{
|
||||
mMain = new bMain(this, fileName, mVersion);
|
||||
}
|
||||
|
||||
bBlenderFile::bBlenderFile(char *memoryBuffer, int len)
|
||||
: bFile(memoryBuffer, len, "BLENDER"),
|
||||
mMain(0)
|
||||
{
|
||||
mMain = new bMain(this, "memoryBuf", mVersion);
|
||||
}
|
||||
|
||||
bBlenderFile::~bBlenderFile()
|
||||
{
|
||||
delete mMain;
|
||||
}
|
||||
|
||||
bMain *bBlenderFile::getMain()
|
||||
{
|
||||
return mMain;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
void bBlenderFile::parseData()
|
||||
{
|
||||
// printf ("Building datablocks\n");
|
||||
// printf ("Chunk size = %d\n",CHUNK_HEADER_LEN);
|
||||
// printf ("File chunk size = %d\n", ChunkUtils::getOffset(mFlags));
|
||||
|
||||
const bool swap = (mFlags & FD_ENDIAN_SWAP) != 0;
|
||||
|
||||
char *dataPtr = mFileBuffer + mDataStart;
|
||||
|
||||
bChunkInd dataChunk;
|
||||
dataChunk.code = 0;
|
||||
|
||||
//dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags);
|
||||
int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
|
||||
//dataPtr += ChunkUtils::getOffset(mFlags);
|
||||
char *dataPtrHead = 0;
|
||||
|
||||
while (dataChunk.code != DNA1)
|
||||
{
|
||||
// one behind
|
||||
if (dataChunk.code == SDNA) break;
|
||||
//if (dataChunk.code == DNA1) break;
|
||||
|
||||
// same as (BHEAD+DATA dependency)
|
||||
dataPtrHead = dataPtr + ChunkUtils::getOffset(mFlags);
|
||||
char *id = readStruct(dataPtrHead, dataChunk);
|
||||
|
||||
// lookup maps
|
||||
if (id)
|
||||
{
|
||||
m_chunkPtrPtrMap.insert(dataChunk.oldPtr, dataChunk);
|
||||
mLibPointers.insert(dataChunk.oldPtr, (bStructHandle *)id);
|
||||
|
||||
m_chunks.push_back(dataChunk);
|
||||
// block it
|
||||
bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code);
|
||||
if (listID)
|
||||
listID->push_back((bStructHandle *)id);
|
||||
}
|
||||
|
||||
if (dataChunk.code == GLOB)
|
||||
{
|
||||
m_glob = (bStructHandle *)id;
|
||||
}
|
||||
|
||||
// next please!
|
||||
dataPtr += seek;
|
||||
|
||||
seek = getNextBlock(&dataChunk, dataPtr, mFlags);
|
||||
if (seek < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void bBlenderFile::addDataBlock(char *dataBlock)
|
||||
{
|
||||
mMain->addDatablock(dataBlock);
|
||||
}
|
||||
|
||||
// 32 && 64 bit versions
|
||||
extern unsigned char DNAstr[];
|
||||
extern int DNAlen;
|
||||
|
||||
//unsigned char DNAstr[]={0};
|
||||
//int DNAlen=0;
|
||||
|
||||
extern unsigned char DNAstr64[];
|
||||
extern int DNAlen64;
|
||||
|
||||
void bBlenderFile::writeDNA(FILE *fp)
|
||||
{
|
||||
bChunkInd dataChunk;
|
||||
dataChunk.code = DNA1;
|
||||
dataChunk.dna_nr = 0;
|
||||
dataChunk.nr = 1;
|
||||
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
dataChunk.len = DNAlen64;
|
||||
dataChunk.oldPtr = DNAstr64;
|
||||
fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
|
||||
fwrite(DNAstr64, DNAlen64, 1, fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataChunk.len = DNAlen;
|
||||
dataChunk.oldPtr = DNAstr;
|
||||
fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
|
||||
fwrite(DNAstr, DNAlen, 1, fp);
|
||||
}
|
||||
}
|
||||
|
||||
void bBlenderFile::parse(int verboseMode)
|
||||
{
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
parseInternal(verboseMode, (char *)DNAstr64, DNAlen64);
|
||||
}
|
||||
else
|
||||
{
|
||||
parseInternal(verboseMode, (char *)DNAstr, DNAlen);
|
||||
}
|
||||
}
|
||||
|
||||
// experimental
|
||||
int bBlenderFile::write(const char *fileName, bool fixupPointers)
|
||||
{
|
||||
FILE *fp = fopen(fileName, "wb");
|
||||
if (fp)
|
||||
{
|
||||
char header[SIZEOFBLENDERHEADER];
|
||||
memcpy(header, m_headerString, 7);
|
||||
int endian = 1;
|
||||
endian = ((char *)&endian)[0];
|
||||
|
||||
if (endian)
|
||||
{
|
||||
header[7] = '_';
|
||||
}
|
||||
else
|
||||
{
|
||||
header[7] = '-';
|
||||
}
|
||||
if (VOID_IS_8)
|
||||
{
|
||||
header[8] = 'V';
|
||||
}
|
||||
else
|
||||
{
|
||||
header[8] = 'v';
|
||||
}
|
||||
|
||||
header[9] = '2';
|
||||
header[10] = '4';
|
||||
header[11] = '9';
|
||||
|
||||
fwrite(header, SIZEOFBLENDERHEADER, 1, fp);
|
||||
|
||||
writeChunks(fp, fixupPointers);
|
||||
|
||||
writeDNA(fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: cannot open file %s for writing\n", fileName);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef B_BLENDER_FILE_H
|
||||
#define B_BLENDER_FILE_H
|
||||
|
||||
#include "bFile.h"
|
||||
|
||||
namespace bParse
|
||||
{
|
||||
// ----------------------------------------------------- //
|
||||
class bBlenderFile : public bFile
|
||||
{
|
||||
protected:
|
||||
bMain* mMain;
|
||||
|
||||
bStructHandle* m_glob;
|
||||
|
||||
public:
|
||||
bBlenderFile(const char* fileName);
|
||||
|
||||
bBlenderFile(char* memoryBuffer, int len);
|
||||
|
||||
virtual ~bBlenderFile();
|
||||
|
||||
bMain* getMain();
|
||||
|
||||
virtual void addDataBlock(char* dataBlock);
|
||||
|
||||
bStructHandle* getFileGlobal()
|
||||
{
|
||||
return m_glob;
|
||||
}
|
||||
|
||||
// experimental
|
||||
virtual int write(const char* fileName, bool fixupPointers = false);
|
||||
|
||||
virtual void parse(int verboseMode);
|
||||
|
||||
virtual void parseData();
|
||||
|
||||
virtual void writeDNA(FILE* fp);
|
||||
};
|
||||
}; // namespace bParse
|
||||
|
||||
#endif //B_BLENDER_FILE_H
|
||||
376
Engine/lib/bullet/Extras/Serialize/BlenderSerialize/bMain.cpp
Normal file
376
Engine/lib/bullet/Extras/Serialize/BlenderSerialize/bMain.cpp
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
/*
|
||||
bParse
|
||||
Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "bMain.h"
|
||||
#include "bBlenderFile.h"
|
||||
#include "bDefines.h"
|
||||
#include "bChunk.h"
|
||||
#include "bDNA.h"
|
||||
|
||||
using namespace bParse;
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
bMain::bMain(bBlenderFile *filePtr, const char *baseName, int fileVersion)
|
||||
: mFP(filePtr),
|
||||
mVersion(fileVersion),
|
||||
mName(baseName)
|
||||
{
|
||||
mData.insert(ID_SCE, bListBasePtr());
|
||||
mData.insert(ID_LI, bListBasePtr());
|
||||
mData.insert(ID_OB, bListBasePtr());
|
||||
mData.insert(ID_ME, bListBasePtr());
|
||||
mData.insert(ID_CU, bListBasePtr());
|
||||
mData.insert(ID_MB, bListBasePtr());
|
||||
mData.insert(ID_MA, bListBasePtr());
|
||||
mData.insert(ID_TE, bListBasePtr());
|
||||
mData.insert(ID_IM, bListBasePtr());
|
||||
mData.insert(ID_WV, bListBasePtr());
|
||||
mData.insert(ID_LT, bListBasePtr());
|
||||
mData.insert(ID_LA, bListBasePtr());
|
||||
mData.insert(ID_CA, bListBasePtr());
|
||||
mData.insert(ID_IP, bListBasePtr());
|
||||
mData.insert(ID_KE, bListBasePtr());
|
||||
mData.insert(ID_WO, bListBasePtr());
|
||||
mData.insert(ID_SCR, bListBasePtr());
|
||||
mData.insert(ID_VF, bListBasePtr());
|
||||
mData.insert(ID_TXT, bListBasePtr());
|
||||
mData.insert(ID_SO, bListBasePtr());
|
||||
mData.insert(ID_GR, bListBasePtr());
|
||||
mData.insert(ID_AR, bListBasePtr());
|
||||
mData.insert(ID_AC, bListBasePtr());
|
||||
mData.insert(ID_NT, bListBasePtr());
|
||||
mData.insert(ID_BR, bListBasePtr());
|
||||
mData.insert(ID_SCRIPT, bListBasePtr());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
bMain::~bMain()
|
||||
{
|
||||
// allocated data blocks!
|
||||
|
||||
int sz = mPool.size();
|
||||
for (int i = 0; i < sz; i++)
|
||||
{
|
||||
delete[] mPool[i];
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
int bMain::getVersion()
|
||||
{
|
||||
return mVersion;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
const char *bMain::getName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- //
|
||||
void bMain::addDatablock(void *allocated)
|
||||
{
|
||||
assert(allocated);
|
||||
mPool.push_back((bStructHandle *)allocated);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
void bMain::linkList(void *listBasePtr)
|
||||
{
|
||||
struct ListBase // local Blender::ListBase
|
||||
{
|
||||
void *first;
|
||||
void *last;
|
||||
};
|
||||
|
||||
struct Link // local Blender::Link
|
||||
{
|
||||
void *next;
|
||||
void *prev;
|
||||
};
|
||||
|
||||
ListBase *base = (ListBase *)listBasePtr;
|
||||
|
||||
if (!base || !base->first)
|
||||
return;
|
||||
|
||||
base->first = mFP->findLibPointer(base->first);
|
||||
if (!base->first)
|
||||
{
|
||||
base->last = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
void *prev = 0;
|
||||
Link *l = (Link *)base->first;
|
||||
while (l)
|
||||
{
|
||||
l->next = mFP->findLibPointer(l->next);
|
||||
l->prev = l->next;
|
||||
prev = l->next;
|
||||
l = (Link *)l->next;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getListBasePtr(int listBaseCode)
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(listBaseCode);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::_findCode(int code)
|
||||
{
|
||||
bListBasePtr *lbPtr = mData.find(code);
|
||||
return lbPtr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getScene()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_SCE);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getLibrary()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_LI);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getObject()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_OB);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getMesh()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_ME);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getCurve()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_CU);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getMball()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_MB);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getMat()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_MA);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getTex()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_TE);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getImage()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_IM);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getWave()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_WV);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getLatt()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_LT);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getLamp()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_LA);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getCamera()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_CA);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getIpo()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_IP);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getKey()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_KE);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getWorld()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_WO);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getScreen()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_SCR);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getScript()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_SCRIPT);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getVfont()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_VF);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getText()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_TXT);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getSound()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_SO);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getGroup()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_GR);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getArmature()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_AR);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getAction()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_AC);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getNodetree()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_NT);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------//
|
||||
bListBasePtr *bMain::getBrush()
|
||||
{
|
||||
bListBasePtr *ptr = _findCode(ID_BR);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
//eof
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue