Merge branch 'develop'

This commit is contained in:
Daniel Chappuis 2022-01-01 15:08:39 +01:00
commit 325bf56155
303 changed files with 139210 additions and 35964 deletions

View File

@ -1,3 +1,4 @@
ignore:
- "usr/"
- "test/"
- "**/CMakeFiles/**/*"

312
.github/workflows/build-and-test.yml vendored Normal file
View File

@ -0,0 +1,312 @@
# Build and run tests for ReactPhysics3D
name: build
# Controls when the action will run. Triggers the workflow on push
on:
push:
branches:
- master
- develop
pull_request:
release:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- {
name: "Linux / GCC (Debug, Single Precision)",
os: ubuntu-latest,
build_type: "Debug",
cc: "gcc",
cxx: "g++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: false,
coverage: false,
}
- {
name: "Linux / GCC (Release, Single Precision)",
os: ubuntu-latest,
build_type: "Release",
cc: "gcc",
cxx: "g++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: false,
coverage: false,
}
- {
name: "Linux / GCC (Debug, Double Precision)",
os: ubuntu-latest,
build_type: "Debug",
cc: "gcc",
cxx: "g++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: true,
coverage: false,
}
- {
name: "Linux / GCC (Release, Double Precision)",
os: ubuntu-latest,
build_type: "Release",
cc: "gcc",
cxx: "g++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: true,
coverage: false,
}
- {
name: "Linux / Clang (Debug, Single Precision)",
os: ubuntu-latest,
build_type: "Debug",
cc: "clang",
cxx: "clang++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: false,
coverage: false,
}
- {
name: "Linux / Clang (Release, Single Precision)",
os: ubuntu-latest,
build_type: "Release",
cc: "clang",
cxx: "clang++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: false,
coverage: false,
}
- {
name: "Linux / Clang (Debug, Double Precision)",
os: ubuntu-latest,
build_type: "Debug",
cc: "clang",
cxx: "clang++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: true,
coverage: false,
}
- {
name: "Linux / Clang (Release, Double Precision)",
os: ubuntu-latest,
build_type: "Release",
cc: "clang",
cxx: "clang++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: true,
coverage: false,
}
- {
name: "Windows / MSVC (Debug, Single Precision)",
os: windows-latest,
build_type: "Debug",
cc: "cl",
cxx: "cl",
cxx_flags: "",
generators: "Visual Studio 16 2019",
double_precision: false,
coverage: false,
}
- {
name: "Windows / MSVC (Release, Single Precision)",
os: windows-latest,
build_type: "Release",
cc: "cl",
cxx: "cl",
cxx_flags: "",
generators: "Visual Studio 16 2019",
double_precision: false,
coverage: false,
}
- {
name: "Windows / MinGW (Debug, Single Precision)",
os: windows-latest,
build_type: "Debug",
cc: "gcc",
cxx: "g++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: false,
coverage: false,
}
- {
name: "Windows / MinGW (Release, Single Precision)",
os: windows-latest,
build_type: "Release",
cc: "gcc",
cxx: "g++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: false,
coverage: false,
}
- {
name: "MacOS / Clang (Debug, Single Precision)",
os: macos-latest,
build_type: "Debug",
cc: "clang",
cxx: "clang++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: false,
coverage: false,
}
- {
name: "MacOS / Clang (Release, Single Precision)",
os: macos-latest,
build_type: "Release",
cc: "clang",
cxx: "clang++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: false,
coverage: false,
}
- {
name: "Code Coverage",
os: ubuntu-latest,
build_type: "Debug",
cc: "gcc",
cxx: "g++",
cxx_flags: "-Wall -Wextra -pedantic",
generators: "Ninja",
double_precision: false,
coverage: true,
}
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- name: Print env
run: |
echo github.event.action: ${{ github.event.action }}
echo github.event_name: ${{ github.event_name }}
- name: Install dependencies on Windows
if: startsWith(matrix.config.os, 'windows')
run: |
choco install ninja cmake
ninja --version
cmake --version
- name: Install dependencies on Linux
if: startsWith(matrix.config.os, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install ninja-build cmake lcov valgrind
ninja --version
cmake --version
gcc --version
clang --version
- name: Install dependencies on MacOS
if: startsWith(matrix.config.os, 'macos')
run: |
brew install cmake ninja
ninja --version
cmake --version
- name: CMake Configure
shell: bash
env:
CC: ${{ matrix.config.cc }}
CXX: ${{ matrix.config.cxx }}
run: |
mkdir build
cmake \
-S . \
-B build \
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
-DRP3D_DOUBLE_PRECISION_ENABLED=${{ matrix.config.double_precision }} \
-DRP3D_CODE_COVERAGE_ENABLED=${{ matrix.config.coverage }} \
-DCODE_COVERAGE_VERBOSE=True \
-DRP3D_COMPILE_TESTS=True \
-DCMAKE_CXX_FLAGS="${{ matrix.config.cxx_flags }}" \
-G "${{ matrix.config.generators }}" \
- name: Build
shell: bash
run: cmake --build build/ --config ${{ matrix.config.build_type }}
- name: Install Library on Linux/MacOS
if: ${{ !startsWith(matrix.config.os, 'windows') }}
shell: bash
run: sudo cmake --install build/ --config ${{ matrix.config.build_type }}
- name: Install Library on Windows
if: startsWith(matrix.config.os, 'windows')
shell: bash
run: cmake --install build/ --config ${{ matrix.config.build_type }}
- name: Run Unit Tests (Linux / MacOS / Windows MinGW)
if: ${{ !startsWith(matrix.config.os, 'windows') }}
shell: bash
run: ./build/test/tests
- name: Run Unit Tests (Windows MSVC)
if: ${{ startsWith(matrix.config.name, 'Windows / MSVC') }}
shell: bash
run: "./build/test/${{ matrix.config.build_type }}/tests.exe"
- name: Build Hello World
if: ${{ !matrix.config.coverage }}
shell: bash
env:
CC: ${{ matrix.config.cc }}
CXX: ${{ matrix.config.cxx }}
run: |
mkdir build_hello_world
cmake \
-S helloworld \
-B build_hello_world \
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
-DCMAKE_EXE_LINKER_FLAGS=-no-pie \
-DCMAKE_CXX_FLAGS="${{ matrix.config.cxx_flags }}" \
-G "${{ matrix.config.generators }}"
cmake --build build_hello_world/ --config ${{ matrix.config.build_type }}
- name: Run Hello World (Linux / MacOS / Windows MinGW)
if: ${{ !startsWith(matrix.config.name, 'Windows / MSVC') && !matrix.config.coverage }}
shell: bash
run: "./build_hello_world/helloworld"
- name: Run Hello World (Windows MSVC)
if: ${{ startsWith(matrix.config.name, 'Windows / MSVC') }}
shell: bash
run: "./build_hello_world/${{ matrix.config.build_type }}/helloworld.exe"
- name: Memory Leaks Test
if: ${{ startsWith(matrix.config.name, 'Linux / GCC (Debug, Single Precision)') }}
shell: bash
run: valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --error-exitcode=1 ./build/test/tests
- name: Compute Code Coverage
if: ${{ matrix.config.coverage }}
env:
CC: ${{ matrix.config.cc }}
CXX: ${{ matrix.config.cxx }}
shell: bash
run: |
cmake --build build/ --target coverage
- name: Upload coverage to Codecov
if: ${{ matrix.config.coverage }}
uses: codecov/codecov-action@v2
with:
fail_ci_if_error: true
verbose: false

1
.gitmodules vendored
View File

@ -1,3 +1,4 @@
[submodule "testbed/extern/nanogui"]
path = testbed/extern/nanogui
url = https://github.com/mitsuba-renderer/nanogui.git
ignore = dirty

View File

@ -1,274 +0,0 @@
language: cpp
install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install valgrind; fi
matrix:
# ----- Linux / GCC -----
include:
- os: linux
name: "Linux / GCC (Debug)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Debug" DOUBLE_PRECISION="False"
- os: linux
name: "Linux / GCC (Release)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Release" DOUBLE_PRECISION="False"
- os: linux
name: "Linux / GCC (Debug, Double Precision)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Debug" DOUBLE_PRECISION="True"
- os: linux
name: "Linux / GCC (Release, Double Precision)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Release" DOUBLE_PRECISION="True"
- os: linux
name: "Linux / GCC (Debug, Profiler)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Debug" DOUBLE_PRECISION="False" Profiler="True"
- os: linux
name: "Linux / GCC (Release, Profiler)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Release" DOUBLE_PRECISION="False" Profiler="True"
- os: linux
name: "Linux / GCC (Debug, Code Coverage)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
- lcov
env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Debug" DOUBLE_PRECISION="False" CODE_COVERAGE="True"
- os: linux
name: "Linux / GCC (Debug, Valgrind)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
- valgrind
env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Debug" DOUBLE_PRECISION="False" VALGRIND="True"
# ----- OS X / GCC -----
- os: osx
name: "OS X / GCC (Debug)"
osx_image: xcode11
env:
- MATRIX_EVAL="brew install gcc@8 && CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Debug" DOUBLE_PRECISION="False"
- os: osx
name: "OS X / GCC (Release)"
osx_image: xcode11
env:
- MATRIX_EVAL="brew install gcc@8 && CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Release" DOUBLE_PRECISION="False"
- os: osx
name: "OS X / GCC (Debug, Double Precision)"
osx_image: xcode11
env:
- MATRIX_EVAL="brew install gcc@8 && CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Debug" DOUBLE_PRECISION="True"
- os: osx
name: "OS X / GCC (Release, Double Precision)"
osx_image: xcode11
env:
- MATRIX_EVAL="brew install gcc@8 && CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Release" DOUBLE_PRECISION="True"
- os: osx
name: "OS X / GCC (Debug, Profiler)"
osx_image: xcode11
env:
- MATRIX_EVAL="brew install gcc@8 && CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Debug" DOUBLE_PRECISION="False" PROFILER="True"
- os: osx
name: "OS X / GCC (Release, Profiler)"
osx_image: xcode11
env:
- MATRIX_EVAL="brew install gcc@8 && CC=gcc-8 && CXX=g++-8" BUILD_TYPE="Release" DOUBLE_PRECISION="False" PROFILER="True"
# ----- Linux / Clang -----
- os: linux
name: "Linux / Clang (Debug)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
packages:
- clang-3.8
- g++-7
env:
- MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" BUILD_TYPE="Debug" DOUBLE_PRECISION="False"
- os: linux
name: "Linux / Clang (Release)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
packages:
- clang-3.8
- g++-7
env:
- MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" BUILD_TYPE="Release" DOUBLE_PRECISION="False"
- os: linux
name: "Linux / Clang (Debug, Double Precision)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
packages:
- clang-3.8
- g++-7
env:
- MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" BUILD_TYPE="Debug" DOUBLE_PRECISION="True"
- os: linux
name: "Linux / Clang (Release, Double Precision)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
packages:
- clang-3.8
- g++-7
env:
- MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" BUILD_TYPE="Release" DOUBLE_PRECISION="True"
- os: linux
name: "Linux / Clang (Debug, Double Precision, Profiler)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
packages:
- clang-3.8
- g++-7
env:
- MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" BUILD_TYPE="Debug" DOUBLE_PRECISION="True" PROFILER="True"
- os: linux
name: "Linux / Clang (Release, Double Precision, Profiler)"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
packages:
- clang-3.8
- g++-7
env:
- MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" BUILD_TYPE="Release" DOUBLE_PRECISION="True" PROFILER="True"
# ----- OS X / Clang -----
- os: osx
name: "OS X / Clang (Debug)"
osx_image: xcode11
env:
- BUILD_TYPE="Debug" DOUBLE_PRECISION="False"
- os: osx
name: "OS X / Clang (Release)"
osx_image: xcode11
env:
- BUILD_TYPE="Release" DOUBLE_PRECISION="False"
- os: osx
name: "OS X / Clang (Debug, Double Precision)"
osx_image: xcode11
env:
- BUILD_TYPE="Debug" DOUBLE_PRECISION="True"
- os: osx
name: "OS X / Clang (Release, Double Precision)"
osx_image: xcode11
env:
- BUILD_TYPE="Release" DOUBLE_PRECISION="True"
- os: osx
name: "OS X / Clang (Debug, Profiler)"
osx_image: xcode11
env:
- BUILD_TYPE="Debug" DOUBLE_PRECISION="False" PROFILER="True"
- os: osx
name: "OS X / Clang (Release, Profiler)"
osx_image: xcode11
env:
- BUILD_TYPE="Release" DOUBLE_PRECISION="False" PROFILER="True"
before_install:
- eval "${MATRIX_EVAL}"
branches:
only:
- master
- develop
script:
- mkdir build_rp3d
- cd build_rp3d
- cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} —DRP3D_DOUBLE_PRECISION_ENABLED=${DOUBLE_PRECISION} -DRP3D_COMPILE_TESTS=True -DRP3D_PROFILING_ENABLED=${PROFILER} -DRP3D_CODE_COVERAGE_ENABLED=${CODE_COVERAGE} ../
- make -j2 && make test ARGS="-V"
- if [ "${VALGRIND}" == "True" ]; then
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --error-exitcode=1 test/tests;
fi
- if [ "${CODE_COVERAGE}" == "False" ]; then
sudo make install;
cd ../;
mkdir build_helloworld;
cd build_helloworld;
cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} ../helloworld/;
make -j2;
fi
after_success:
# Generate code coverage report
- if [ "${CODE_COVERAGE}" == "True" ]; then
bash <(curl -s https://codecov.io/bash) || echo "Codecov did not collect coverage reports";
fi

View File

@ -1,5 +1,76 @@
# Changelog
## Release candidate
Note that this release contains some public API changes. Please read carefully the following changes before upgrading to this new version and
do not hesitate to take a look at the user manual.
### Added
- The performance of the collision detection and rigid bodies simulation has been improved a lot
- Method RigidBody::resetForce() to reset the accumulated external force on a rigid body has been added
- Method RigidBody::resetTorque() to reset the accumulated external torque on a rigid body has been added
- Constructors with local-space anchor/axis have been added to BallAndSocketJointInfo, HingeJointInfo, FixedJointInfo and SliderJointInfo classes
- Method HingeJoint::getAngle() to get the current angle of the hinge joint has been added
- Method Joint::getReactionForce() has been added to retrieve the current reaction force of a joint
- Method Joint::getReactionTorque() has been added to retrieve the current reaction torque of a joint
- Method RigidBody::setLinearLockAxisFactor() to lock the translational movement of a body along the world-space x, y and z axes
- Method RigidBody::setAngularLockAxisFactor() to lock the rotational movement of a body around the world-space x, y and z axes
- Method RigidBody::applyLocalForceAtWorldPosition() to manually apply a force to a rigid body
- Method RigidBody::applyLocalForceAtLocalPosition() to manually apply a force to a rigid body
- Method RigidBody::applyLocalForceToCenterOfMass() to manually apply a force to a rigid body
- Method RigidBody::applyLocalTorque() to apply a local-space torque to a rigid body
- Method RigidBody::getForce() to get the total manually applied force on a rigid body
- Method RigidBody::getTorque() to get the total manually applied torque on a rigid body
- Method RigidBody::setIsSleeping() is now public in order to wake up or put to sleep a rigid body
- A cone limit can now be set to the ball-and-socket joint (this is useful for ragdolls)
- New scenes have been added to the testbed application (Box Tower, Ragdoll, Rope, Ball And Socket Joint, Bridge, Hinge Joint, Hinge Joint chain, Ball and
Socket Joint chain, Ball and Socket Joint net, ...)
- It is now possible to move bodies using the mouse (CTRL + click and drag) in the testbed application
### Changed
- The PhysicsWorld::setGravity() method now takes a const parameter
- Rolling resistance constraint is not solved anymore in the solver. Angular damping needs to be used instead to simulate it.
- The List class has been renamed to Array
- The default number of iterations for the velocity solver is now 6 instead of 10
- The default number of iterations for the position solver is now 3 instead of 5
- Rename method RigidBody::applyForceAtWorldPosition() into RigidBody::applyWorldForceAtWorldPosition()
- Rename method RigidBody::applyForceAtLocalPosition() into RigidBody::applyWorldForceAtLocalPosition()
- Rename method RigidBody::applyForceToCenterOfMass() into RigidBody::applyWorldForceAtCenterOfMass()
- Rename method RigidBody::applyTorque() into RigidBody::applyWorldTorque()
- The raycasting broad-phase performance has been improved
- The raycasting performance against HeighFieldShape has been improved (better middle-phase algorithm)
- Robustness of polyhedron vs polyhedron collision detection has been improved in SAT algorithm (face contacts are favored over edge-edge contacts for better stability)
### Removed
- Method Material::getRollingResistance() has been removed (angular damping has to be used instead of rolling resistance)
- Method Material::setRollingResistance() has been removed (angular damping has to be used instead of rolling resistance)
### Fixed
- Issue [#165](https://github.com/DanielChappuis/reactphysics3d/issues/165) with order of contact manifolds in islands creation has been fixed
- Issue [#179](https://github.com/DanielChappuis/reactphysics3d/issues/179) with FixedJoint constraint
- Issue [#195](https://github.com/DanielChappuis/reactphysics3d/issues/195) in RigidBodyComponents
- Issue with concave vs convex shape collision detection has been fixed
- Issue with edge vs edge collision has been fixed in SAT algorithm (wrong contact normal was computed)
- Issue with sphere radius in DebugRenderer
- Issue where changing the transform of a Collider attached to a sleeping RigidBody caused the body to remain asleep
- Issue with wrong calculation performed in the ContactSolverSystem
- Issue with joints when center of mass is not at the center of the rigid body local-space
- Issue [#157](https://github.com/DanielChappuis/reactphysics3d/issues/157) with matrix to quaternion conversion has been fixed
- Issue [#184](https://github.com/DanielChappuis/reactphysics3d/issues/184) with update of mass/inertia properties of static bodies
- Issue with the computation of the two friction vectors in the contact solver
- Issue with the rendering of the capsule collision shape in the Debug Renderer (missing triangle faces)
- Issue with wrong linear velocity update computed in RigidBody::setLocalCenterOfMass() method
- Issue with wrong linear velocity update computed in RigidBody::updateLocalCenterOfMassFromColliders() method
- Issue with wrong linear velocity update computed in RigidBody::updateMassPropertiesFromColliders() method
- Issue in copy-constructors in Map and Set classes
- A lot of code warnings have been fixed [#221](https://github.com/DanielChappuis/reactphysics3d/issues/221)[#222](https://github.com/DanielChappuis/reactphysics3d/issues/222)[#223](https://github.com/DanielChappuis/reactphysics3d/issues/223)[#224](https://github.com/DanielChappuis/reactphysics3d/issues/224)
- The default warning level is not set anymore in CMakeLists.txt file (Issue [#220](https://github.com/DanielChappuis/reactphysics3d/issues/220))
- Issue with collision not working when setting a body to be static before calling updateMassPropertiesFromColliders() (Issue [#225](https://github.com/DanielChappuis/reactphysics3d/issues/225))
## Version 0.8.0 (May 31, 2020)
Note that this release contains some public API changes. Please read carefully the following changes before upgrading to this new version and
@ -68,6 +139,7 @@ do not hesitate to take a look at the user manual.
- The RigidBody::recomputeMassInformation() method has been renamed to RigidBody::updateMassPropertiesFromColliders.
- Now, you need to manually call the RigidBody::updateMassPropertiesFromColliders() method after adding colliders to a rigid body to recompute its inertia tensor, center of mass and mass. There are other methods that you can use form that (see the user manual)
- The RigidBody::applyForce() method has been renamed to RigidBody::applyForceAtWorldPosition()
- The linear and angular damping function of the rigid bodies has been changed
- The rendering in the testbed application has been improved
- Many of the data inside the library have been refactored for better caching and easier parallelization in the future
- The old Logger class has been renamed to DefaultLogger

View File

@ -2,7 +2,7 @@
cmake_minimum_required(VERSION 3.8)
# Project configuration
project(ReactPhysics3D VERSION 0.8.0 LANGUAGES CXX)
project(ReactPhysics3D VERSION 0.9.0 LANGUAGES CXX)
# In order to install libraries into correct locations on all platforms.
include(GNUInstallDirs)
@ -31,15 +31,15 @@ option(RP3D_PROFILING_ENABLED "Select this if you want to compile for performana
option(RP3D_CODE_COVERAGE_ENABLED "Select this if you need to build for code coverage calculation" OFF)
option(RP3D_DOUBLE_PRECISION_ENABLED "Select this if you want to compile using double precision floating values" OFF)
# Code Coverage
if(RP3D_CODE_COVERAGE_ENABLED)
if(CMAKE_COMPILER_IS_GNUCXX)
INCLUDE(CodeCoverage)
SETUP_TARGET_FOR_COVERAGE(${PROJECT_NAME}_coverage tests coverage)
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
INCLUDE(CodeCoverage)
SETUP_TARGET_FOR_COVERAGE_LCOV(NAME coverage EXECUTABLE test/tests)
APPEND_COVERAGE_COMPILER_FLAGS()
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
endif()
# Headers filen1s
# Headers files
set (REACTPHYSICS3D_HEADERS
"include/reactphysics3d/configuration.h"
"include/reactphysics3d/decimal.h"
@ -63,9 +63,6 @@ set (REACTPHYSICS3D_HEADERS
"include/reactphysics3d/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.h"
"include/reactphysics3d/collision/narrowphase/NarrowPhaseInput.h"
"include/reactphysics3d/collision/narrowphase/NarrowPhaseInfoBatch.h"
"include/reactphysics3d/collision/narrowphase/SphereVsSphereNarrowPhaseInfoBatch.h"
"include/reactphysics3d/collision/narrowphase/CapsuleVsCapsuleNarrowPhaseInfoBatch.h"
"include/reactphysics3d/collision/narrowphase/SphereVsCapsuleNarrowPhaseInfoBatch.h"
"include/reactphysics3d/collision/shapes/AABB.h"
"include/reactphysics3d/collision/shapes/ConvexShape.h"
"include/reactphysics3d/collision/shapes/ConvexPolyhedronShape.h"
@ -108,7 +105,6 @@ set (REACTPHYSICS3D_HEADERS
"include/reactphysics3d/engine/Island.h"
"include/reactphysics3d/engine/Islands.h"
"include/reactphysics3d/engine/Material.h"
"include/reactphysics3d/engine/Timer.h"
"include/reactphysics3d/engine/OverlappingPairs.h"
"include/reactphysics3d/systems/BroadPhaseSystem.h"
"include/reactphysics3d/components/Components.h"
@ -124,6 +120,7 @@ set (REACTPHYSICS3D_HEADERS
"include/reactphysics3d/collision/CollisionCallback.h"
"include/reactphysics3d/collision/OverlapCallback.h"
"include/reactphysics3d/mathematics/mathematics.h"
"include/reactphysics3d/mathematics/mathematics_common.h"
"include/reactphysics3d/mathematics/mathematics_functions.h"
"include/reactphysics3d/mathematics/Matrix2x2.h"
"include/reactphysics3d/mathematics/Matrix3x3.h"
@ -140,7 +137,7 @@ set (REACTPHYSICS3D_HEADERS
"include/reactphysics3d/memory/MemoryManager.h"
"include/reactphysics3d/containers/Stack.h"
"include/reactphysics3d/containers/LinkedList.h"
"include/reactphysics3d/containers/List.h"
"include/reactphysics3d/containers/Array.h"
"include/reactphysics3d/containers/Map.h"
"include/reactphysics3d/containers/Set.h"
"include/reactphysics3d/containers/Pair.h"
@ -168,9 +165,6 @@ set (REACTPHYSICS3D_SOURCES
"src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.cpp"
"src/collision/narrowphase/NarrowPhaseInput.cpp"
"src/collision/narrowphase/NarrowPhaseInfoBatch.cpp"
"src/collision/narrowphase/SphereVsSphereNarrowPhaseInfoBatch.cpp"
"src/collision/narrowphase/CapsuleVsCapsuleNarrowPhaseInfoBatch.cpp"
"src/collision/narrowphase/SphereVsCapsuleNarrowPhaseInfoBatch.cpp"
"src/collision/shapes/AABB.cpp"
"src/collision/shapes/ConvexShape.cpp"
"src/collision/shapes/ConvexPolyhedronShape.cpp"
@ -209,7 +203,6 @@ set (REACTPHYSICS3D_SOURCES
"src/engine/PhysicsWorld.cpp"
"src/engine/Island.cpp"
"src/engine/Material.cpp"
"src/engine/Timer.cpp"
"src/engine/OverlappingPairs.cpp"
"src/engine/Entity.cpp"
"src/engine/EntityManager.cpp"
@ -226,7 +219,6 @@ set (REACTPHYSICS3D_SOURCES
"src/components/SliderJointComponents.cpp"
"src/collision/CollisionCallback.cpp"
"src/collision/OverlapCallback.cpp"
"src/mathematics/mathematics_functions.cpp"
"src/mathematics/Matrix2x2.cpp"
"src/mathematics/Matrix3x3.cpp"
"src/mathematics/Quaternion.cpp"
@ -253,12 +245,6 @@ add_library(ReactPhysics3D::reactphysics3d ALIAS reactphysics3d)
target_compile_features(reactphysics3d PUBLIC cxx_std_11)
set_target_properties(reactphysics3d PROPERTIES CXX_EXTENSIONS OFF)
# Compile with warning messages
target_compile_options(reactphysics3d PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/W4> # for Visual Studio
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -pedantic> # Other compilers
)
# Library headers
target_include_directories(reactphysics3d PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
@ -287,8 +273,8 @@ endif()
# Version number and soname for the library
set_target_properties(reactphysics3d PROPERTIES
VERSION "0.8.0"
SOVERSION "0.8"
VERSION "0.9.0"
SOVERSION "0.9"
)
# Install target (install library only, not headers)
@ -333,3 +319,4 @@ install(FILES
${CMAKE_CURRENT_BINARY_DIR}/ReactPhysics3DConfigVersion.cmake
DESTINATION lib/cmake/ReactPhysics3D
)

View File

@ -1,4 +1,4 @@
# Copyright (c) 2012 - 2015, Lars Bilke
# Copyright (c) 2012 - 2017, Lars Bilke
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -26,7 +26,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
# CHANGES:
#
# 2012-01-31, Lars Bilke
# - Enable Code Coverage
@ -35,163 +35,674 @@
# - Added support for Clang.
# - Some additional usage instructions.
#
# 2016-02-03, Lars Bilke
# - Refactored functions to use named parameters
#
# 2017-06-02, Lars Bilke
# - Merged with modified version from github.com/ufz/ogs
#
# 2019-05-06, Anatolii Kurotych
# - Remove unnecessary --coverage flag
#
# 2019-12-13, FeRD (Frank Dana)
# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor
# of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments.
# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY
# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list
# - Set lcov basedir with -b argument
# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be
# overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().)
# - Delete output dir, .info file on 'make clean'
# - Remove Python detection, since version mismatches will break gcovr
# - Minor cleanup (lowercase function names, update examples...)
#
# 2019-12-19, FeRD (Frank Dana)
# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets
#
# 2020-01-19, Bob Apthorpe
# - Added gfortran support
#
# 2020-02-17, FeRD (Frank Dana)
# - Make all add_custom_target()s VERBATIM to auto-escape wildcard characters
# in EXCLUDEs, and remove manual escaping from gcovr targets
#
# 2021-01-19, Robin Mueller
# - Add CODE_COVERAGE_VERBOSE option which will allow to print out commands which are run
# - Added the option for users to set the GCOVR_ADDITIONAL_ARGS variable to supply additional
# flags to the gcovr command
#
# 2020-05-04, Mihchael Davis
# - Add -fprofile-abs-path to make gcno files contain absolute paths
# - Fix BASE_DIRECTORY not working when defined
# - Change BYPRODUCT from folder to index.html to stop ninja from complaining about double defines
#
# 2021-05-10, Martin Stump
# - Check if the generator is multi-config before warning about non-Debug builds
#
# USAGE:
# 0. (Mac only) If you use Xcode 5.1 make sure to patch geninfo as described here:
# http://stackoverflow.com/a/22404544/80480
#
# 1. Copy this file into your cmake modules path.
#
# 2. Add the following line to your CMakeLists.txt:
# INCLUDE(CodeCoverage)
# 2. Add the following line to your CMakeLists.txt (best inside an if-condition
# using a CMake option() to enable it just optionally):
# include(CodeCoverage)
#
# 3. Set compiler flags to turn off optimization and enable coverage:
# SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
# SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
# 3. Append necessary compiler flags:
# append_coverage_compiler_flags()
#
# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target
# which runs your test executable and produces a lcov code coverage report:
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
#
# 4. If you need to exclude additional directories from the report, specify them
# using full paths in the COVERAGE_EXCLUDES variable before calling
# setup_target_for_coverage_*().
# Example:
# SETUP_TARGET_FOR_COVERAGE(
# my_coverage_target # Name for custom target.
# test_driver # Name of the test driver executable that runs the tests.
# # NOTE! This should always have a ZERO as exit code
# # otherwise the coverage generation will not complete.
# coverage # Name of output directory.
# )
# set(COVERAGE_EXCLUDES
# '${PROJECT_SOURCE_DIR}/src/dir1/*'
# '/path/to/my/src/dir2/*')
# Or, use the EXCLUDE argument to setup_target_for_coverage_*().
# Example:
# setup_target_for_coverage_lcov(
# NAME coverage
# EXECUTABLE testrunner
# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*")
#
# 4. Build a Debug build:
# cmake -DCMAKE_BUILD_TYPE=Debug ..
# make
# make my_coverage_target
# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set
# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR)
# Example:
# set(COVERAGE_EXCLUDES "dir1/*")
# setup_target_for_coverage_gcovr_html(
# NAME coverage
# EXECUTABLE testrunner
# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
# EXCLUDE "dir2/*")
#
# 5. Use the functions described below to create a custom make target which
# runs your test executable and produces a code coverage report.
#
# 6. Build a Debug build:
# cmake -DCMAKE_BUILD_TYPE=Debug ..
# make
# make my_coverage_target
#
include(CMakeParseArguments)
option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
# Check prereqs
FIND_PROGRAM( GCOV_PATH gcov )
FIND_PROGRAM( LCOV_PATH lcov )
FIND_PROGRAM( GENHTML_PATH genhtml )
FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests)
find_program( GCOV_PATH gcov )
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
find_program( FASTCOV_PATH NAMES fastcov fastcov.py )
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
find_program( CPPFILT_PATH NAMES c++filt )
IF(NOT GCOV_PATH)
MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
ENDIF() # NOT GCOV_PATH
if(NOT GCOV_PATH)
message(FATAL_ERROR "gcov not found! Aborting...")
endif() # NOT GCOV_PATH
IF("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
IF("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3)
MESSAGE(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
ENDIF()
ELSEIF(NOT CMAKE_COMPILER_IS_GNUCXX)
MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
ENDIF() # CHECK VALID COMPILER
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
list(GET LANGUAGES 0 LANG)
SET(CMAKE_CXX_FLAGS_COVERAGE
"-g -O0 --coverage -fprofile-arcs -ftest-coverage"
if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
endif()
elseif(NOT CMAKE_COMPILER_IS_GNUCXX)
if("${CMAKE_Fortran_COMPILER_ID}" MATCHES "[Ff]lang")
# Do nothing; exit conditional without error if true
elseif("${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU")
# Do nothing; exit conditional without error if true
else()
message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
endif()
endif()
set(COVERAGE_COMPILER_FLAGS "-g -fprofile-arcs -ftest-coverage"
CACHE INTERNAL "")
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-fprofile-abs-path HAVE_fprofile_abs_path)
if(HAVE_fprofile_abs_path)
set(COVERAGE_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
endif()
endif()
set(CMAKE_Fortran_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the Fortran compiler during coverage builds."
FORCE )
set(CMAKE_CXX_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the C++ compiler during coverage builds."
FORCE )
SET(CMAKE_C_FLAGS_COVERAGE
"-g -O0 --coverage -fprofile-arcs -ftest-coverage"
set(CMAKE_C_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the C compiler during coverage builds."
FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
""
CACHE STRING "Flags used for linking binaries during coverage builds."
FORCE )
SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
""
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
FORCE )
MARK_AS_ADVANCED(
mark_as_advanced(
CMAKE_Fortran_FLAGS_COVERAGE
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
IF ( NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "Coverage"))
MESSAGE( WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" )
ENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
link_libraries(gcov)
endif()
# Param _targetname The name of new the custom make target
# Param _testrunner The name of the target which runs the tests.
# MUST return ZERO always, even on errors.
# If not, no coverage report will be created!
# Param _outputname lcov output is generated as _outputname.info
# HTML report is generated in _outputname/index.html
# Optional fourth parameter is passed as arguments to _testrunner
# Pass them in list form, e.g.: "-j;2" for -j 2
FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname)
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_lcov(
# NAME testrunner_coverage # New target name
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES testrunner # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# NO_DEMANGLE # Don't demangle C++ symbols
# # even if c++filt is found
# )
function(setup_target_for_coverage_lcov)
IF(NOT LCOV_PATH)
MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
ENDIF() # NOT LCOV_PATH
set(options NO_DEMANGLE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
IF(NOT GENHTML_PATH)
MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
ENDIF() # NOT GENHTML_PATH
if(NOT LCOV_PATH)
message(FATAL_ERROR "lcov not found! Aborting...")
endif() # NOT LCOV_PATH
SET(coverage_info "${CMAKE_BINARY_DIR}/${_outputname}.info")
SET(coverage_cleaned "${coverage_info}.cleaned")
if(NOT GENHTML_PATH)
message(FATAL_ERROR "genhtml not found! Aborting...")
endif() # NOT GENHTML_PATH
SEPARATE_ARGUMENTS(test_command UNIX_COMMAND "${_testrunner}")
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Setup target
ADD_CUSTOM_TARGET(${_targetname}
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(LCOV_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND LCOV_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES LCOV_EXCLUDES)
# Cleanup lcov
${LCOV_PATH} --directory . --zerocounters
# Conditional arguments
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
endif()
# Setting up commands which will be run to generate coverage data.
# Cleanup lcov
set(LCOV_CLEAN_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory .
-b ${BASEDIR} --zerocounters
)
# Create baseline to make sure untouched files show up in the report
set(LCOV_BASELINE_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b
${BASEDIR} -o ${Coverage_NAME}.base
)
# Run tests
set(LCOV_EXEC_TESTS_CMD
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
)
# Capturing lcov counters and generating report
set(LCOV_CAPTURE_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b
${BASEDIR} --capture --output-file ${Coverage_NAME}.capture
)
# add baseline counters
set(LCOV_BASELINE_COUNT_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base
-a ${Coverage_NAME}.capture --output-file ${Coverage_NAME}.total
)
# filter collected data to final coverage report
set(LCOV_FILTER_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove
${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${Coverage_NAME}.info
)
# Generate HTML output
set(LCOV_GEN_HTML_CMD
${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o
${Coverage_NAME} ${Coverage_NAME}.info
)
# Run tests
COMMAND ${test_command} ${ARGV3}
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
message(STATUS "Command to clean up lcov: ")
string(REPLACE ";" " " LCOV_CLEAN_CMD_SPACED "${LCOV_CLEAN_CMD}")
message(STATUS "${LCOV_CLEAN_CMD_SPACED}")
# Capturing lcov counters and generating report
COMMAND ${LCOV_PATH} --directory . --capture --output-file ${coverage_info}
COMMAND ${LCOV_PATH} --remove ${coverage_info} 'tests/*' '/usr/*' --output-file ${coverage_cleaned}
COMMAND ${GENHTML_PATH} -o ${_outputname} ${coverage_cleaned}
COMMAND ${CMAKE_COMMAND} -E remove ${coverage_info} ${coverage_cleaned}
message(STATUS "Command to create baseline: ")
string(REPLACE ";" " " LCOV_BASELINE_CMD_SPACED "${LCOV_BASELINE_CMD}")
message(STATUS "${LCOV_BASELINE_CMD_SPACED}")
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
)
message(STATUS "Command to run the tests: ")
string(REPLACE ";" " " LCOV_EXEC_TESTS_CMD_SPACED "${LCOV_EXEC_TESTS_CMD}")
message(STATUS "${LCOV_EXEC_TESTS_CMD_SPACED}")
# Show info where to find the report
ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
COMMAND ;
COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report."
)
message(STATUS "Command to capture counters and generate report: ")
string(REPLACE ";" " " LCOV_CAPTURE_CMD_SPACED "${LCOV_CAPTURE_CMD}")
message(STATUS "${LCOV_CAPTURE_CMD_SPACED}")
ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE
message(STATUS "Command to add baseline counters: ")
string(REPLACE ";" " " LCOV_BASELINE_COUNT_CMD_SPACED "${LCOV_BASELINE_COUNT_CMD}")
message(STATUS "${LCOV_BASELINE_COUNT_CMD_SPACED}")
# Param _targetname The name of new the custom make target
# Param _testrunner The name of the target which runs the tests
# Param _outputname cobertura output is generated as _outputname.xml
# Optional fourth parameter is passed as arguments to _testrunner
# Pass them in list form, e.g.: "-j;2" for -j 2
FUNCTION(SETUP_TARGET_FOR_COVERAGE_COBERTURA _targetname _testrunner _outputname)
message(STATUS "Command to filter collected data: ")
string(REPLACE ";" " " LCOV_FILTER_CMD_SPACED "${LCOV_FILTER_CMD}")
message(STATUS "${LCOV_FILTER_CMD_SPACED}")
IF(NOT PYTHON_EXECUTABLE)
MESSAGE(FATAL_ERROR "Python not found! Aborting...")
ENDIF() # NOT PYTHON_EXECUTABLE
message(STATUS "Command to generate lcov HTML output: ")
string(REPLACE ";" " " LCOV_GEN_HTML_CMD_SPACED "${LCOV_GEN_HTML_CMD}")
message(STATUS "${LCOV_GEN_HTML_CMD_SPACED}")
endif()
IF(NOT GCOVR_PATH)
MESSAGE(FATAL_ERROR "gcovr not found! Aborting...")
ENDIF() # NOT GCOVR_PATH
# Setup target
add_custom_target(${Coverage_NAME}
COMMAND ${LCOV_CLEAN_CMD}
COMMAND ${LCOV_BASELINE_CMD}
COMMAND ${LCOV_EXEC_TESTS_CMD}
COMMAND ${LCOV_CAPTURE_CMD}
COMMAND ${LCOV_BASELINE_COUNT_CMD}
COMMAND ${LCOV_FILTER_CMD}
COMMAND ${LCOV_GEN_HTML_CMD}
ADD_CUSTOM_TARGET(${_targetname}
# Set output files as GENERATED (will be removed on 'make clean')
BYPRODUCTS
${Coverage_NAME}.base
${Coverage_NAME}.capture
${Coverage_NAME}.total
${Coverage_NAME}.info
${Coverage_NAME}/index.html
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
)
# Run tests
${_testrunner} ${ARGV3}
# Show where to find the lcov info report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info."
)
# Running gcovr
COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} -e '${CMAKE_SOURCE_DIR}/tests/' -o ${_outputname}.xml
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Running gcovr to produce Cobertura code coverage report."
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
)
# Show info where to find the report
ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
COMMAND ;
COMMENT "Cobertura code coverage report saved in ${_outputname}.xml."
)
endfunction() # setup_target_for_coverage_lcov
ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_COBERTURA
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_gcovr_xml(
# NAME ctest_coverage # New target name
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES executable_target # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# )
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
# GCVOR command.
function(setup_target_for_coverage_gcovr_xml)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT GCOVR_PATH)
message(FATAL_ERROR "gcovr not found! Aborting...")
endif() # NOT GCOVR_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach(EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach()
# Set up commands which will be run to generate coverage data
# Run tests
set(GCOVR_XML_EXEC_TESTS_CMD
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
)
# Running gcovr
set(GCOVR_XML_CMD
${GCOVR_PATH} --xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS} ${GCOVR_EXCLUDE_ARGS}
--object-directory=${PROJECT_BINARY_DIR} -o ${Coverage_NAME}.xml
)
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
message(STATUS "Command to run tests: ")
string(REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD}")
message(STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED}")
message(STATUS "Command to generate gcovr XML coverage data: ")
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
message(STATUS "${GCOVR_XML_CMD_SPACED}")
endif()
add_custom_target(${Coverage_NAME}
COMMAND ${GCOVR_XML_EXEC_TESTS_CMD}
COMMAND ${GCOVR_XML_CMD}
BYPRODUCTS ${Coverage_NAME}.xml
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce Cobertura code coverage report."
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
)
endfunction() # setup_target_for_coverage_gcovr_xml
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_gcovr_html(
# NAME ctest_coverage # New target name
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES executable_target # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# )
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
# GCVOR command.
function(setup_target_for_coverage_gcovr_html)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT GCOVR_PATH)
message(FATAL_ERROR "gcovr not found! Aborting...")
endif() # NOT GCOVR_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach(EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach()
# Set up commands which will be run to generate coverage data
# Run tests
set(GCOVR_HTML_EXEC_TESTS_CMD
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
)
# Create folder
set(GCOVR_HTML_FOLDER_CMD
${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME}
)
# Running gcovr
set(GCOVR_HTML_CMD
${GCOVR_PATH} --html --html-details -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
-o ${Coverage_NAME}/index.html
)
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
message(STATUS "Command to run tests: ")
string(REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD}")
message(STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED}")
message(STATUS "Command to create a folder: ")
string(REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD}")
message(STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED}")
message(STATUS "Command to generate gcovr HTML coverage data: ")
string(REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD}")
message(STATUS "${GCOVR_HTML_CMD_SPACED}")
endif()
add_custom_target(${Coverage_NAME}
COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD}
COMMAND ${GCOVR_HTML_FOLDER_CMD}
COMMAND ${GCOVR_HTML_CMD}
BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report directory
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce HTML code coverage report."
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
)
endfunction() # setup_target_for_coverage_gcovr_html
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_fastcov(
# NAME testrunner_coverage # New target name
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES testrunner # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/" "src/dir2/" # Patterns to exclude.
# NO_DEMANGLE # Don't demangle C++ symbols
# # even if c++filt is found
# SKIP_HTML # Don't create html report
# POST_CMD perl -i -pe s!${PROJECT_SOURCE_DIR}/!!g ctest_coverage.json # E.g. for stripping source dir from file paths
# )
function(setup_target_for_coverage_fastcov)
set(options NO_DEMANGLE SKIP_HTML)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES FASTCOV_ARGS GENHTML_ARGS POST_CMD)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT FASTCOV_PATH)
message(FATAL_ERROR "fastcov not found! Aborting...")
endif()
if(NOT Coverage_SKIP_HTML AND NOT GENHTML_PATH)
message(FATAL_ERROR "genhtml not found! Aborting...")
endif()
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (Patterns, not paths, for fastcov)
set(FASTCOV_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_FASTCOV_EXCLUDES})
list(APPEND FASTCOV_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES FASTCOV_EXCLUDES)
# Conditional arguments
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
endif()
# Set up commands which will be run to generate coverage data
set(FASTCOV_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
set(FASTCOV_CAPTURE_CMD ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
--search-directory ${BASEDIR}
--process-gcno
--output ${Coverage_NAME}.json
--exclude ${FASTCOV_EXCLUDES}
--exclude ${FASTCOV_EXCLUDES}
)
set(FASTCOV_CONVERT_CMD ${FASTCOV_PATH}
-C ${Coverage_NAME}.json --lcov --output ${Coverage_NAME}.info
)
if(Coverage_SKIP_HTML)
set(FASTCOV_HTML_CMD ";")
else()
set(FASTCOV_HTML_CMD ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS}
-o ${Coverage_NAME} ${Coverage_NAME}.info
)
endif()
set(FASTCOV_POST_CMD ";")
if(Coverage_POST_CMD)
set(FASTCOV_POST_CMD ${Coverage_POST_CMD})
endif()
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Code coverage commands for target ${Coverage_NAME} (fastcov):")
message(" Running tests:")
string(REPLACE ";" " " FASTCOV_EXEC_TESTS_CMD_SPACED "${FASTCOV_EXEC_TESTS_CMD}")
message(" ${FASTCOV_EXEC_TESTS_CMD_SPACED}")
message(" Capturing fastcov counters and generating report:")
string(REPLACE ";" " " FASTCOV_CAPTURE_CMD_SPACED "${FASTCOV_CAPTURE_CMD}")
message(" ${FASTCOV_CAPTURE_CMD_SPACED}")
message(" Converting fastcov .json to lcov .info:")
string(REPLACE ";" " " FASTCOV_CONVERT_CMD_SPACED "${FASTCOV_CONVERT_CMD}")
message(" ${FASTCOV_CONVERT_CMD_SPACED}")
if(NOT Coverage_SKIP_HTML)
message(" Generating HTML report: ")
string(REPLACE ";" " " FASTCOV_HTML_CMD_SPACED "${FASTCOV_HTML_CMD}")
message(" ${FASTCOV_HTML_CMD_SPACED}")
endif()
if(Coverage_POST_CMD)
message(" Running post command: ")
string(REPLACE ";" " " FASTCOV_POST_CMD_SPACED "${FASTCOV_POST_CMD}")
message(" ${FASTCOV_POST_CMD_SPACED}")
endif()
endif()
# Setup target
add_custom_target(${Coverage_NAME}
# Cleanup fastcov
COMMAND ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
--search-directory ${BASEDIR}
--zerocounters
COMMAND ${FASTCOV_EXEC_TESTS_CMD}
COMMAND ${FASTCOV_CAPTURE_CMD}
COMMAND ${FASTCOV_CONVERT_CMD}
COMMAND ${FASTCOV_HTML_CMD}
COMMAND ${FASTCOV_POST_CMD}
# Set output files as GENERATED (will be removed on 'make clean')
BYPRODUCTS
${Coverage_NAME}.info
${Coverage_NAME}.json
${Coverage_NAME}/index.html # report directory
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Resetting code coverage counters to zero. Processing code coverage counters and generating report."
)
set(INFO_MSG "fastcov code coverage info report saved in ${Coverage_NAME}.info and ${Coverage_NAME}.json.")
if(NOT Coverage_SKIP_HTML)
string(APPEND INFO_MSG " Open ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html in your browser to view the coverage report.")
endif()
# Show where to find the fastcov info report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo ${INFO_MSG}
)
endfunction() # setup_target_for_coverage_fastcov
function(append_coverage_compiler_flags)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
endfunction() # append_coverage_compiler_flags

View File

@ -1,4 +1,4 @@
Copyright (c) 2010-2020 Daniel Chappuis http://www.reactphysics3d.com
Copyright (c) 2010-2022 Daniel Chappuis http://www.reactphysics3d.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

View File

@ -1,20 +1,28 @@
[![Travis Build Status](https://travis-ci.org/DanielChappuis/reactphysics3d.svg?branch=master)](https://travis-ci.org/DanielChappuis/reactphysics3d)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3ae24e998e304e4da78ec848eade9e3a)](https://www.codacy.com/app/chappuis.daniel/reactphysics3d?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=DanielChappuis/reactphysics3d&amp;utm_campaign=Badge_Grade)
[![codecov.io](https://codecov.io/github/DanielChappuis/reactphysics3d/coverage.svg?branch=master)](https://codecov.io/github/DanielChappuis/reactphysics3d?branch=master)
<h1 align="center">
<a href="https://www.reactphysics3d.com"><img src="https://github.com/DanielChappuis/reactphysics3d/blob/62e17155e3fc187f4a90f7328c1154fc47e41d69/documentation/UserManual/images/ReactPhysics3DLogo.png" alt="ReactPhysics3D" width="300"></a>
<br>
ReactPhysics3D
<br>
</h1>
## ReactPhysics3D
<h4 align="center">ReactPhysics3D is an open source C++ physics engine library that can be used in 3D simulations and games.</h4>
<p align="center"><a href="https://www.reactphysics3d.com">www.reactphysics3d.com</a></p>
<p align="center">
<a href="https://github.com/DanielChappuis/reactphysics3d/actions/workflows/build-and-test.yml">
<img src="https://github.com/DanielChappuis/reactphysics3d/actions/workflows/build-and-test.yml/badge.svg"
alt="Build">
</a>
<a href="https://www.codacy.com/app/chappuis.daniel/reactphysics3d?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=DanielChappuis/reactphysics3d&amp;utm_campaign=Badge_Grade"><img src="https://api.codacy.com/project/badge/Grade/3ae24e998e304e4da78ec848eade9e3a"></a>
<a href="https://codecov.io/github/DanielChappuis/reactphysics3d?branch=master">
<img src="https://codecov.io/github/DanielChappuis/reactphysics3d/coverage.svg?branch=master">
</a>
</p>
ReactPhysics3D is an open source C++ physics engine library that can be used in 3D simulations and games.
<p align="center">
<img src="https://github.com/DanielChappuis/reactphysics3d/blob/images/showreel.gif?raw=true" alt="Drawing" />
</p>
Website : [https://www.reactphysics3d.com](https://www.reactphysics3d.com)
Author : Daniel Chappuis
<img src="https://raw.githubusercontent.com/DanielChappuis/reactphysics3d/master/documentation/UserManual/images/testbed.png" alt="Drawing" height="400" />
## Features
ReactPhysics3D has the following features:
## :dart: Features
- Rigid body dynamics
- Discrete collision detection
@ -36,26 +44,42 @@ ReactPhysics3D has the following features:
- Logs
- Unit tests
## License
## :book: Documentation
The ReactPhysics3D library is released under the open-source [ZLib license](http://opensource.org/licenses/zlib).
You can find the user manual and the Doxygen API documentation <a href="https://www.reactphysics3d.com/documentation.html" target="_blank">here</a>.
## Documentation
## :information_source: Branches
You can find the user manual and the Doxygen API documentation [here](https://www.reactphysics3d.com/documentation.html)
## Branches
The "master" branch always contains the last released version of the library and some possible bug fixes. This is the most stable version. On the other side,
The "master" branch always contains the last released version of the library and some possible hot fixes. This is the most stable version. On the other side,
the "develop" branch is used for development. This branch is frequently updated and can be quite unstable. Therefore, if you want to use the library in
your application, it is recommended to checkout the "master" branch.
## Issues
## :question: Questions
If you find any issue with the library, you can report it on the issue tracker [here](https://github.com/DanielChappuis/reactphysics3d/issues).
If you have any questions about the library and how to use it, you should use <a href="https://github.com/DanielChappuis/reactphysics3d/discussions" target="_blank">Github Discussions</a> to read previous questions and answers or to ask new questions. If you want, you can also share your project there if you are using the ReactPhysics3D library.
## Credits
## :warning: Issues
If you find any issue with the library, you can report it on the issue tracker <a href="https://github.com/DanielChappuis/reactphysics3d/issues" target="_blank">here</a>.
## :man: Author
The ReactPhysics3D library has been created and is maintained by <a href="https://github.com/DanielChappuis" target="_blank">Daniel Chappuis</a>.
## :copyright: License
The ReactPhysics3D library is released under the open-source <a href="http://opensource.org/licenses/zlib" target="_blank">ZLib license</a>.
## :+1: Sponsorship
If you are using this library and want to support its development, you can sponsor it <a href="https://github.com/sponsors/DanielChappuis" target="_blank">here</a>.
## :clap: Credits
Thanks a lot to Erin Catto, Dirk Gregorius, Erwin Coumans, Pierre Terdiman and Christer Ericson for their amazing GDC presentations,
their physics engines, their books or articles and their contributions on many physics engine forums.
Thanks to all the contributors that have reported issues or have taken the time to send pull requests.
- [Artbake Graphics](https://sketchfab.com/ismir) for the static castle 3D model used in testbed application ([CC license](https://creativecommons.org/licenses/by/4.0))

View File

@ -1 +1 @@
0.8.0
0.9.0

View File

@ -38,7 +38,7 @@ PROJECT_NAME = "ReactPhysics3D"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = "0.8.0"
PROJECT_NUMBER = "0.9.0"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@ -170,11 +170,11 @@
Now, if you go into the folder you have chosen to build the library, you should find the native build tool files that you will use to build
the library on your platform.
\subsection{Bulding the library}
\subsection{Building the library}
Now, that you have generated the native build tool files on your system, you will need to build (compile) the library.
\subsubsection{Bulding the library using \texttt{make} on the command line (Linux, Mac OS X)}
\subsubsection{Building the library using \texttt{make} on the command line (Linux, Mac OS X)}
On Linux or Mac OS X, you can compile the library on the command line using the \texttt{make} command. Go into the directory where you have generated the
native build tool files and run the following command: \\
@ -183,7 +183,7 @@
The library will start compiling.
\subsubsection{Bulding the library with Visual Studio (Windows)}
\subsubsection{Building the library with Visual Studio (Windows)}
If you have generated the native build tool files in the previous step on Windows, you should have obtained a Visual Studio solution of ReactPhysics3D.
Now, you can open the Visual Studio solution (.sln file). Once Visual Studio is open, you first need to change the compilation mode to \emph{Release}
@ -315,7 +315,7 @@ target_link_libraries(helloworld ReactPhysics3D::ReactPhysics3D)
# Minimum cmake version required
cmake_minimum_required(VERSION 3.8)
# Help CMake to find the installed library on Windows or Mac OS X
# Help CMake to find the installed library on Windows or Mac OS X
if(WIN32)
list(APPEND CMAKE_PREFIX_PATH "C:\\Program Files (x86)\\ReactPhysics3D")
elseif(APPLE)
@ -924,8 +924,7 @@ float factor = accumulator / timeStep;
\begin{lstlisting}
// Compute the interpolated transform of the rigid body
Transform interpolatedTransform = Transform::interpolateTransforms(prevTransform,
currTransform, factor);
Transform interpolatedTransform = Transform::interpolateTransforms(prevTransform, currTransform, factor);
\end{lstlisting}
\vspace{0.6cm}
@ -967,8 +966,7 @@ decimal factor = accumulator / timeStep;
Transform currTransform = body->getTransform();
// Compute the interpolated transform of the rigid body
Transform interpolatedTransform = Transform::interpolateTransforms(prevTransform,
currTransform, factor);
Transform interpolatedTransform = Transform::interpolateTransforms(prevTransform, currTransform, factor);
// Now you can render your body using the interpolated transform here
@ -1037,6 +1035,28 @@ transform.getOpenGLMatrix(matrix);
\texttt{RigidBody::updateMassPropertiesFromColliders()}.
\end{sloppypar}
\subsection{Restricting linear/angular motion of a Rigid Body}
It is possible to use the \texttt{RigidBody::setLinearLockAxisFactor()} method to restrict the linear motion of a rigid body along the world-space
X,Y and Z axes. For instance, the following code shows how to disable the linear motion of a rigid body along the world-space Y axis by setting the lock
factor to zero for this axis. \\
\begin{lstlisting}
// Disable motion along the Y axis
rigidBody->setLinearAxisFactor(Vector3(1, 0, 1));
\end{lstlisting}
\vspace{0.6cm}
In the same way, you can use the \texttt{RigidBody::setAngularLockAxisFactor()} method to restrict the angular motion of a rigid body around the
world-space X,Y and Z axes. For instance, the following code shows how to disable the angular motion of a rigid body around the world-space Y axis
by setting the lock factor to zero for this axis. \\
\begin{lstlisting}
// Disable rotation around the Y axis
rigidBody->setAngularAxisFactor(Vector3(1, 0, 1));
\end{lstlisting}
\subsection{Destroying a Rigid Body}
\begin{sloppypar}
@ -1090,7 +1110,9 @@ collider = body->addCollider(&shape, transform);
\label{sec:collisionshapes}
As we have just seen, a collision shape is used to describe the shape of a collider for collision detection. They are many types of
collision shapes that you can use. They all inherit from the \texttt{CollisionShape} class.
collision shapes that you can use. They all inherit from the \texttt{CollisionShape} class. \\
Note that ReactPhysics3D does not support collision between two concave shapes (\texttt{ConcaveMeshShape} and \texttt{HeightFieldShape}).
\subsubsection{Box Shape}
@ -1215,7 +1237,7 @@ for (int f = 0; f < 6; f++) {
}
// Create the polygon vertex array
PolygonVertexArray* polygonVertexArray = new PolygonVertexArray(8, vertices, 3 x sizeof(float),
PolygonVertexArray* polygonVertexArray = new PolygonVertexArray(8, vertices, 3 * sizeof(float),
indices, sizeof(int), 6, polygonFaces,
PolygonVertexArray::VertexDataType::VERTEX_FLOAT_TYPE,
PolygonVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
@ -1236,6 +1258,9 @@ ConvexMeshShape* convexMeshShape = physicsCommon.createConvexMeshShape(polyhedro
that you need to avoid coplanar faces in your convex mesh shape. Coplanar faces have to be merged together. Remember that convex meshes are
not limited to triangular faces, you can create faces with more than three vertices. \\
Also note that meshes with duplicated vertices are not supported. The number of vertices you pass to create the PolygonVertexArray must be exactly
the number of vertices in your convex mesh. \\
When you specify the vertices for each face of your convex mesh, be careful with their order. The vertices of a face must be specified in
counter clockwise order as seen from the outside of your convex mesh. \\
@ -1316,8 +1341,11 @@ ConcaveMeshShape* concaveMesh = physicsCommon.createConcaveMeshShape(triangleMes
\texttt{TriangleMesh} for multiple \texttt{ConcaveMeshShape} with a different scaling factor each time. \\
\end{sloppypar}
In the previous example, the vertex normals that are needed for collision detection are automatically computed. However, if you want to specify your own
vertex normals, you can do it by using another constructor for the \texttt{TriangleVertexArray}. \\
In the previous example, the vertices normals that are needed for collision detection are automatically computed. However, you can specify your own
vertices normals by using another constructor for the \texttt{TriangleVertexArray}. Note that each vertex normal is computed as weighted average
of the face normals of all the neighboring triangle faces. Therefore, if you specify your mesh with duplicated vertices when you create the
\emph{TriangleVertexArray}, the automatic vertices normals computation will not give correct normals because each vertex of the mesh will only be
part of a single triangle face. In this case, you should provide your own vertices normals when you create the \emph{TriangleVertexArray}. \\
\subsubsection{Heightfield Shape}
@ -1440,14 +1468,13 @@ colliderBody4->setCollideWithMaskBits(CATEGORY2);
\subsection{Material}
\label{sec:material}
The material of a rigid body is used to describe the physical properties it is made of. This is represented by the \texttt{Material} class. Each body that
you create will have a default material. You can get the material of the rigid body using the \texttt{RigidBody::\allowbreak getMaterial()} method. \\
The material of a collider is used to describe the physical properties it is made of. This is represented by the \texttt{Material} class. Each collider that you create will have a default material. You can get the material of the collider using the \texttt{Collider::\allowbreak getMaterial()} method. \\
You can use the material to set those physical properties. \\
For instance, you can change the bounciness of the rigid body. The bounciness is a value between 0 and 1. The value 1 is used for a very bouncy
object and the value 0 means that the body will not be bouncy at all. To change the bounciness of the material, you can use the
\texttt{Material::\allowbreak setBounciness()} method. \\
For instance, you can change the bounciness of the collider. The bounciness is a value between 0 and 1. The value 1 is used for
a very bouncy object and the value 0 means that the collider will not be bouncy at all. To change the bounciness of the material,
you can use the \texttt{Material::\allowbreak setBounciness()} method. \\
\begin{sloppypar}
It is also possible to set the mass density of the collider which has a default value of 1. As described in section \ref{sec:rigidbodymass}, the
@ -1455,25 +1482,20 @@ colliderBody4->setCollideWithMaskBits(CATEGORY2);
mass density of a collider, you need to use the \texttt{Material::setMassDensity()} method. \\
\end{sloppypar}
You are also able to change the friction coefficient of the body. This value needs to be between 0 and 1. If the value is 0, no friction will be
applied when the body is in contact with another body. However, if the value is 1, the friction force will be high. You can change the
friction coefficient of the material with the \texttt{Material::\allowbreak setFrictionCoefficient()} method. \\
You are also able to change the friction coefficient of the collider. This value needs to be between 0 and 1. If the value is 0,
no friction will be applied when the collider is in contact with another collider. However, if the value is 1, the friction force will be high. You can
change the friction coefficient of the material with the \texttt{Material::\allowbreak setFrictionCoefficient()} method. \\
You can use the material to add rolling resistance to a rigid body. Rolling resistance can be used to stop
a rolling object on a flat surface for instance. You should use this only with SphereShape or
CapsuleShape collision shapes. By default, rolling resistance is zero but you can
set a positive value using the \texttt{Material::\allowbreak setRollingResistance()} method to increase resistance. \\
Here is how to get the material of a rigid body and how to modify some of its properties: \\
Here is how to get the material of a collider and how to modify some of its properties: \\
\begin{lstlisting}
// Get the current material of the body
Material& material = rigidBody->getMaterial();
// Get the current material of the collider
Material& material = collider->getMaterial();
// Change the bounciness of the body
// Change the bounciness of the collider
material.setBounciness(0.4);
// Change the friction coefficient of the body
// Change the friction coefficient of the collider
material.setFrictionCoefficient(0.2);
\end{lstlisting}
@ -1509,12 +1531,15 @@ bombCollider->setIsTrigger(true);
\subsection{Ball and Socket Joint}
The \texttt{BallAndSocketJoint} class describes a ball and socket joint between two bodies. In a ball and socket joint, the two bodies cannot translate with respect to each other.
However, they can rotate freely around a common anchor point. This joint has three degrees of freedom and can be used to simulate a chain of bodies for instance. \\
The \texttt{BallAndSocketJoint} class describes a ball and socket joint between two bodies. In a ball and socket joint, the two bodies cannot
translate with respect to each other. However, they can rotate freely around a common anchor point. This joint has three degrees of freedom
and can be used to simulate a chain of bodies for instance. \\
In order to create a ball and socket joint, you first need to create an instance of the \texttt{BallAndSocketJointInfo} class with the necessary information. You need to provide the pointers to the
two rigid bodies and also the coordinates of the anchor point (in world-space). At the joint creation, the world-space anchor point will be converted into the local-space of the two rigid
bodies and then, the joint will make sure that the two local-space anchor points match in world-space. Therefore, the two bodies need to be in a correct position at the joint creation. \\
In order to create a ball and socket joint, you first need to create an instance of the \texttt{BallAndSocketJointInfo} class with the necessary
information. You need to provide the pointers to the two rigid bodies and also the coordinates of the anchor point. The \texttt{BallAndSocketJointInfo}
class contains different constructors that you can use whether you want to specify the anchor point in world-space or local-space coordinates.
The joint will make sure that the two local-space anchor points match in world-space. Make sure that the two bodies are in a valid position (with
respect to the joint constraint) at the beginning of the simulation. \\
Here is the code to create the \texttt{BallAndSocketJointInfo} object: \\
@ -1542,7 +1567,22 @@ BallAndSocketJoint* joint;
joint = dynamic_cast<BallAndSocketJoint*>(world->createJoint(jointInfo));
\end{lstlisting}
\vspace{0.6cm}
\subsubsection{Cone limit}
With the ball and socket joint, it is possible to enable a cone limit. Let's call the \texttt{anchor axis} for body 1 the axis from body 1 center of mass
to the joint anchor point. The cone limit can be used to constraint the angle between the anchor axis of body 1 and the anchor axis of body 2.
The idea is to limit the angle of the anchor axis of body 2 inside a cone around the anchor axis of body 1. The cone is defined by its main axis
which is the anchor axis of body 1 and is also defined by the cone half angle. \\
In the following example, we enable the cone limit for a given ball and socket joint. \\
\begin{lstlisting}
// Set the maximum half angle (in radians)
joint->setConeLimitHalfAngle(45.0 * PI / 180.0);
// Enable the cone limit for this joint
joint->enableConeLimit(true);
\end{lstlisting}
\subsection{Hinge Joint}
@ -1550,8 +1590,9 @@ joint = dynamic_cast<BallAndSocketJoint*>(world->createJoint(jointInfo));
anchor point and around a single axis (the hinge axis). This joint can be used to simulate doors or pendulums for instance. \\
In order to create a hinge joint, you first need to create a \texttt{HingeJointInfo} object with the necessary information. You need to provide
the pointers to the two rigid bodies, the coordinates of the anchor point (in world-space) and also the hinge rotation axis (in world-space). The
two bodies need to be in a correct position when the joint is created. \\
the pointers to the two rigid bodies, the coordinates of the anchor point and also the hinge rotation axis. The \texttt{HingeJointInfo} class contains
different constructors that you can use whether you want to specify the anchor point or the rotation axis in local-space or world-space.
Make sure that the two bodies are in a valid position (with respect to the joint constraint) at the beginning of the simulation. \\
Here is the code to create the \texttt{HingeJointInfo} object: \\
@ -1584,10 +1625,11 @@ joint = dynamic_cast<HingeJoint*>(world->createJoint(jointInfo));
\subsubsection{Limits}
With the hinge joint, you can constrain the motion range using limits. The limits of the hinge joint are the minimum and maximum angle of rotation allowed with respect to the initial
angle between the bodies when the joint is created. The limits are disabled by default. If you want to use the limits, you first need to enable them by setting the
\texttt{isLimitEnabled} variable of the \texttt{HingeJointInfo} object to \emph{true} before you create the joint. You also have to specify the minimum and maximum limit
angles (in radians) using the \texttt{minAngleLimit} and \texttt{maxAngleLimit} variables of the joint info object. Note that the minimum limit angle must be in the
With the hinge joint, you can constrain the motion range using limits. The limits of the hinge joint are the minimum and maximum angle of
rotation allowed with respect to the initial angle between the bodies when the joint is created. The limits are disabled by default.
If you want to use the limits, you first need to enable them by setting the \texttt{isLimitEnabled} variable of the \texttt{HingeJointInfo}
object to \emph{true} before you create the joint. You also have to specify the minimum and maximum limit angles (in radians) using
the \texttt{minAngleLimit} and \texttt{maxAngleLimit} variables of the joint info object. Note that the minimum limit angle must be in the
range $[ -2 \pi; 0 ]$ and the maximum limit angle must be in the range $[ 0; 2 \pi ]$. \\
For instance, here is the way to use the limits for a hinge joint when the joint is created: \\
@ -1654,10 +1696,14 @@ joint = dynamic_cast<HingeJoint*>(world->createJoint(jointInfo));
\subsection{Slider Joint}
The \texttt{SliderJoint} class describes a slider joint (or prismatic joint) that only allows relative translation along a single direction. It has a single degree of freedom and allows no
relative rotation. In order to create a slider joint, you first need to specify the anchor point (in world-space) and the slider axis direction (in world-space). The constructor of the
\texttt{SliderJointInfo} object needs two pointers to the bodies of the joint, the anchor point and the axis direction. Note that the two bodies have to be in a correct initial position when
the joint is created. \\
The \texttt{SliderJoint} class describes a slider joint (or prismatic joint) that only allows relative translation along a single direction.
It has a single degree of freedom and allows no relative rotation. \\
In order to create a slider joint, you first need to specify the anchor point and the slider axis direction.
The constructor of the \texttt{SliderJointInfo} object needs two pointers to the bodies of the joint, the anchor point and the axis direction.
The \texttt{SliderJointInfo} class contains different constructors that you can use whether you want to specify the anchor point and the direction axis
in local-space or world-space. Make sure that the two bodies are in a valid position (with respect to the joint constraint) at the beginning
of the simulation.\\
You can see in the following code how to specify the information to create a slider joint: \\
@ -1758,9 +1804,12 @@ joint = dynamic_cast<SliderJoint*>(world->createJoint(jointInfo));
\subsection{Fixed Joint}
The \texttt{FixedJoint} class describes a fixed joint between two bodies. In a fixed joint, there is no degree of freedom, the bodies are not allowed to translate
or rotate with respect to each other. In order to create a fixed joint, you simply need to specify an anchor point (in world-space) to create the \texttt{FixedJointInfo}
object. \\
The \texttt{FixedJoint} class describes a fixed joint between two bodies. In a fixed joint, there is no degree of freedom, the bodies are not
allowed to translate or rotate with respect to each other. \\
In order to create a fixed joint, you simply need to specify an anchor point to create the \texttt{FixedJointInfo}
object. The \texttt{FixedJointInfo} class contains different constructors that you can use whether you want to specify the anchor point in local-space
or world-space. Make sure that the two bodies are in a valid position (with respect to the joint constraint) at the beginning of the simulation.\\
For instance, here is how to create the joint info object for a fixed joint: \\
@ -2002,51 +2051,6 @@ bool isHit = collider->raycast(ray, raycastInfo);
the ReactPhysics3D library. Do not hesitate to take a look at the code of the demo scenes to better understand how
to use the library in your application. \\
The following subsections describe the demo scenes that can be found in the testbed application.
\subsection{Cubes Scene}
In this scene, you will see how to create a floor and some cubes using the Box Shape for collision detection. Because of gravity,
the cubes will fall down on the floor. After falling down, the cubes will come to rest and start sleeping (become inactive). In this scene,
the cubes will become red as they get inactive (sleeping).
\subsection{Cubes Stack Scene}
This scene has a physics world and a pyramid of cubes.
\subsection{Joints Scene}
In this scene, you will learn how to create different joints (ball and socket, hinge, slider, fixed) into the physics world. You can also see how
to set the motor or limits of the joints.
\subsection{Collision Shapes Scene}
In this scene, you will see how to create a floor (using the Box Shape) and some other bodies using the different collision shapes available
in the ReactPhysics3D library like capsules, spheres, boxes and convex meshes. Those bodies will fall down to the floor.
\subsection{Heightfield Scene}
In this scene, you will see how to use the Height field collision shape of the library. Several bodies will fall
down to the height field.
\subsection{Raycast Scene}
In this scene, you will see how to use the ray casting methods of the library. Several rays are thrown against the different collision shapes.
It is possible to switch from a collision shape to another using the spacebar key.
\subsection{Collision Detection Scene}
This scene has a physics world and several collision bodies that can be move around with keyboard keys. This scene shows how to manually compute
collision detection in a physics world.
\subsection{Concave Mesh Scene}
In this scene, you will see how to use the static concave mesh collision shape of the library.
\subsection{Pile Scene}
This demo is basically a pile of many bodies with different types of shapes.
\section{Receiving Feedback}
\label{sec:receiving_feedback}
@ -2092,6 +2096,13 @@ world->setEventListener(&listener);
will be no contact points in the contact pair. \\
\end{sloppypar}
\begin{sloppypar}
As you know, rigid bodies can sleep. During that time, no contacts will be reported using the \texttt{EventListener::onContact()} method. Therefore,
If you stop receiving contact notifications for a rigid body, it does not necessarily mean that there is no contacts anymore but it could mean that the
body has fallen asleep. You need to use the \texttt{getEventType()} method to know if the body is not colliding anymore (when you receive an event of type
\texttt{ContactExit}). \\
\end{sloppypar}
\begin{sloppypar}
In the following example, you can see how to override the \texttt{EventListener::onContact()} method to get the current contact points of the physics
world: \\
@ -2148,7 +2159,14 @@ class YourEventListener : public EventListener {
The overlapping pair also has a \texttt{getEventType()} method that gives information about the type of overlapping event for the pair. It can be
\texttt{OverlapStart} if the two bodies of the pair where not overlapping in the previous call to \texttt{PhysicsWorld::update()} and are now
overlapping. It can be \texttt{OverlapStay}, if the two bodies where overlapping in the previous frame and are still overlapping or it can be
\texttt{OverlapExit} if the two bodies where overlapping in the previous frame but are not overlapping anymore.
\texttt{OverlapExit} if the two bodies where overlapping in the previous frame but are not overlapping anymore. \\
\end{sloppypar}
\begin{sloppypar}
As you know, rigid bodies can sleep. During that time, no overlap will be reported using the \texttt{EventListener::onTrigger()} method. Therefore,
If you stop receiving trigger overlap notifications for a rigid body, it does not necessarily mean that there is no overlap anymore but it could mean
that the body has fallen asleep. You need to use the \texttt{getEventType()} method to know if the body is not overlapping anymore (when you receive an
event of type \texttt{OverlapExit}). \\
\end{sloppypar}
Note that the \texttt{onTrigger()} method is only called for colliders that you have set as triggers using the \texttt{Collider::setIsTrigger()} method.
@ -2169,21 +2187,27 @@ class YourEventListener : public EventListener {
\section{Logger}
\label{sec:logger}
ReactPhysics3D has an internal logger that can be used to get logs while running the application. This can be useful for debugging for instance. \\
ReactPhysics3D has an internal logger that can be used to get logs from the library while the application is running. This can be useful for
debugging for instance. \\
The logger is part of the \texttt{PhysicsCommon} class. By default there is no logger set. If you want to create your custom logger to receive logs
from ReactPhysics3D, you can inherit the \texttt{Logger} class and override the \texttt{Logger::log()} method. Then, you have to use the
\texttt{PhysicsCommon::setLogger()} method to set the logger. \\
Getting the logs is the way for you to see the errors reported by the library and therefore, you should not just ignore the errors from the logs.
You should at least redirect the logs (warnings and errors) in the standard output while debugging your application as described in the example
below. \\
\begin{sloppypar}
If you don't want to create your custom logger class, you can use the default logger of ReactPhysics3D (class \texttt{DefaultLogger}). With this
logger, you can output the logs into
a file or a std::stream. The logs can have different format like raw text of HTML. In order to create a default logger, you need to call the
\texttt{PhysicsCommon::createDefaultLogger()} method. Then, you can customize this default logger and finally, you need to set this logger using the
a file or a std::stream. The logs can have different format like raw text of HTML. In order to instantiate the default logger, you need to call the
\texttt{PhysicsCommon::createDefaultLogger()} method. Then, you can customize this logger and finally, you need to set this logger using the
\texttt{PhysicsCommon::setLogger()} method. \\
\end{sloppypar}
The following code shows how to create a default logger that will output logs (warning and errors) in HTML into a file: \\
The following code shows how to create a default logger that will output logs (warning and errors) in HTML into a file and in raw text into
the standard output: \\
\begin{lstlisting}
// Create the default logger
@ -2193,8 +2217,10 @@ DefaultLogger* logger = physicsCommon.createDefaultLogger();
uint logLevel = static_cast<uint>(static_cast<uint>(Logger::Level::Warning) | static_cast<uint>(Logger::Level::Error);
// Output the logs into an HTML file
logger->addFileDestination("rp3d_log_" + name + ".html", logLevel,
DefaultLogger::Format::HTML);
logger->addFileDestination("rp3d_log_" + name + ".html", logLevel, DefaultLogger::Format::HTML);
// Output the logs into the standard output
logger->addStreamDestination(std::cout, logLevel, DefaultLogger::Format::Text);
// Set the logger
physicsCommon.setLogger(logger);
@ -2253,6 +2279,16 @@ debugRenderer.setIsDebugItemDisplayed(DebugRenderer::DebugItem::CONTACT_NORMAL,
are defined in world-space coordinates of the physics world.
\end{sloppypar}
\section{Determinism}
\label{sec:determinism}
Sometimes, it is important that the simulation of a physics world behaves exactly the same each time we run it. Because of the differences in
compilers and computer hardware it is quite difficult to achieve this between different machines. However, ReactPhysics3D should be deterministic when
compiled with the same compiler and running on the same machine. In order to obtain two similar runs of the simulation of a physics world, it is
adviced to completely destroy and recreate the physics world, the bodies and the joints inside it (in order to reset all the internal data cached
for the simulation). You must also create the bodies and joints in the same order each time and make sure that all the calls to the methods
of your physics world, bodies and joints happen in the same order.
\section{API Reference Documentation}
ReactPhysics3D contains Doxygen documentation for its API. \\

View File

@ -10,7 +10,7 @@
\vskip 1.3cm
{\Huge \@title\par}%
\vskip 0.3cm
{\Large Version: 0.8.0\par}%
{\Large Version: 0.9.0\par}%
\vskip 0.3cm
{\Large \@author\par}%
\vskip 2cm

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -75,7 +75,7 @@ class CollisionBody {
void removeAllColliders();
/// Update the broad-phase state for this body (because it has moved for instance)
void updateBroadPhaseState(decimal timeStep) const;
void updateBroadPhaseState() const;
/// Ask the broad-phase to test again the collision shapes of the body for collision
/// (as if the body has moved).
@ -137,13 +137,13 @@ class CollisionBody {
AABB getAABB() const;
/// Return a const pointer to a given collider of the body
const Collider* getCollider(uint colliderIndex) const;
const Collider* getCollider(uint32 colliderIndex) const;
/// Return a pointer to a given collider of the body
Collider* getCollider(uint colliderIndex);
Collider* getCollider(uint32 colliderIndex);
/// Return the number of colliders associated with this body
uint getNbColliders() const;
uint32 getNbColliders() const;
/// Return the world-space coordinates of a point given the local-space coordinates of the body
Vector3 getWorldPoint(const Vector3& localPoint) const;
@ -178,7 +178,7 @@ class CollisionBody {
* @param worldAABB The AABB (in world-space coordinates) that will be used to test overlap
* @return True if the given AABB overlaps with the AABB of the collision body
*/
inline bool CollisionBody::testAABBOverlap(const AABB& worldAABB) const {
RP3D_FORCE_INLINE bool CollisionBody::testAABBOverlap(const AABB& worldAABB) const {
return worldAABB.testCollision(getAABB());
}
@ -186,14 +186,14 @@ inline bool CollisionBody::testAABBOverlap(const AABB& worldAABB) const {
/**
* @return The entity of the body
*/
inline Entity CollisionBody::getEntity() const {
RP3D_FORCE_INLINE Entity CollisionBody::getEntity() const {
return mEntity;
}
#ifdef IS_RP3D_PROFILING_ENABLED
// Set the profiler
inline void CollisionBody::setProfiler(Profiler* profiler) {
RP3D_FORCE_INLINE void CollisionBody::setProfiler(Profiler* profiler) {
mProfiler = profiler;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -53,11 +53,8 @@ class RigidBody : public CollisionBody {
// -------------------- Methods -------------------- //
/// Set the variable to know whether or not the body is sleeping
void setIsSleeping(bool isSleeping);
/// Update whether the current overlapping pairs where this body is involed are active or not
void updateOverlappingPairs();
void resetOverlappingPairs();
/// Compute and return the local-space center of mass of the body using its colliders
Vector3 computeCenterOfMass() const;
@ -65,8 +62,8 @@ class RigidBody : public CollisionBody {
/// Compute the local-space inertia tensor and total mass of the body using its colliders
void computeMassAndInertiaTensorLocal(Vector3& inertiaTensorLocal, decimal& totalMass) const;
/// Return the inverse of the inertia tensor in world coordinates.
static const Matrix3x3 getWorldInertiaTensorInverse(PhysicsWorld& world, Entity bodyEntity);
/// Compute the inverse of the inertia tensor in world coordinates.
static void computeWorldInertiaTensorInverse(const Matrix3x3& orientation, const Vector3& inverseInertiaTensorLocal, Matrix3x3& outInverseInertiaTensorWorld);
public :
@ -141,6 +138,9 @@ class RigidBody : public CollisionBody {
/// Set the variable to know if the gravity is applied to this rigid body
void enableGravity(bool isEnabled);
/// Set the variable to know whether or not the body is sleeping
void setIsSleeping(bool isSleeping);
/// Return the linear velocity damping factor
decimal getLinearDamping() const;
@ -153,17 +153,53 @@ class RigidBody : public CollisionBody {
/// Set the angular damping factor
void setAngularDamping(decimal angularDamping);
/// Apply an external force to the body at its center of mass.
void applyForceToCenterOfMass(const Vector3& force);
/// Return the lock translation factor
const Vector3& getLinearLockAxisFactor() const;
/// Apply an external force to the body at a given point (in local-space coordinates).
void applyForceAtLocalPosition(const Vector3& force, const Vector3& point);
/// Set the linear lock factor
void setLinearLockAxisFactor(const Vector3& linearLockAxisFactor) const;
/// Apply an external force to the body at a given point (in world-space coordinates).
void applyForceAtWorldPosition(const Vector3& force, const Vector3& point);
/// Return the lock rotation factor
const Vector3& getAngularLockAxisFactor() const;
/// Apply an external torque to the body.
void applyTorque(const Vector3& torque);
/// Set the lock rotation factor
void setAngularLockAxisFactor(const Vector3& angularLockAxisFactor) const;
/// Manually apply an external force (in local-space) to the body at its center of mass.
void applyLocalForceAtCenterOfMass(const Vector3& force);
/// Manually apply an external force (in world-space) to the body at its center of mass.
void applyWorldForceAtCenterOfMass(const Vector3& force);
/// Manually apply an external force (in local-space) to the body at a given point (in local-space).
void applyLocalForceAtLocalPosition(const Vector3& force, const Vector3& point);
/// Manually apply an external force (in world-space) to the body at a given point (in local-space).
void applyWorldForceAtLocalPosition(const Vector3& force, const Vector3& point);
/// Manually apply an external force (in local-space) to the body at a given point (in world-space).
void applyLocalForceAtWorldPosition(const Vector3& force, const Vector3& point);
/// Manually apply an external force (in world-space) to the body at a given point (in world-space).
void applyWorldForceAtWorldPosition(const Vector3& force, const Vector3& point);
/// Manually apply an external torque to the body (in world-space).
void applyWorldTorque(const Vector3& torque);
/// Manually apply an external torque to the body (in local-space).
void applyLocalTorque(const Vector3& torque);
/// Reset the manually applied force to zero
void resetForce();
/// Reset the manually applied torque to zero
void resetTorque();
/// Return the total manually applied force on the body (in world-space)
const Vector3& getForce() const;
/// Return the total manually applied torque on the body (in world-space)
const Vector3& getTorque() const;
/// Return whether or not the body is allowed to sleep
bool isAllowedToSleep() const;
@ -204,8 +240,27 @@ class RigidBody : public CollisionBody {
friend class SolveHingeJointSystem;
friend class SolveSliderJointSystem;
friend class Joint;
friend class Collider;
};
/// Compute the inverse of the inertia tensor in world coordinates.
RP3D_FORCE_INLINE void RigidBody::computeWorldInertiaTensorInverse(const Matrix3x3& orientation, const Vector3& inverseInertiaTensorLocal, Matrix3x3& outInverseInertiaTensorWorld) {
outInverseInertiaTensorWorld[0][0] = orientation[0][0] * inverseInertiaTensorLocal.x;
outInverseInertiaTensorWorld[0][1] = orientation[1][0] * inverseInertiaTensorLocal.x;
outInverseInertiaTensorWorld[0][2] = orientation[2][0] * inverseInertiaTensorLocal.x;
outInverseInertiaTensorWorld[1][0] = orientation[0][1] * inverseInertiaTensorLocal.y;
outInverseInertiaTensorWorld[1][1] = orientation[1][1] * inverseInertiaTensorLocal.y;
outInverseInertiaTensorWorld[1][2] = orientation[2][1] * inverseInertiaTensorLocal.y;
outInverseInertiaTensorWorld[2][0] = orientation[0][2] * inverseInertiaTensorLocal.z;
outInverseInertiaTensorWorld[2][1] = orientation[1][2] * inverseInertiaTensorLocal.z;
outInverseInertiaTensorWorld[2][2] = orientation[2][2] * inverseInertiaTensorLocal.z;
outInverseInertiaTensorWorld = orientation * outInverseInertiaTensorWorld;
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -59,9 +59,6 @@ class Collider {
/// Pointer to the parent body
CollisionBody* mBody;
/// Material properties of the rigid body
Material mMaterial;
/// Pointer to user data
void* mUserData;
@ -188,7 +185,7 @@ class Collider {
/**
* @return The entity of the collider
*/
inline Entity Collider::getEntity() const {
RP3D_FORCE_INLINE Entity Collider::getEntity() const {
return mEntity;
}
@ -196,7 +193,7 @@ inline Entity Collider::getEntity() const {
/**
* @return Pointer to the parent body
*/
inline CollisionBody* Collider::getBody() const {
RP3D_FORCE_INLINE CollisionBody* Collider::getBody() const {
return mBody;
}
@ -204,7 +201,7 @@ inline CollisionBody* Collider::getBody() const {
/**
* @return A pointer to the user data stored into the collider
*/
inline void* Collider::getUserData() const {
RP3D_FORCE_INLINE void* Collider::getUserData() const {
return mUserData;
}
@ -212,7 +209,7 @@ inline void* Collider::getUserData() const {
/**
* @param userData Pointer to the user data you want to store within the collider
*/
inline void Collider::setUserData(void* userData) {
RP3D_FORCE_INLINE void Collider::setUserData(void* userData) {
mUserData = userData;
}
@ -221,18 +218,10 @@ inline void Collider::setUserData(void* userData) {
* @param worldAABB The AABB (in world-space coordinates) that will be used to test overlap
* @return True if the given AABB overlaps with the AABB of the collision body
*/
inline bool Collider::testAABBOverlap(const AABB& worldAABB) const {
RP3D_FORCE_INLINE bool Collider::testAABBOverlap(const AABB& worldAABB) const {
return worldAABB.testCollision(getWorldAABB());
}
// Return a reference to the material properties of the collider
/**
* @return A reference to the material of the body
*/
inline Material& Collider::getMaterial() {
return mMaterial;
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -27,7 +27,7 @@
#define REACTPHYSICS3D_COLLISION_CALLBACK_H
// Libraries
#include <reactphysics3d/containers/List.h>
#include <reactphysics3d/containers/Array.h>
#include <reactphysics3d/collision/ContactPair.h>
#include <reactphysics3d/constraint/ContactPoint.h>
@ -114,7 +114,7 @@ class CollisionCallback {
// Class ContactPair
/**
* This class represents the contact between two colliders of the physics world.
* A contact pair contains a list of contact points.
* A contact pair contains an array of contact points.
*/
class ContactPair {
@ -141,7 +141,7 @@ class CollisionCallback {
const reactphysics3d::ContactPair& mContactPair;
/// Pointer to the contact points
List<reactphysics3d::ContactPoint>* mContactPoints;
Array<reactphysics3d::ContactPoint>* mContactPoints;
/// Reference to the physics world
PhysicsWorld& mWorld;
@ -152,7 +152,7 @@ class CollisionCallback {
// -------------------- Methods -------------------- //
/// Constructor
ContactPair(const reactphysics3d::ContactPair& contactPair, List<reactphysics3d::ContactPoint>* contactPoints,
ContactPair(const reactphysics3d::ContactPair& contactPair, Array<reactphysics3d::ContactPoint>* contactPoints,
PhysicsWorld& world, bool mIsLostContactPair);
public:
@ -172,14 +172,14 @@ class CollisionCallback {
/**
* @return The number of contact points in the contact pair
*/
uint getNbContactPoints() const;
uint32 getNbContactPoints() const;
/// Return a given contact point
/**
* @param index Index of the contact point to retrieve
* @return A contact point object
*/
ContactPoint getContactPoint(uint index) const;
ContactPoint getContactPoint(uint32 index) const;
/// Return a pointer to the first body in contact
/**
@ -226,23 +226,23 @@ class CollisionCallback {
// -------------------- Attributes -------------------- //
/// Pointer to the list of contact pairs (contains contacts and triggers events)
List<reactphysics3d::ContactPair>* mContactPairs;
/// Pointer to the array of contact pairs (contains contacts and triggers events)
Array<reactphysics3d::ContactPair>* mContactPairs;
/// Pointer to the list of contact manifolds
List<ContactManifold>* mContactManifolds;
/// Pointer to the array of contact manifolds
Array<ContactManifold>* mContactManifolds;
/// Pointer to the contact points
List<reactphysics3d::ContactPoint>* mContactPoints;
Array<reactphysics3d::ContactPoint>* mContactPoints;
/// Pointer to the list of lost contact pairs (contains contacts and triggers events)
List<reactphysics3d::ContactPair>& mLostContactPairs;
/// Pointer to the array of lost contact pairs (contains contacts and triggers events)
Array<reactphysics3d::ContactPair>& mLostContactPairs;
/// List of indices of the mContactPairs list that are contact events (not overlap/triggers)
List<uint> mContactPairsIndices;
/// Array of indices in the mContactPairs array that are contact events (not overlap/triggers)
Array<uint64> mContactPairsIndices;
/// List of indices of the mLostContactPairs list that are contact events (not overlap/triggers)
List<uint> mLostContactPairsIndices;
/// Array of indices in the mLostContactPairs array that are contact events (not overlap/triggers)
Array<uint64> mLostContactPairsIndices;
/// Reference to the physics world
PhysicsWorld& mWorld;
@ -250,8 +250,8 @@ class CollisionCallback {
// -------------------- Methods -------------------- //
/// Constructor
CallbackData(List<reactphysics3d::ContactPair>* contactPairs, List<ContactManifold>* manifolds,
List<reactphysics3d::ContactPoint>* contactPoints, List<reactphysics3d::ContactPair>& lostContactPairs,
CallbackData(Array<reactphysics3d::ContactPair>* contactPairs, Array<ContactManifold>* manifolds,
Array<reactphysics3d::ContactPoint>* contactPoints, Array<reactphysics3d::ContactPair>& lostContactPairs,
PhysicsWorld& world);
/// Deleted copy constructor
@ -271,14 +271,14 @@ class CollisionCallback {
/**
* @return The number of contact pairs
*/
uint getNbContactPairs() const;
uint32 getNbContactPairs() const;
/// Return a given contact pair
/**
* @param index Index of the contact pair to retrieve
* @return A contact pair object
*/
ContactPair getContactPair(uint index) const;
ContactPair getContactPair(uint64 index) const;
// -------------------- Friendship -------------------- //
@ -296,15 +296,15 @@ class CollisionCallback {
/**
* @return The number of contact pairs
*/
inline uint CollisionCallback::CallbackData::getNbContactPairs() const {
return mContactPairsIndices.size() + mLostContactPairsIndices.size();
RP3D_FORCE_INLINE uint32 CollisionCallback::CallbackData::getNbContactPairs() const {
return static_cast<uint32>(mContactPairsIndices.size() + mLostContactPairsIndices.size());
}
// Return the number of contact points in the contact pair
/**
* @return The number of contact points
*/
inline uint CollisionCallback::ContactPair::getNbContactPoints() const {
RP3D_FORCE_INLINE uint32 CollisionCallback::ContactPair::getNbContactPoints() const {
return mContactPair.nbToTalContactPoints;
}
@ -312,7 +312,7 @@ inline uint CollisionCallback::ContactPair::getNbContactPoints() const {
/**
* @return The penetration depth (larger than zero)
*/
inline decimal CollisionCallback::ContactPoint::getPenetrationDepth() const {
RP3D_FORCE_INLINE decimal CollisionCallback::ContactPoint::getPenetrationDepth() const {
return mContactPoint.getPenetrationDepth();
}
@ -320,7 +320,7 @@ inline decimal CollisionCallback::ContactPoint::getPenetrationDepth() const {
/**
* @return The contact normal direction at the contact point (in world-space)
*/
inline const Vector3& CollisionCallback::ContactPoint::getWorldNormal() const {
RP3D_FORCE_INLINE const Vector3& CollisionCallback::ContactPoint::getWorldNormal() const {
return mContactPoint.getNormal();
}
@ -328,7 +328,7 @@ inline const Vector3& CollisionCallback::ContactPoint::getWorldNormal() const {
/**
* @return The contact point in the local-space of the first collider (from body1) in contact
*/
inline const Vector3& CollisionCallback::ContactPoint::getLocalPointOnCollider1() const {
RP3D_FORCE_INLINE const Vector3& CollisionCallback::ContactPoint::getLocalPointOnCollider1() const {
return mContactPoint.getLocalPointOnShape1();
}
@ -336,7 +336,7 @@ inline const Vector3& CollisionCallback::ContactPoint::getLocalPointOnCollider1(
/**
* @return The contact point in the local-space of the second collider (from body2) in contact
*/
inline const Vector3& CollisionCallback::ContactPoint::getLocalPointOnCollider2() const {
RP3D_FORCE_INLINE const Vector3& CollisionCallback::ContactPoint::getLocalPointOnCollider2() const {
return mContactPoint.getLocalPointOnShape2();
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -34,7 +34,7 @@ namespace reactphysics3d {
// Class declarations
class ContactManifold;
class ContactManifoldInfo;
struct ContactManifoldInfo;
struct ContactPointInfo;
class CollisionBody;
class ContactPoint;
@ -58,12 +58,12 @@ class ContactManifold {
// -------------------- Constants -------------------- //
/// Maximum number of contact points in a reduced contact manifold
const int MAX_CONTACT_POINTS_IN_MANIFOLD = 4;
static constexpr int MAX_CONTACT_POINTS_IN_MANIFOLD = 4;
// -------------------- Attributes -------------------- //
/// Index of the first contact point of the manifold in the list of contact points
uint contactPointsIndex;
/// Index of the first contact point of the manifold in the array of contact points
uint32 contactPointsIndex;
/// Entity of the first body in contact
Entity bodyEntity1;
@ -78,7 +78,7 @@ class ContactManifold {
Entity colliderEntity2;
/// Number of contacts in the cache
int8 nbContactPoints;
uint8 nbContactPoints;
/// First friction vector of the contact manifold
Vector3 frictionVector1;
@ -95,9 +95,6 @@ class ContactManifold {
/// Twist friction constraint accumulated impulse
decimal frictionTwistImpulse;
/// Accumulated rolling resistance impulse
Vector3 rollingResistanceImpulse;
/// True if the contact manifold has already been added into an island
bool isAlreadyInIsland;
@ -107,16 +104,7 @@ class ContactManifold {
/// Constructor
ContactManifold(Entity bodyEntity1, Entity bodyEntity2, Entity colliderEntity1, Entity colliderEntity2,
uint contactPointsIndex, int8 nbContactPoints);
/// Destructor
~ContactManifold();
/// Copy-constructor
ContactManifold(const ContactManifold& contactManifold) = default;
/// Assignment operator
ContactManifold& operator=(const ContactManifold& contactManifold) = default;
uint32 contactPointsIndex, uint8 nbContactPoints);
// -------------------- Friendship -------------------- //

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -45,8 +45,12 @@ struct ContactManifoldInfo {
// -------------------- Attributes -------------------- //
/// Number of potential contact points
uint8 nbPotentialContactPoints;
/// Indices of the contact points in the mPotentialContactPoints array
List<uint> potentialContactPointsIndices;
uint32 potentialContactPointsIndices[NB_MAX_CONTACT_POINTS_IN_POTENTIAL_MANIFOLD];
/// Overlapping pair id
uint64 pairId;
@ -54,8 +58,7 @@ struct ContactManifoldInfo {
// -------------------- Methods -------------------- //
/// Constructor
ContactManifoldInfo(uint64 pairId, MemoryAllocator& allocator)
: potentialContactPointsIndices(allocator), pairId(pairId) {
ContactManifoldInfo(uint64 pairId) : nbPotentialContactPoints(0), potentialContactPointsIndices{0}, pairId(pairId) {
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -47,8 +47,11 @@ struct ContactPair {
/// Overlapping pair Id
uint64 pairId;
/// Number of potential contact manifolds
uint8 nbPotentialContactManifolds;
/// Indices of the potential contact manifolds
List<uint> potentialContactManifoldsIndices;
uint32 potentialContactManifoldsIndices[NB_MAX_POTENTIAL_CONTACT_MANIFOLDS];
/// Entity of the first body of the contact
Entity body1Entity;
@ -66,19 +69,19 @@ struct ContactPair {
bool isAlreadyInIsland;
/// Index of the contact pair in the array of pairs
uint contactPairIndex;
uint32 contactPairIndex;
/// Index of the first contact manifold in the array
uint contactManifoldsIndex;
uint32 contactManifoldsIndex;
/// Number of contact manifolds
int8 nbContactManifolds;
uint32 nbContactManifolds;
/// Index of the first contact point in the array of contact points
uint contactPointsIndex;
uint32 contactPointsIndex;
/// Total number of contact points in all the manifolds of the contact pair
uint nbToTalContactPoints;
uint32 nbToTalContactPoints;
/// True if the colliders of the pair were already colliding in the previous frame
bool collidingInPreviousFrame;
@ -90,13 +93,21 @@ struct ContactPair {
/// Constructor
ContactPair(uint64 pairId, Entity body1Entity, Entity body2Entity, Entity collider1Entity,
Entity collider2Entity, uint contactPairIndex, bool collidingInPreviousFrame, bool isTrigger, MemoryAllocator& allocator)
: pairId(pairId), potentialContactManifoldsIndices(allocator), body1Entity(body1Entity), body2Entity(body2Entity),
Entity collider2Entity, uint32 contactPairIndex, bool collidingInPreviousFrame, bool isTrigger)
: pairId(pairId), nbPotentialContactManifolds(0), potentialContactManifoldsIndices{0}, body1Entity(body1Entity), body2Entity(body2Entity),
collider1Entity(collider1Entity), collider2Entity(collider2Entity),
isAlreadyInIsland(false), contactPairIndex(contactPairIndex), contactManifoldsIndex(0), nbContactManifolds(0),
contactPointsIndex(0), nbToTalContactPoints(0), collidingInPreviousFrame(collidingInPreviousFrame), isTrigger(isTrigger) {
}
// Remove a potential manifold at a given index in the array
void removePotentialManifoldAtIndex(uint32 index) {
assert(index < nbPotentialContactManifolds);
potentialContactManifoldsIndices[index] = potentialContactManifoldsIndices[nbPotentialContactManifolds - 1];
nbPotentialContactManifolds--;
}
};
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -45,10 +45,6 @@ class CollisionBody;
*/
struct ContactPointInfo {
private:
// -------------------- Methods -------------------- //
public:
// -------------------- Attributes -------------------- //
@ -56,29 +52,15 @@ struct ContactPointInfo {
/// Normalized normal vector of the collision contact in world space
Vector3 normal;
/// Penetration depth of the contact
decimal penetrationDepth;
/// Contact point of body 1 in local space of body 1
Vector3 localPoint1;
/// Contact point of body 2 in local space of body 2
Vector3 localPoint2;
// -------------------- Methods -------------------- //
/// Penetration depth of the contact
decimal penetrationDepth;
/// Constructor
ContactPointInfo(const Vector3& contactNormal, decimal penDepth,
const Vector3& localPt1, const Vector3& localPt2)
: normal(contactNormal), penetrationDepth(penDepth),
localPoint1(localPt1), localPoint2(localPt2) {
assert(contactNormal.lengthSquare() > decimal(0.8));
assert(penDepth > decimal(0.0));
}
/// Destructor
~ContactPointInfo() = default;
};
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -41,35 +41,35 @@ class HalfEdgeStructure {
public:
using VerticesPair = Pair<uint, uint>;
using VerticesPair = Pair<uint32, uint32>;
/// Edge
struct Edge {
uint vertexIndex; // Index of the vertex at the beginning of the edge
uint twinEdgeIndex; // Index of the twin edge
uint faceIndex; // Adjacent face index of the edge
uint nextEdgeIndex; // Index of the next edge
uint32 vertexIndex; // Index of the vertex at the beginning of the edge
uint32 twinEdgeIndex; // Index of the twin edge
uint32 faceIndex; // Adjacent face index of the edge
uint32 nextEdgeIndex; // Index of the next edge
};
/// Face
struct Face {
uint edgeIndex; // Index of an half-edge of the face
List<uint> faceVertices; // Index of the vertices of the face
uint32 edgeIndex; // Index of an half-edge of the face
Array<uint32> faceVertices; // Index of the vertices of the face
/// Constructor
Face(MemoryAllocator& allocator) : faceVertices(allocator) {}
Face(MemoryAllocator& allocator) : edgeIndex(0), faceVertices(allocator) {}
/// Constructor
Face(List<uint> vertices) : faceVertices(vertices) {}
Face(Array<uint32> vertices) : edgeIndex(0), faceVertices(vertices) {}
};
/// Vertex
struct Vertex {
uint vertexPointIndex; // Index of the vertex point in the origin vertex array
uint edgeIndex; // Index of one edge emanting from this vertex
uint32 vertexPointIndex; // Index of the vertex point in the origin vertex array
uint32 edgeIndex; // Index of one edge emanting from this vertex
/// Constructor
Vertex(uint vertexCoordsIndex) : vertexPointIndex(vertexCoordsIndex) { }
Vertex(uint32 vertexCoordsIndex) : vertexPointIndex(vertexCoordsIndex), edgeIndex(0) { }
};
private:
@ -78,19 +78,19 @@ class HalfEdgeStructure {
MemoryAllocator& mAllocator;
/// All the faces
List<Face> mFaces;
Array<Face> mFaces;
/// All the vertices
List<Vertex> mVertices;
Array<Vertex> mVertices;
/// All the half-edges
List<Edge> mEdges;
Array<Edge> mEdges;
public:
/// Constructor
HalfEdgeStructure(MemoryAllocator& allocator, uint facesCapacity, uint verticesCapacity,
uint edgesCapacity) :mAllocator(allocator), mFaces(allocator, facesCapacity),
HalfEdgeStructure(MemoryAllocator& allocator, uint32 facesCapacity, uint32 verticesCapacity,
uint32 edgesCapacity) :mAllocator(allocator), mFaces(allocator, facesCapacity),
mVertices(allocator, verticesCapacity), mEdges(allocator, edgesCapacity) {}
/// Destructor
@ -100,28 +100,28 @@ class HalfEdgeStructure {
void init();
/// Add a vertex
uint addVertex(uint vertexPointIndex);
uint32 addVertex(uint32 vertexPointIndex);
/// Add a face
void addFace(List<uint> faceVertices);
void addFace(Array<uint32> faceVertices);
/// Return the number of faces
uint getNbFaces() const;
uint32 getNbFaces() const;
/// Return the number of half-edges
uint getNbHalfEdges() const;
uint32 getNbHalfEdges() const;
/// Return the number of vertices
uint getNbVertices() const;
uint32 getNbVertices() const;
/// Return a given face
const Face& getFace(uint index) const;
const Face& getFace(uint32 index) const;
/// Return a given edge
const Edge& getHalfEdge(uint index) const;
const Edge& getHalfEdge(uint32 index) const;
/// Return a given vertex
const Vertex& getVertex(uint index) const;
const Vertex& getVertex(uint32 index) const;
};
@ -129,18 +129,18 @@ class HalfEdgeStructure {
/**
* @param vertexPointIndex Index of the vertex in the vertex data array
*/
inline uint HalfEdgeStructure::addVertex(uint vertexPointIndex) {
RP3D_FORCE_INLINE uint32 HalfEdgeStructure::addVertex(uint32 vertexPointIndex) {
Vertex vertex(vertexPointIndex);
mVertices.add(vertex);
return mVertices.size() - 1;
return static_cast<uint32>(mVertices.size()) - 1;
}
// Add a face
/**
* @param faceVertices List of the vertices in a face (ordered in CCW order as seen from outside
* @param faceVertices Array of the vertices in a face (ordered in CCW order as seen from outside
* the polyhedron
*/
inline void HalfEdgeStructure::addFace(List<uint> faceVertices) {
RP3D_FORCE_INLINE void HalfEdgeStructure::addFace(Array<uint32> faceVertices) {
// Create a new face
Face face(faceVertices);
@ -151,31 +151,31 @@ inline void HalfEdgeStructure::addFace(List<uint> faceVertices) {
/**
* @return The number of faces in the polyhedron
*/
inline uint HalfEdgeStructure::getNbFaces() const {
return static_cast<uint>(mFaces.size());
RP3D_FORCE_INLINE uint32 HalfEdgeStructure::getNbFaces() const {
return static_cast<uint32>(mFaces.size());
}
// Return the number of edges
/**
* @return The number of edges in the polyhedron
*/
inline uint HalfEdgeStructure::getNbHalfEdges() const {
return static_cast<uint>(mEdges.size());
RP3D_FORCE_INLINE uint32 HalfEdgeStructure::getNbHalfEdges() const {
return static_cast<uint32>(mEdges.size());
}
// Return the number of vertices
/**
* @return The number of vertices in the polyhedron
*/
inline uint HalfEdgeStructure::getNbVertices() const {
return static_cast<uint>(mVertices.size());
RP3D_FORCE_INLINE uint32 HalfEdgeStructure::getNbVertices() const {
return static_cast<uint32>(mVertices.size());
}
// Return a given face
/**
* @return A given face of the polyhedron
*/
inline const HalfEdgeStructure::Face& HalfEdgeStructure::getFace(uint index) const {
RP3D_FORCE_INLINE const HalfEdgeStructure::Face& HalfEdgeStructure::getFace(uint32 index) const {
assert(index < mFaces.size());
return mFaces[index];
}
@ -184,7 +184,7 @@ inline const HalfEdgeStructure::Face& HalfEdgeStructure::getFace(uint index) con
/**
* @return A given edge of the polyhedron
*/
inline const HalfEdgeStructure::Edge& HalfEdgeStructure::getHalfEdge(uint index) const {
RP3D_FORCE_INLINE const HalfEdgeStructure::Edge& HalfEdgeStructure::getHalfEdge(uint32 index) const {
assert(index < mEdges.size());
return mEdges[index];
}
@ -193,7 +193,7 @@ inline const HalfEdgeStructure::Edge& HalfEdgeStructure::getHalfEdge(uint index)
/**
* @return A given vertex of the polyhedron
*/
inline const HalfEdgeStructure::Vertex& HalfEdgeStructure::getVertex(uint index) const {
RP3D_FORCE_INLINE const HalfEdgeStructure::Vertex& HalfEdgeStructure::getVertex(uint32 index) const {
assert(index < mVertices.size());
return mVertices[index];
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -27,7 +27,7 @@
#define REACTPHYSICS3D_OVERLAP_CALLBACK_H
// Libraries
#include <reactphysics3d/containers/List.h>
#include <reactphysics3d/containers/Array.h>
#include <reactphysics3d/collision/ContactPair.h>
/// ReactPhysics3D namespace
@ -131,17 +131,17 @@ class OverlapCallback {
// -------------------- Attributes -------------------- //
/// Reference to the list of contact pairs (contains contacts and triggers events)
List<ContactPair>& mContactPairs;
/// Reference to the array of contact pairs (contains contacts and triggers events)
Array<ContactPair>& mContactPairs;
/// Reference to the list of lost contact pairs (contains contacts and triggers events)
List<ContactPair>& mLostContactPairs;
/// Reference to the array of lost contact pairs (contains contacts and triggers events)
Array<ContactPair>& mLostContactPairs;
/// List of indices of the mContactPairs list that are overlap/triggers events (not contact events)
List<uint> mContactPairsIndices;
/// Array of indices of the mContactPairs array that are overlap/triggers events (not contact events)
Array<uint64> mContactPairsIndices;
/// List of indices of the mLostContactPairs list that are overlap/triggers events (not contact events)
List<uint> mLostContactPairsIndices;
/// Array of indices of the mLostContactPairs array that are overlap/triggers events (not contact events)
Array<uint64> mLostContactPairsIndices;
/// Reference to the physics world
PhysicsWorld& mWorld;
@ -149,7 +149,7 @@ class OverlapCallback {
// -------------------- Methods -------------------- //
/// Constructor
CallbackData(List<ContactPair>& contactPairs, List<ContactPair>& lostContactPairs, bool onlyReportTriggers, PhysicsWorld& world);
CallbackData(Array<ContactPair>& contactPairs, Array<ContactPair>& lostContactPairs, bool onlyReportTriggers, PhysicsWorld& world);
/// Deleted copy constructor
CallbackData(const CallbackData& callbackData) = delete;
@ -165,10 +165,10 @@ class OverlapCallback {
// -------------------- Methods -------------------- //
/// Return the number of overlapping pairs of bodies
uint getNbOverlappingPairs() const;
uint32 getNbOverlappingPairs() const;
/// Return a given overlapping pair of bodies
OverlapPair getOverlappingPair(uint index) const;
OverlapPair getOverlappingPair(uint32 index) const;
// -------------------- Friendship -------------------- //
@ -185,15 +185,15 @@ class OverlapCallback {
};
// Return the number of overlapping pairs of bodies
inline uint OverlapCallback::CallbackData::getNbOverlappingPairs() const {
return mContactPairsIndices.size() + mLostContactPairsIndices.size();
RP3D_FORCE_INLINE uint32 OverlapCallback::CallbackData::getNbOverlappingPairs() const {
return static_cast<uint32>(mContactPairsIndices.size() + mLostContactPairsIndices.size());
}
// Return a given overlapping pair of bodies
/// Note that the returned OverlapPair object is only valid during the call of the CollisionCallback::onOverlap()
/// method. Therefore, you need to get contact data from it and make a copy. Do not make a copy of the OverlapPair
/// object itself because it won't be valid after the CollisionCallback::onOverlap() call.
inline OverlapCallback::OverlapPair OverlapCallback::CallbackData::getOverlappingPair(uint index) const {
RP3D_FORCE_INLINE OverlapCallback::OverlapPair OverlapCallback::CallbackData::getOverlappingPair(uint32 index) const {
assert(index < getNbOverlappingPairs());

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -56,34 +56,34 @@ class PolygonVertexArray {
struct PolygonFace {
/// Number of vertices in the polygon face
uint nbVertices;
uint32 nbVertices;
/// Index of the first vertex of the polygon face
/// inside the array with all vertex indices
uint indexBase;
uint32 indexBase;
};
protected:
/// Number of vertices in the array
uint mNbVertices;
uint32 mNbVertices;
/// Pointer to the first vertex value in the array
const unsigned char* mVerticesStart;
/// Stride (number of bytes) between the beginning of two vertices
/// values in the array
int mVerticesStride;
uint32 mVerticesStride;
/// Pointer to the first vertex index of the array
const unsigned char* mIndicesStart;
/// Stride (number of bytes) between the beginning of two indices in
/// the array
int mIndicesStride;
uint32 mIndicesStride;
/// Number of polygon faces in the array
uint mNbFaces;
uint32 mNbFaces;
/// Pointer to the first polygon face in the polyhedron
PolygonFace* mPolygonFacesStart;
@ -97,9 +97,9 @@ class PolygonVertexArray {
public:
/// Constructor
PolygonVertexArray(uint nbVertices, const void* verticesStart, int verticesStride,
const void* indexesStart, int indexesStride,
uint nbFaces, PolygonFace* facesStart,
PolygonVertexArray(uint32 nbVertices, const void* verticesStart, uint32 verticesStride,
const void* indexesStart, uint32 indexesStride,
uint32 nbFaces, PolygonFace* facesStart,
VertexDataType vertexDataType, IndexDataType indexDataType);
/// Destructor
@ -112,22 +112,22 @@ class PolygonVertexArray {
IndexDataType getIndexDataType() const;
/// Return the number of vertices
uint getNbVertices() const;
uint32 getNbVertices() const;
/// Return the number of faces
uint getNbFaces() const;
uint32 getNbFaces() const;
/// Return the vertices stride (number of bytes)
int getVerticesStride() const;
uint32 getVerticesStride() const;
/// Return the indices stride (number of bytes)
int getIndicesStride() const;
uint32 getIndicesStride() const;
/// Return the vertex index of a given vertex in a face
uint getVertexIndexInFace(uint faceIndex, uint noVertexInFace) const;
uint32 getVertexIndexInFace(uint32 faceIndex32, uint32 noVertexInFace) const;
/// Return a polygon face of the polyhedron
PolygonFace* getPolygonFace(uint faceIndex) const;
PolygonFace* getPolygonFace(uint32 faceIndex) const;
/// Return the pointer to the start of the vertices array
const unsigned char* getVerticesStart() const;
@ -140,7 +140,7 @@ class PolygonVertexArray {
/**
* @return The data type of the vertices in the array
*/
inline PolygonVertexArray::VertexDataType PolygonVertexArray::getVertexDataType() const {
RP3D_FORCE_INLINE PolygonVertexArray::VertexDataType PolygonVertexArray::getVertexDataType() const {
return mVertexDataType;
}
@ -148,7 +148,7 @@ inline PolygonVertexArray::VertexDataType PolygonVertexArray::getVertexDataType(
/**
* @return The data type of the indices in the array
*/
inline PolygonVertexArray::IndexDataType PolygonVertexArray::getIndexDataType() const {
RP3D_FORCE_INLINE PolygonVertexArray::IndexDataType PolygonVertexArray::getIndexDataType() const {
return mIndexDataType;
}
@ -156,7 +156,7 @@ inline PolygonVertexArray::IndexDataType PolygonVertexArray::getIndexDataType()
/**
* @return The number of vertices in the array
*/
inline uint PolygonVertexArray::getNbVertices() const {
RP3D_FORCE_INLINE uint32 PolygonVertexArray::getNbVertices() const {
return mNbVertices;
}
@ -164,7 +164,7 @@ inline uint PolygonVertexArray::getNbVertices() const {
/**
* @return The number of faces in the array
*/
inline uint PolygonVertexArray::getNbFaces() const {
RP3D_FORCE_INLINE uint32 PolygonVertexArray::getNbFaces() const {
return mNbFaces;
}
@ -172,7 +172,7 @@ inline uint PolygonVertexArray::getNbFaces() const {
/**
* @return The number of bytes between two vertices
*/
inline int PolygonVertexArray::getVerticesStride() const {
RP3D_FORCE_INLINE uint32 PolygonVertexArray::getVerticesStride() const {
return mVerticesStride;
}
@ -180,7 +180,7 @@ inline int PolygonVertexArray::getVerticesStride() const {
/**
* @return The number of bytes between two consecutive face indices
*/
inline int PolygonVertexArray::getIndicesStride() const {
RP3D_FORCE_INLINE uint32 PolygonVertexArray::getIndicesStride() const {
return mIndicesStride;
}
@ -189,7 +189,7 @@ inline int PolygonVertexArray::getIndicesStride() const {
* @param faceIndex Index of a given face
* @return A polygon face
*/
inline PolygonVertexArray::PolygonFace* PolygonVertexArray::getPolygonFace(uint faceIndex) const {
RP3D_FORCE_INLINE PolygonVertexArray::PolygonFace* PolygonVertexArray::getPolygonFace(uint32 faceIndex) const {
assert(faceIndex < mNbFaces);
return &mPolygonFacesStart[faceIndex];
}
@ -198,7 +198,7 @@ inline PolygonVertexArray::PolygonFace* PolygonVertexArray::getPolygonFace(uint
/**
* @return A pointer to the start of the vertex array of the polyhedron
*/
inline const unsigned char* PolygonVertexArray::getVerticesStart() const {
RP3D_FORCE_INLINE const unsigned char* PolygonVertexArray::getVerticesStart() const {
return mVerticesStart;
}
@ -206,7 +206,7 @@ inline const unsigned char* PolygonVertexArray::getVerticesStart() const {
/**
* @return A pointer to the start of the face indices array of the polyhedron
*/
inline const unsigned char* PolygonVertexArray::getIndicesStart() const {
RP3D_FORCE_INLINE const unsigned char* PolygonVertexArray::getIndicesStart() const {
return mIndicesStart;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -28,6 +28,7 @@
// Libraries
#include <reactphysics3d/mathematics/mathematics.h>
#include <reactphysics3d/containers/Array.h>
#include "HalfEdgeStructure.h"
namespace reactphysics3d {
@ -69,7 +70,7 @@ class PolyhedronMesh {
PolyhedronMesh(PolygonVertexArray* polygonVertexArray, MemoryAllocator& allocator);
/// Create the half-edge structure of the mesh
void createHalfEdgeStructure();
bool createHalfEdgeStructure();
/// Compute the faces normals
void computeFacesNormals();
@ -78,7 +79,10 @@ class PolyhedronMesh {
void computeCentroid() ;
/// Compute and return the area of a face
decimal getFaceArea(uint faceIndex) const;
decimal getFaceArea(uint32 faceIndex) const;
/// Static factory method to create a polyhedron mesh
static PolyhedronMesh* create(PolygonVertexArray* polygonVertexArray, MemoryAllocator& polyhedronMeshAllocator, MemoryAllocator& dataAllocator);
public:
@ -88,16 +92,16 @@ class PolyhedronMesh {
~PolyhedronMesh();
/// Return the number of vertices
uint getNbVertices() const;
uint32 getNbVertices() const;
/// Return a vertex
Vector3 getVertex(uint index) const;
Vector3 getVertex(uint32 index) const;
/// Return the number of faces
uint getNbFaces() const;
uint32 getNbFaces() const;
/// Return a face normal
Vector3 getFaceNormal(uint faceIndex) const;
Vector3 getFaceNormal(uint32 faceIndex) const;
/// Return the half-edge structure of the mesh
const HalfEdgeStructure& getHalfEdgeStructure() const;
@ -117,7 +121,7 @@ class PolyhedronMesh {
/**
* @return The number of vertices in the mesh
*/
inline uint PolyhedronMesh::getNbVertices() const {
RP3D_FORCE_INLINE uint32 PolyhedronMesh::getNbVertices() const {
return mHalfEdgeStructure.getNbVertices();
}
@ -125,7 +129,7 @@ inline uint PolyhedronMesh::getNbVertices() const {
/**
* @return The number of faces in the mesh
*/
inline uint PolyhedronMesh::getNbFaces() const {
RP3D_FORCE_INLINE uint32 PolyhedronMesh::getNbFaces() const {
return mHalfEdgeStructure.getNbFaces();
}
@ -134,7 +138,7 @@ inline uint PolyhedronMesh::getNbFaces() const {
* @param faceIndex The index of a given face of the mesh
* @return The normal vector of a given face of the mesh
*/
inline Vector3 PolyhedronMesh::getFaceNormal(uint faceIndex) const {
RP3D_FORCE_INLINE Vector3 PolyhedronMesh::getFaceNormal(uint32 faceIndex) const {
assert(faceIndex < mHalfEdgeStructure.getNbFaces());
return mFacesNormals[faceIndex];
}
@ -143,7 +147,7 @@ inline Vector3 PolyhedronMesh::getFaceNormal(uint faceIndex) const {
/**
* @return The Half-Edge structure of the mesh
*/
inline const HalfEdgeStructure& PolyhedronMesh::getHalfEdgeStructure() const {
RP3D_FORCE_INLINE const HalfEdgeStructure& PolyhedronMesh::getHalfEdgeStructure() const {
return mHalfEdgeStructure;
}
@ -151,7 +155,7 @@ inline const HalfEdgeStructure& PolyhedronMesh::getHalfEdgeStructure() const {
/**
* @return The centroid of the mesh
*/
inline Vector3 PolyhedronMesh::getCentroid() const {
RP3D_FORCE_INLINE Vector3 PolyhedronMesh::getCentroid() const {
return mCentroid;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -137,6 +137,7 @@ struct RaycastTest {
/// Constructor
RaycastTest(RaycastCallback* callback) {
userCallback = callback;
}
/// Ray cast test against a collider

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -28,7 +28,7 @@
// Libraries
#include <cassert>
#include <reactphysics3d/containers/List.h>
#include <reactphysics3d/containers/Array.h>
#include <reactphysics3d/memory/MemoryAllocator.h>
namespace reactphysics3d {
@ -49,7 +49,7 @@ class TriangleMesh {
protected:
/// All the triangle arrays of the mesh (one triangle array per part)
List<TriangleVertexArray*> mTriangleArrays;
Array<TriangleVertexArray*> mTriangleArrays;
/// Constructor
TriangleMesh(reactphysics3d::MemoryAllocator& allocator);
@ -63,10 +63,10 @@ class TriangleMesh {
void addSubpart(TriangleVertexArray* triangleVertexArray);
/// Return a pointer to a given subpart (triangle vertex array) of the mesh
TriangleVertexArray* getSubpart(uint indexSubpart) const;
TriangleVertexArray* getSubpart(uint32 indexSubpart) const;
/// Return the number of subparts of the mesh
uint getNbSubparts() const;
uint32 getNbSubparts() const;
// ---------- Friendship ---------- //
@ -78,7 +78,7 @@ class TriangleMesh {
/**
* @param triangleVertexArray Pointer to the TriangleVertexArray to add into the mesh
*/
inline void TriangleMesh::addSubpart(TriangleVertexArray* triangleVertexArray) {
RP3D_FORCE_INLINE void TriangleMesh::addSubpart(TriangleVertexArray* triangleVertexArray) {
mTriangleArrays.add(triangleVertexArray );
}
@ -87,7 +87,7 @@ inline void TriangleMesh::addSubpart(TriangleVertexArray* triangleVertexArray) {
* @param indexSubpart The index of the sub-part of the mesh
* @return A pointer to the triangle vertex array of a given sub-part of the mesh
*/
inline TriangleVertexArray* TriangleMesh::getSubpart(uint indexSubpart) const {
RP3D_FORCE_INLINE TriangleVertexArray* TriangleMesh::getSubpart(uint32 indexSubpart) const {
assert(indexSubpart < mTriangleArrays.size());
return mTriangleArrays[indexSubpart];
}
@ -96,8 +96,8 @@ inline TriangleVertexArray* TriangleMesh::getSubpart(uint indexSubpart) const {
/**
* @return The number of sub-parts of the mesh
*/
inline uint TriangleMesh::getNbSubparts() const {
return mTriangleArrays.size();
RP3D_FORCE_INLINE uint32 TriangleMesh::getNbSubparts() const {
return static_cast<uint32>(mTriangleArrays.size());
}
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -62,30 +62,30 @@ class TriangleVertexArray {
// -------------------- Attributes -------------------- //
/// Number of vertices in the array
uint mNbVertices;
uint32 mNbVertices;
/// Pointer to the first vertex value in the array
const uchar* mVerticesStart;
/// Stride (number of bytes) between the beginning of two vertices
/// values in the array
uint mVerticesStride;
uint32 mVerticesStride;
/// Pointer to the first vertex normal value in the array
const uchar* mVerticesNormalsStart;
/// Stride (number of bytes) between the beginning of two vertex normals
/// values in the array
uint mVerticesNormalsStride;
uint32 mVerticesNormalsStride;
/// Number of triangles in the array
uint mNbTriangles;
uint32 mNbTriangles;
/// Pointer to the first vertex index of the array
const uchar* mIndicesStart;
/// Stride (number of bytes) between the beginning of the three indices of two triangles
uint mIndicesStride;
uint32 mIndicesStride;
/// Data type of the vertices in the array
VertexDataType mVertexDataType;
@ -109,14 +109,14 @@ class TriangleVertexArray {
// -------------------- Methods -------------------- //
/// Constructor without vertices normals
TriangleVertexArray(uint nbVertices, const void* verticesStart, uint verticesStride,
uint nbTriangles, const void* indexesStart, uint indexesStride,
TriangleVertexArray(uint32 nbVertices, const void* verticesStart, uint32 verticesStride,
uint32 nbTriangles, const void* indexesStart, uint32 indexesStride,
VertexDataType vertexDataType, IndexDataType indexDataType);
/// Constructor with vertices normals
TriangleVertexArray(uint nbVertices, const void* verticesStart, uint verticesStride,
const void* verticesNormalsStart, uint uverticesNormalsStride,
uint nbTriangles, const void* indexesStart, uint indexesStride,
TriangleVertexArray(uint32 nbVertices, const void* verticesStart, uint32 verticesStride,
const void* verticesNormalsStart, uint32 uverticesNormalsStride,
uint32 nbTriangles, const void* indexesStart, uint32 indexesStride,
VertexDataType vertexDataType, NormalDataType normalDataType,
IndexDataType indexDataType);
@ -139,19 +139,19 @@ class TriangleVertexArray {
IndexDataType getIndexDataType() const;
/// Return the number of vertices
uint getNbVertices() const;
uint32 getNbVertices() const;
/// Return the number of triangles
uint getNbTriangles() const;
uint32 getNbTriangles() const;
/// Return the vertices stride (number of bytes)
uint getVerticesStride() const;
uint32 getVerticesStride() const;
/// Return the vertex normals stride (number of bytes)
uint getVerticesNormalsStride() const;
uint32 getVerticesNormalsStride() const;
/// Return the indices stride (number of bytes)
uint getIndicesStride() const;
uint32 getIndicesStride() const;
/// Return the pointer to the start of the vertices array
const void* getVerticesStart() const;
@ -163,26 +163,26 @@ class TriangleVertexArray {
const void* getIndicesStart() const;
/// Return the vertices coordinates of a triangle
void getTriangleVertices(uint triangleIndex, Vector3* outTriangleVertices) const;
void getTriangleVertices(uint32 triangleIndex, Vector3* outTriangleVertices) const;
/// Return the three vertices normals of a triangle
void getTriangleVerticesNormals(uint triangleIndex, Vector3* outTriangleVerticesNormals) const;
void getTriangleVerticesNormals(uint32 triangleIndex, Vector3* outTriangleVerticesNormals) const;
/// Return the indices of the three vertices of a given triangle in the array
void getTriangleVerticesIndices(uint triangleIndex, uint* outVerticesIndices) const;
void getTriangleVerticesIndices(uint32 triangleIndex, uint32* outVerticesIndices) const;
/// Return a vertex of the array
void getVertex(uint vertexIndex, Vector3* outVertex);
void getVertex(uint32 vertexIndex, Vector3* outVertex);
/// Return a vertex normal of the array
void getNormal(uint vertexIndex, Vector3* outNormal);
void getNormal(uint32 vertexIndex, Vector3* outNormal);
};
// Return the vertex data type
/**
* @return The data type of the vertices in the array
*/
inline TriangleVertexArray::VertexDataType TriangleVertexArray::getVertexDataType() const {
RP3D_FORCE_INLINE TriangleVertexArray::VertexDataType TriangleVertexArray::getVertexDataType() const {
return mVertexDataType;
}
@ -190,7 +190,7 @@ inline TriangleVertexArray::VertexDataType TriangleVertexArray::getVertexDataTyp
/**
* @return The data type of the normals in the array
*/
inline TriangleVertexArray::NormalDataType TriangleVertexArray::getVertexNormalDataType() const {
RP3D_FORCE_INLINE TriangleVertexArray::NormalDataType TriangleVertexArray::getVertexNormalDataType() const {
return mVertexNormaldDataType;
}
@ -198,7 +198,7 @@ inline TriangleVertexArray::NormalDataType TriangleVertexArray::getVertexNormalD
/**
* @return The data type of the face indices in the array
*/
inline TriangleVertexArray::IndexDataType TriangleVertexArray::getIndexDataType() const {
RP3D_FORCE_INLINE TriangleVertexArray::IndexDataType TriangleVertexArray::getIndexDataType() const {
return mIndexDataType;
}
@ -206,7 +206,7 @@ inline TriangleVertexArray::IndexDataType TriangleVertexArray::getIndexDataType(
/**
* @return The number of vertices in the array
*/
inline uint TriangleVertexArray::getNbVertices() const {
RP3D_FORCE_INLINE uint32 TriangleVertexArray::getNbVertices() const {
return mNbVertices;
}
@ -214,7 +214,7 @@ inline uint TriangleVertexArray::getNbVertices() const {
/**
* @return The number of triangles in the array
*/
inline uint TriangleVertexArray::getNbTriangles() const {
RP3D_FORCE_INLINE uint32 TriangleVertexArray::getNbTriangles() const {
return mNbTriangles;
}
@ -222,7 +222,7 @@ inline uint TriangleVertexArray::getNbTriangles() const {
/**
* @return The number of bytes separating two consecutive vertices in the array
*/
inline uint TriangleVertexArray::getVerticesStride() const {
RP3D_FORCE_INLINE uint32 TriangleVertexArray::getVerticesStride() const {
return mVerticesStride;
}
@ -230,7 +230,7 @@ inline uint TriangleVertexArray::getVerticesStride() const {
/**
* @return The number of bytes separating two consecutive normals in the array
*/
inline uint TriangleVertexArray::getVerticesNormalsStride() const {
RP3D_FORCE_INLINE uint32 TriangleVertexArray::getVerticesNormalsStride() const {
return mVerticesNormalsStride;
}
@ -238,7 +238,7 @@ inline uint TriangleVertexArray::getVerticesNormalsStride() const {
/**
* @return The number of bytes separating two consecutive face indices in the array
*/
inline uint TriangleVertexArray::getIndicesStride() const {
RP3D_FORCE_INLINE uint32 TriangleVertexArray::getIndicesStride() const {
return mIndicesStride;
}
@ -246,7 +246,7 @@ inline uint TriangleVertexArray::getIndicesStride() const {
/**
* @return A pointer to the start of the vertices data in the array
*/
inline const void* TriangleVertexArray::getVerticesStart() const {
RP3D_FORCE_INLINE const void* TriangleVertexArray::getVerticesStart() const {
return mVerticesStart;
}
@ -254,7 +254,7 @@ inline const void* TriangleVertexArray::getVerticesStart() const {
/**
* @return A pointer to the start of the normals data in the array
*/
inline const void* TriangleVertexArray::getVerticesNormalsStart() const {
RP3D_FORCE_INLINE const void* TriangleVertexArray::getVerticesNormalsStart() const {
return mVerticesNormalsStart;
}
@ -262,7 +262,7 @@ inline const void* TriangleVertexArray::getVerticesNormalsStart() const {
/**
* @return A pointer to the start of the face indices data in the array
*/
inline const void* TriangleVertexArray::getIndicesStart() const {
RP3D_FORCE_INLINE const void* TriangleVertexArray::getIndicesStart() const {
return mIndicesStart;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -58,7 +58,7 @@ struct TreeNode {
// -------------------- Attributes -------------------- //
// A node is either in the tree (has a parent) or in the free nodes list
// A node is either in the tree (has a parent) or in the free nodes array
// (has a next node)
union {
@ -90,6 +90,11 @@ struct TreeNode {
// -------------------- Methods -------------------- //
/// Constructor
TreeNode() : nextNodeID(NULL_TREE_NODE), height(-1) {
}
/// Return true if the node is a leaf of the tree
bool isLeaf() const;
};
@ -149,7 +154,7 @@ class DynamicAABBTree {
/// ID of the root node of the tree
int32 mRootNodeID;
/// ID of the first node of the list of free (allocated) nodes in the tree that we can use
/// ID of the first node of the array of free (allocated) nodes in the tree that we can use
int32 mFreeNodeID;
/// Number of allocated nodes in the tree
@ -236,11 +241,11 @@ class DynamicAABBTree {
void* getNodeDataPointer(int32 nodeID) const;
/// Report all shapes overlapping with all the shapes in the map in parameter
void reportAllShapesOverlappingWithShapes(const List<int32>& nodesToTest, size_t startIndex,
size_t endIndex, List<Pair<int32, int32>>& outOverlappingNodes) const;
void reportAllShapesOverlappingWithShapes(const Array<int32>& nodesToTest, uint32 startIndex,
size_t endIndex, Array<Pair<int32, int32>>& outOverlappingNodes) const;
/// Report all shapes overlapping with the AABB given in parameter.
void reportAllShapesOverlappingWithAABB(const AABB& aabb, List<int>& overlappingNodes) const;
void reportAllShapesOverlappingWithAABB(const AABB& aabb, Array<int>& overlappingNodes) const;
/// Ray casting method
void raycast(const Ray& ray, DynamicAABBTreeRaycastCallback& callback) const;
@ -264,38 +269,38 @@ class DynamicAABBTree {
};
// Return true if the node is a leaf of the tree
inline bool TreeNode::isLeaf() const {
RP3D_FORCE_INLINE bool TreeNode::isLeaf() const {
return (height == 0);
}
// Return the fat AABB corresponding to a given node ID
inline const AABB& DynamicAABBTree::getFatAABB(int32 nodeID) const {
RP3D_FORCE_INLINE const AABB& DynamicAABBTree::getFatAABB(int32 nodeID) const {
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
return mNodes[nodeID].aabb;
}
// Return the pointer to the data array of a given leaf node of the tree
inline int32* DynamicAABBTree::getNodeDataInt(int32 nodeID) const {
RP3D_FORCE_INLINE int32* DynamicAABBTree::getNodeDataInt(int32 nodeID) const {
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
assert(mNodes[nodeID].isLeaf());
return mNodes[nodeID].dataInt;
}
// Return the pointer to the data pointer of a given leaf node of the tree
inline void* DynamicAABBTree::getNodeDataPointer(int32 nodeID) const {
RP3D_FORCE_INLINE void* DynamicAABBTree::getNodeDataPointer(int32 nodeID) const {
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
assert(mNodes[nodeID].isLeaf());
return mNodes[nodeID].dataPointer;
}
// Return the root AABB of the tree
inline AABB DynamicAABBTree::getRootAABB() const {
RP3D_FORCE_INLINE AABB DynamicAABBTree::getRootAABB() const {
return getFatAABB(mRootNodeID);
}
// Add an object into the tree. This method creates a new leaf node in the tree and
// returns the ID of the corresponding node.
inline int32 DynamicAABBTree::addObject(const AABB& aabb, int32 data1, int32 data2) {
RP3D_FORCE_INLINE int32 DynamicAABBTree::addObject(const AABB& aabb, int32 data1, int32 data2) {
int32 nodeId = addObjectInternal(aabb);
@ -307,7 +312,7 @@ inline int32 DynamicAABBTree::addObject(const AABB& aabb, int32 data1, int32 dat
// Add an object into the tree. This method creates a new leaf node in the tree and
// returns the ID of the corresponding node.
inline int32 DynamicAABBTree::addObject(const AABB& aabb, void* data) {
RP3D_FORCE_INLINE int32 DynamicAABBTree::addObject(const AABB& aabb, void* data) {
int32 nodeId = addObjectInternal(aabb);
@ -319,7 +324,7 @@ inline int32 DynamicAABBTree::addObject(const AABB& aabb, void* data) {
#ifdef IS_RP3D_PROFILING_ENABLED
// Set the profiler
inline void DynamicAABBTree::setProfiler(Profiler* profiler) {
RP3D_FORCE_INLINE void DynamicAABBTree::setProfiler(Profiler* profiler) {
mProfiler = profiler;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -34,7 +34,7 @@
namespace reactphysics3d {
// Declarations
struct CapsuleVsCapsuleNarrowPhaseInfoBatch;
struct NarrowPhaseInfoBatch;
class ContactPoint;
// Class CapsuleVsCapsuleAlgorithm
@ -66,8 +66,8 @@ class CapsuleVsCapsuleAlgorithm : public NarrowPhaseAlgorithm {
CapsuleVsCapsuleAlgorithm& operator=(const CapsuleVsCapsuleAlgorithm& algorithm) = delete;
/// Compute the narrow-phase collision detection between two capsules
bool testCollision(CapsuleVsCapsuleNarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex,
uint batchNbItems, MemoryAllocator& memoryAllocator);
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint32 batchStartIndex,
uint32 batchNbItems, MemoryAllocator& memoryAllocator);
};
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -34,6 +34,7 @@ namespace reactphysics3d {
// Declarations
class ContactPoint;
struct NarrowPhaseInfoBatch;
// Class CapsuleVsConvexPolyhedronAlgorithm
/**
@ -69,8 +70,8 @@ class CapsuleVsConvexPolyhedronAlgorithm : public NarrowPhaseAlgorithm {
CapsuleVsConvexPolyhedronAlgorithm& operator=(const CapsuleVsConvexPolyhedronAlgorithm& algorithm) = delete;
/// Compute the narrow-phase collision detection between a capsule and a polyhedron
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex,
uint batchNbItems, bool clipWithPreviousAxisIfStillColliding,
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint32 batchStartIndex,
uint32 batchNbItems, bool clipWithPreviousAxisIfStillColliding,
MemoryAllocator& memoryAllocator);
};

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -173,39 +173,39 @@ class CollisionDispatch {
};
// Get the Sphere vs Sphere narrow-phase collision detection algorithm
inline SphereVsSphereAlgorithm* CollisionDispatch::getSphereVsSphereAlgorithm() {
RP3D_FORCE_INLINE SphereVsSphereAlgorithm* CollisionDispatch::getSphereVsSphereAlgorithm() {
return mSphereVsSphereAlgorithm;
}
// Get the Sphere vs Capsule narrow-phase collision detection algorithm
inline SphereVsCapsuleAlgorithm* CollisionDispatch::getSphereVsCapsuleAlgorithm() {
RP3D_FORCE_INLINE SphereVsCapsuleAlgorithm* CollisionDispatch::getSphereVsCapsuleAlgorithm() {
return mSphereVsCapsuleAlgorithm;
}
// Get the Capsule vs Capsule narrow-phase collision detection algorithm
inline CapsuleVsCapsuleAlgorithm* CollisionDispatch::getCapsuleVsCapsuleAlgorithm() {
RP3D_FORCE_INLINE CapsuleVsCapsuleAlgorithm* CollisionDispatch::getCapsuleVsCapsuleAlgorithm() {
return mCapsuleVsCapsuleAlgorithm;
}
// Get the Sphere vs Convex Polyhedron narrow-phase collision detection algorithm
inline SphereVsConvexPolyhedronAlgorithm* CollisionDispatch::getSphereVsConvexPolyhedronAlgorithm() {
RP3D_FORCE_INLINE SphereVsConvexPolyhedronAlgorithm* CollisionDispatch::getSphereVsConvexPolyhedronAlgorithm() {
return mSphereVsConvexPolyhedronAlgorithm;
}
// Get the Capsule vs Convex Polyhedron narrow-phase collision detection algorithm
inline CapsuleVsConvexPolyhedronAlgorithm* CollisionDispatch::getCapsuleVsConvexPolyhedronAlgorithm() {
RP3D_FORCE_INLINE CapsuleVsConvexPolyhedronAlgorithm* CollisionDispatch::getCapsuleVsConvexPolyhedronAlgorithm() {
return mCapsuleVsConvexPolyhedronAlgorithm;
}
// Get the Convex Polyhedron vs Convex Polyhedron narrow-phase collision detection algorithm
inline ConvexPolyhedronVsConvexPolyhedronAlgorithm* CollisionDispatch::getConvexPolyhedronVsConvexPolyhedronAlgorithm() {
RP3D_FORCE_INLINE ConvexPolyhedronVsConvexPolyhedronAlgorithm* CollisionDispatch::getConvexPolyhedronVsConvexPolyhedronAlgorithm() {
return mConvexPolyhedronVsConvexPolyhedronAlgorithm;
}
#ifdef IS_RP3D_PROFILING_ENABLED
// Set the profiler
inline void CollisionDispatch::setProfiler(Profiler* profiler) {
RP3D_FORCE_INLINE void CollisionDispatch::setProfiler(Profiler* profiler) {
mProfiler = profiler;
mSphereVsSphereAlgorithm->setProfiler(profiler);

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -34,6 +34,7 @@ namespace reactphysics3d {
// Declarations
class ContactPoint;
struct NarrowPhaseInfoBatch;
// Class ConvexPolyhedronVsConvexPolyhedronAlgorithm
/**
@ -64,7 +65,7 @@ class ConvexPolyhedronVsConvexPolyhedronAlgorithm : public NarrowPhaseAlgorithm
ConvexPolyhedronVsConvexPolyhedronAlgorithm& operator=(const ConvexPolyhedronVsConvexPolyhedronAlgorithm& algorithm) = delete;
/// Compute the narrow-phase collision detection between two convex polyhedra
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems,
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint32 batchStartIndex, uint32 batchNbItems,
bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& memoryAllocator);
};

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -34,12 +34,12 @@
namespace reactphysics3d {
// Declarations
class ContactManifoldInfo;
struct ContactManifoldInfo;
struct NarrowPhaseInfoBatch;
class ConvexShape;
class Profiler;
class VoronoiSimplex;
template<typename T> class List;
template<typename T> class Array;
// Constants
constexpr decimal REL_ERROR = decimal(1.0e-3);
@ -97,8 +97,8 @@ class GJKAlgorithm {
GJKAlgorithm& operator=(const GJKAlgorithm& algorithm) = delete;
/// Compute a contact info if the two bounding volumes collide.
void testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex,
uint batchNbItems, List<GJKResult>& gjkResults);
void testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint32 batchStartIndex,
uint32 batchNbItems, Array<GJKResult>& gjkResults);
#ifdef IS_RP3D_PROFILING_ENABLED
@ -112,7 +112,7 @@ class GJKAlgorithm {
#ifdef IS_RP3D_PROFILING_ENABLED
// Set the profiler
inline void GJKAlgorithm::setProfiler(Profiler* profiler) {
RP3D_FORCE_INLINE void GJKAlgorithm::setProfiler(Profiler* profiler) {
mProfiler = profiler;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -28,6 +28,7 @@
// Libraries
#include <reactphysics3d/mathematics/Vector3.h>
#include <reactphysics3d/mathematics/Vector2.h>
/// ReactPhysics3D namespace
namespace reactphysics3d {
@ -171,17 +172,17 @@ class VoronoiSimplex {
};
// Return true if the simplex contains 4 points
inline bool VoronoiSimplex::isFull() const {
RP3D_FORCE_INLINE bool VoronoiSimplex::isFull() const {
return mNbPoints == 4;
}
// Return true if the simple is empty
inline bool VoronoiSimplex::isEmpty() const {
RP3D_FORCE_INLINE bool VoronoiSimplex::isEmpty() const {
return mNbPoints == 0;
}
// Set the barycentric coordinates of the closest point
inline void VoronoiSimplex::setBarycentricCoords(decimal a, decimal b, decimal c, decimal d) {
RP3D_FORCE_INLINE void VoronoiSimplex::setBarycentricCoords(decimal a, decimal b, decimal c, decimal d) {
mBarycentricCoords[0] = a;
mBarycentricCoords[1] = b;
mBarycentricCoords[2] = c;
@ -189,7 +190,7 @@ inline void VoronoiSimplex::setBarycentricCoords(decimal a, decimal b, decimal c
}
// Compute the closest point "v" to the origin of the current simplex.
inline bool VoronoiSimplex::computeClosestPoint(Vector3& v) {
RP3D_FORCE_INLINE bool VoronoiSimplex::computeClosestPoint(Vector3& v) {
bool isValid = recomputeClosestPoint();
v = mClosestPoint;
@ -197,7 +198,7 @@ inline bool VoronoiSimplex::computeClosestPoint(Vector3& v) {
}
// Return true if the
inline bool VoronoiSimplex::checkClosestPointValid() const {
RP3D_FORCE_INLINE bool VoronoiSimplex::checkClosestPointValid() const {
return mBarycentricCoords[0] >= decimal(0.0) && mBarycentricCoords[1] >= decimal(0.0) &&
mBarycentricCoords[2] >= decimal(0.0) && mBarycentricCoords[3] >= decimal(0.0);
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -33,7 +33,7 @@
namespace reactphysics3d {
class CollisionDetectionSystem;
class ContactManifoldInfo;
struct ContactManifoldInfo;
class DefaultPoolAllocator;
class OverlappingPair;
struct NarrowPhaseInfoBatch;
@ -106,7 +106,7 @@ class NarrowPhaseAlgorithm {
#ifdef IS_RP3D_PROFILING_ENABLED
// Set the profiler
inline void NarrowPhaseAlgorithm::setProfiler(Profiler* profiler) {
RP3D_FORCE_INLINE void NarrowPhaseAlgorithm::setProfiler(Profiler* profiler) {
mProfiler = profiler;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -28,6 +28,8 @@
// Libraries
#include <reactphysics3d/engine/OverlappingPairs.h>
#include <reactphysics3d/collision/ContactPointInfo.h>
#include <reactphysics3d/configuration.h>
/// Namespace ReactPhysics3D
namespace reactphysics3d {
@ -35,98 +37,148 @@ namespace reactphysics3d {
// Declarations
class CollisionShape;
struct LastFrameCollisionInfo;
class ContactManifoldInfo;
struct ContactManifoldInfo;
struct ContactPointInfo;
// Struct NarrowPhaseInfoBatch
/**
* This abstract structure collects all the potential collisions from the middle-phase algorithm
* that have to be tested during narrow-phase collision detection. There is an implementation of
* this class for each kind of collision detection test. For instance, one for sphere vs sphere,
* one for sphere vs capsule, ...
* This structure collects all the potential collisions from the middle-phase algorithm
* that have to be tested during narrow-phase collision detection.
*/
struct NarrowPhaseInfoBatch {
struct NarrowPhaseInfo {
/// Broadphase overlapping pairs ids
uint64 overlappingPairId;
/// Entity of the first collider to test collision with
Entity colliderEntity1;
/// Entity of the second collider to test collision with
Entity colliderEntity2;
/// Collision info of the previous frame
LastFrameCollisionInfo* lastFrameCollisionInfo;
/// Memory allocator for the collision shape (Used to release TriangleShape memory in destructor)
MemoryAllocator* collisionShapeAllocator;
/// Shape local to world transform of sphere 1
Transform shape1ToWorldTransform;
/// Shape local to world transform of sphere 2
Transform shape2ToWorldTransform;
/// Pointer to the first collision shapes to test collision with
CollisionShape* collisionShape1;
/// Pointer to the second collision shapes to test collision with
CollisionShape* collisionShape2;
/// True if we need to report contacts (false for triggers for instance)
bool reportContacts;
/// Result of the narrow-phase collision detection test
bool isColliding;
/// Number of contact points
uint8 nbContactPoints;
/// Array of contact points created during the narrow-phase
ContactPointInfo contactPoints[NB_MAX_CONTACT_POINTS_IN_NARROWPHASE_INFO];
/// Constructor
NarrowPhaseInfo(uint64 pairId, Entity collider1, Entity collider2, LastFrameCollisionInfo* lastFrameInfo, MemoryAllocator& shapeAllocator,
const Transform& shape1ToWorldTransform, const Transform& shape2ToWorldTransform, CollisionShape* shape1,
CollisionShape* shape2, bool needToReportContacts)
: overlappingPairId(pairId), colliderEntity1(collider1), colliderEntity2(collider2), lastFrameCollisionInfo(lastFrameInfo),
collisionShapeAllocator(&shapeAllocator), shape1ToWorldTransform(shape1ToWorldTransform),
shape2ToWorldTransform(shape2ToWorldTransform), collisionShape1(shape1),
collisionShape2(shape2), reportContacts(needToReportContacts), isColliding(false), nbContactPoints(0) {
}
};
protected:
/// Memory allocator
/// Reference to the memory allocator
MemoryAllocator& mMemoryAllocator;
/// Reference to all the broad-phase overlapping pairs
OverlappingPairs& mOverlappingPairs;
/// Cached capacity
uint mCachedCapacity = 0;
uint32 mCachedCapacity = 0;
public:
/// List of Broadphase overlapping pairs ids
List<uint64> overlappingPairIds;
/// List of pointers to the first colliders to test collision with
List<Entity> colliderEntities1;
/// List of pointers to the second colliders to test collision with
List<Entity> colliderEntities2;
/// List of pointers to the first collision shapes to test collision with
List<CollisionShape*> collisionShapes1;
/// List of pointers to the second collision shapes to test collision with
List<CollisionShape*> collisionShapes2;
/// List of transforms that maps from collision shape 1 local-space to world-space
List<Transform> shape1ToWorldTransforms;
/// List of transforms that maps from collision shape 2 local-space to world-space
List<Transform> shape2ToWorldTransforms;
/// True for each pair of objects that we need to report contacts (false for triggers for instance)
List<bool> reportContacts;
/// Result of the narrow-phase collision detection test
List<bool> isColliding;
/// List of contact points created during the narrow-phase
List<List<ContactPointInfo*>> contactPoints;
/// Memory allocators for the collision shape (Used to release TriangleShape memory in destructor)
List<MemoryAllocator*> collisionShapeAllocators;
/// Collision infos of the previous frame
List<LastFrameCollisionInfo*> lastFrameCollisionInfos;
/// For each collision test, we keep some meta data
Array<NarrowPhaseInfo> narrowPhaseInfos;
/// Constructor
NarrowPhaseInfoBatch(MemoryAllocator& allocator, OverlappingPairs& overlappingPairs);
NarrowPhaseInfoBatch(OverlappingPairs& overlappingPairs, MemoryAllocator& allocator);
/// Destructor
virtual ~NarrowPhaseInfoBatch();
/// Return the number of objects in the batch
uint getNbObjects() const;
~NarrowPhaseInfoBatch();
/// Add shapes to be tested during narrow-phase collision detection into the batch
virtual void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1,
CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform, bool needToReportContacts, MemoryAllocator& shapeAllocator);
void addNarrowPhaseInfo(uint64 pairId, Entity collider1, Entity collider2, CollisionShape* shape1,
CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform,
bool needToReportContacts, LastFrameCollisionInfo* lastFrameInfo, MemoryAllocator& shapeAllocator);
/// Return the number of objects in the batch
uint32 getNbObjects() const;
/// Add a new contact point
virtual void addContactPoint(uint index, const Vector3& contactNormal, decimal penDepth,
void addContactPoint(uint32 index, const Vector3& contactNormal, decimal penDepth,
const Vector3& localPt1, const Vector3& localPt2);
/// Reset the remaining contact points
void resetContactPoints(uint index);
void resetContactPoints(uint32 index);
// Initialize the containers using cached capacity
virtual void reserveMemory();
void reserveMemory();
/// Clear all the objects in the batch
virtual void clear();
void clear();
};
/// Return the number of objects in the batch
inline uint NarrowPhaseInfoBatch::getNbObjects() const {
return overlappingPairIds.size();
RP3D_FORCE_INLINE uint32 NarrowPhaseInfoBatch::getNbObjects() const {
return static_cast<uint32>(narrowPhaseInfos.size());
}
// Add shapes to be tested during narrow-phase collision detection into the batch
RP3D_FORCE_INLINE void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity collider1, Entity collider2, CollisionShape* shape1,
CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform,
bool needToReportContacts, LastFrameCollisionInfo* lastFrameInfo, MemoryAllocator& shapeAllocator) {
// Create a meta data object
narrowPhaseInfos.emplace(pairId, collider1, collider2, lastFrameInfo, shapeAllocator, shape1Transform, shape2Transform, shape1, shape2, needToReportContacts);
}
// Add a new contact point
RP3D_FORCE_INLINE void NarrowPhaseInfoBatch::addContactPoint(uint32 index, const Vector3& contactNormal, decimal penDepth, const Vector3& localPt1, const Vector3& localPt2) {
assert(penDepth > decimal(0.0));
if (narrowPhaseInfos[index].nbContactPoints < NB_MAX_CONTACT_POINTS_IN_NARROWPHASE_INFO) {
assert(contactNormal.length() > 0.8f);
// Add it into the array of contact points
narrowPhaseInfos[index].contactPoints[narrowPhaseInfos[index].nbContactPoints].normal = contactNormal;
narrowPhaseInfos[index].contactPoints[narrowPhaseInfos[index].nbContactPoints].penetrationDepth = penDepth;
narrowPhaseInfos[index].contactPoints[narrowPhaseInfos[index].nbContactPoints].localPoint1 = localPt1;
narrowPhaseInfos[index].contactPoints[narrowPhaseInfos[index].nbContactPoints].localPoint2 = localPt2;
narrowPhaseInfos[index].nbContactPoints++;
}
}
// Reset the remaining contact points
RP3D_FORCE_INLINE void NarrowPhaseInfoBatch::resetContactPoints(uint32 index) {
narrowPhaseInfos[index].nbContactPoints = 0;
}
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -27,11 +27,9 @@
#define REACTPHYSICS3D_NARROW_PHASE_INPUT_H
// Libraries
#include <reactphysics3d/containers/List.h>
#include <reactphysics3d/containers/Array.h>
#include <reactphysics3d/collision/narrowphase/NarrowPhaseInfoBatch.h>
#include <reactphysics3d/collision/narrowphase/SphereVsSphereNarrowPhaseInfoBatch.h>
#include <reactphysics3d/collision/narrowphase/CapsuleVsCapsuleNarrowPhaseInfoBatch.h>
#include <reactphysics3d/collision/narrowphase/SphereVsCapsuleNarrowPhaseInfoBatch.h>
#include <reactphysics3d/collision/narrowphase/CollisionDispatch.h>
/// Namespace ReactPhysics3D
namespace reactphysics3d {
@ -55,9 +53,9 @@ class NarrowPhaseInput {
private:
SphereVsSphereNarrowPhaseInfoBatch mSphereVsSphereBatch;
SphereVsCapsuleNarrowPhaseInfoBatch mSphereVsCapsuleBatch;
CapsuleVsCapsuleNarrowPhaseInfoBatch mCapsuleVsCapsuleBatch;
NarrowPhaseInfoBatch mSphereVsSphereBatch;
NarrowPhaseInfoBatch mSphereVsCapsuleBatch;
NarrowPhaseInfoBatch mCapsuleVsCapsuleBatch;
NarrowPhaseInfoBatch mSphereVsConvexPolyhedronBatch;
NarrowPhaseInfoBatch mCapsuleVsConvexPolyhedronBatch;
NarrowPhaseInfoBatch mConvexPolyhedronVsConvexPolyhedronBatch;
@ -68,19 +66,19 @@ class NarrowPhaseInput {
NarrowPhaseInput(MemoryAllocator& allocator, OverlappingPairs& overlappingPairs);
/// Add shapes to be tested during narrow-phase collision detection into the batch
void addNarrowPhaseTest(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1,
void addNarrowPhaseTest(uint64 pairId, Entity collider1, Entity collider2, CollisionShape* shape1,
CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform, NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, bool reportContacts,
MemoryAllocator& shapeAllocator);
LastFrameCollisionInfo* lastFrameInfo, MemoryAllocator& shapeAllocator);
/// Get a reference to the sphere vs sphere batch
SphereVsSphereNarrowPhaseInfoBatch& getSphereVsSphereBatch();
NarrowPhaseInfoBatch& getSphereVsSphereBatch();
/// Get a reference to the sphere vs capsule batch
SphereVsCapsuleNarrowPhaseInfoBatch& getSphereVsCapsuleBatch();
NarrowPhaseInfoBatch& getSphereVsCapsuleBatch();
/// Get a reference to the capsule vs capsule batch
CapsuleVsCapsuleNarrowPhaseInfoBatch& getCapsuleVsCapsuleBatch();
NarrowPhaseInfoBatch& getCapsuleVsCapsuleBatch();
/// Get a reference to the sphere vs convex polyhedron batch
NarrowPhaseInfoBatch& getSphereVsConvexPolyhedronBatch();
@ -100,34 +98,65 @@ class NarrowPhaseInput {
// Get a reference to the sphere vs sphere batch contacts
inline SphereVsSphereNarrowPhaseInfoBatch& NarrowPhaseInput::getSphereVsSphereBatch() {
RP3D_FORCE_INLINE NarrowPhaseInfoBatch& NarrowPhaseInput::getSphereVsSphereBatch() {
return mSphereVsSphereBatch;
}
// Get a reference to the sphere vs capsule batch contacts
inline SphereVsCapsuleNarrowPhaseInfoBatch& NarrowPhaseInput::getSphereVsCapsuleBatch() {
RP3D_FORCE_INLINE NarrowPhaseInfoBatch& NarrowPhaseInput::getSphereVsCapsuleBatch() {
return mSphereVsCapsuleBatch;
}
// Get a reference to the capsule vs capsule batch contacts
inline CapsuleVsCapsuleNarrowPhaseInfoBatch& NarrowPhaseInput::getCapsuleVsCapsuleBatch() {
RP3D_FORCE_INLINE NarrowPhaseInfoBatch& NarrowPhaseInput::getCapsuleVsCapsuleBatch() {
return mCapsuleVsCapsuleBatch;
}
// Get a reference to the sphere vs convex polyhedron batch contacts
inline NarrowPhaseInfoBatch& NarrowPhaseInput::getSphereVsConvexPolyhedronBatch() {
RP3D_FORCE_INLINE NarrowPhaseInfoBatch& NarrowPhaseInput::getSphereVsConvexPolyhedronBatch() {
return mSphereVsConvexPolyhedronBatch;
}
// Get a reference to the capsule vs convex polyhedron batch contacts
inline NarrowPhaseInfoBatch& NarrowPhaseInput::getCapsuleVsConvexPolyhedronBatch() {
RP3D_FORCE_INLINE NarrowPhaseInfoBatch& NarrowPhaseInput::getCapsuleVsConvexPolyhedronBatch() {
return mCapsuleVsConvexPolyhedronBatch;
}
// Get a reference to the convex polyhedron vs convex polyhedron batch contacts
inline NarrowPhaseInfoBatch& NarrowPhaseInput::getConvexPolyhedronVsConvexPolyhedronBatch() {
RP3D_FORCE_INLINE NarrowPhaseInfoBatch &NarrowPhaseInput::getConvexPolyhedronVsConvexPolyhedronBatch() {
return mConvexPolyhedronVsConvexPolyhedronBatch;
}
// Add shapes to be tested during narrow-phase collision detection into the batch
RP3D_FORCE_INLINE void NarrowPhaseInput::addNarrowPhaseTest(uint64 pairId, Entity collider1, Entity collider2, CollisionShape* shape1, CollisionShape* shape2,
const Transform& shape1Transform, const Transform& shape2Transform,
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, bool reportContacts, LastFrameCollisionInfo* lastFrameInfo,
MemoryAllocator& shapeAllocator) {
switch (narrowPhaseAlgorithmType) {
case NarrowPhaseAlgorithmType::SphereVsSphere:
mSphereVsSphereBatch.addNarrowPhaseInfo(pairId, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, lastFrameInfo, shapeAllocator);
break;
case NarrowPhaseAlgorithmType::SphereVsCapsule:
mSphereVsCapsuleBatch.addNarrowPhaseInfo(pairId, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, lastFrameInfo, shapeAllocator);
break;
case NarrowPhaseAlgorithmType::CapsuleVsCapsule:
mCapsuleVsCapsuleBatch.addNarrowPhaseInfo(pairId, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, lastFrameInfo, shapeAllocator);
break;
case NarrowPhaseAlgorithmType::SphereVsConvexPolyhedron:
mSphereVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, lastFrameInfo, shapeAllocator);
break;
case NarrowPhaseAlgorithmType::CapsuleVsConvexPolyhedron:
mCapsuleVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, lastFrameInfo, shapeAllocator);
break;
case NarrowPhaseAlgorithmType::ConvexPolyhedronVsConvexPolyhedron:
mConvexPolyhedronVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, lastFrameInfo, shapeAllocator);
break;
case NarrowPhaseAlgorithmType::None:
// Must never happen
assert(false);
break;
}
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -36,7 +36,7 @@ namespace reactphysics3d {
// Declarations
class CapsuleShape;
class SphereShape;
class ContactManifoldInfo;
struct ContactManifoldInfo;
struct NarrowPhaseInfoBatch;
class ConvexPolyhedronShape;
class MemoryAllocator;
@ -107,7 +107,7 @@ class SATAlgorithm {
decimal testSingleFaceDirectionPolyhedronVsPolyhedron(const ConvexPolyhedronShape* polyhedron1,
const ConvexPolyhedronShape* polyhedron2,
const Transform& polyhedron1ToPolyhedron2,
uint faceIndex) const;
uint32 faceIndex) const;
/// Test all the normals of a polyhedron for separating axis in the polyhedron vs polyhedron case
@ -115,11 +115,11 @@ class SATAlgorithm {
const Transform& polyhedron1ToPolyhedron2, uint& minFaceIndex) const;
/// Compute the penetration depth between a face of the polyhedron and a sphere along the polyhedron face normal direction
decimal computePolyhedronFaceVsSpherePenetrationDepth(uint faceIndex, const ConvexPolyhedronShape* polyhedron,
decimal computePolyhedronFaceVsSpherePenetrationDepth(uint32 faceIndex, const ConvexPolyhedronShape* polyhedron,
const SphereShape* sphere, const Vector3& sphereCenter) const;
/// Compute the penetration depth between the face of a polyhedron and a capsule along the polyhedron face normal direction
decimal computePolyhedronFaceVsCapsulePenetrationDepth(uint polyhedronFaceIndex, const ConvexPolyhedronShape* polyhedron,
decimal computePolyhedronFaceVsCapsulePenetrationDepth(uint32 polyhedronFaceIndex, const ConvexPolyhedronShape* polyhedron,
const CapsuleShape* capsule, const Transform& polyhedronToCapsuleTransform,
Vector3& outFaceNormalCapsuleSpace) const;
@ -132,8 +132,8 @@ class SATAlgorithm {
/// Compute the contact points between two faces of two convex polyhedra.
bool computePolyhedronVsPolyhedronFaceContactPoints(bool isMinPenetrationFaceNormalPolyhedron1, const ConvexPolyhedronShape* polyhedron1,
const ConvexPolyhedronShape* polyhedron2, const Transform& polyhedron1ToPolyhedron2,
const Transform& polyhedron2ToPolyhedron1, uint minFaceIndex,
NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchIndex) const;
const Transform& polyhedron2ToPolyhedron1, uint32 minFaceIndex,
NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint32 batchIndex) const;
public :
@ -154,24 +154,24 @@ class SATAlgorithm {
/// Test collision between a sphere and a convex mesh
bool testCollisionSphereVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch,
uint batchStartIndex, uint batchNbItems) const;
uint32 batchStartIndex, uint32 batchNbItems) const;
/// Test collision between a capsule and a convex mesh
bool testCollisionCapsuleVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchIndex) const;
bool testCollisionCapsuleVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint32 batchIndex) const;
/// Compute the two contact points between a polyhedron and a capsule when the separating axis is a face normal of the polyhedron
bool computeCapsulePolyhedronFaceContactPoints(uint referenceFaceIndex, decimal capsuleRadius, const ConvexPolyhedronShape* polyhedron,
bool computeCapsulePolyhedronFaceContactPoints(uint32 referenceFaceIndex, decimal capsuleRadius, const ConvexPolyhedronShape* polyhedron,
decimal penetrationDepth, const Transform& polyhedronToCapsuleTransform,
Vector3& normalWorld, const Vector3& separatingAxisCapsuleSpace,
const Vector3& capsuleSegAPolyhedronSpace, const Vector3& capsuleSegBPolyhedronSpace,
NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchIndex, bool isCapsuleShape1) const;
NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint32 batchIndex, bool isCapsuleShape1) const;
// This method returns true if an edge of a polyhedron and a capsule forms a face of the Minkowski Difference
bool isMinkowskiFaceCapsuleVsEdge(const Vector3& capsuleSegment, const Vector3& edgeAdjacentFace1Normal,
const Vector3& edgeAdjacentFace2Normal) const;
/// Test collision between two convex meshes
bool testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems) const;
bool testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint32 batchStartIndex, uint32 batchNbItems) const;
#ifdef IS_RP3D_PROFILING_ENABLED
@ -185,7 +185,7 @@ class SATAlgorithm {
#ifdef IS_RP3D_PROFILING_ENABLED
// Set the profiler
inline void SATAlgorithm::setProfiler(Profiler* profiler) {
RP3D_FORCE_INLINE void SATAlgorithm::setProfiler(Profiler* profiler) {
mProfiler = profiler;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -34,7 +34,7 @@ namespace reactphysics3d {
// Declarations
class ContactPoint;
struct SphereVsCapsuleNarrowPhaseInfoBatch;
struct NarrowPhaseInfoBatch;
// Class SphereVsCapsuleAlgorithm
/**
@ -65,8 +65,8 @@ class SphereVsCapsuleAlgorithm : public NarrowPhaseAlgorithm {
SphereVsCapsuleAlgorithm& operator=(const SphereVsCapsuleAlgorithm& algorithm) = delete;
/// Compute the narrow-phase collision detection between a sphere and a capsule
bool testCollision(SphereVsCapsuleNarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex,
uint batchNbItems, MemoryAllocator& memoryAllocator);
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint32 batchStartIndex,
uint32 batchNbItems, MemoryAllocator& memoryAllocator);
};
}

View File

@ -1,78 +0,0 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
*********************************************************************************
* *
* 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 REACTPHYSICS3D_SPHERE_VS_CAPSULE_NARROW_PHASE_INFO_BATCH_H
#define REACTPHYSICS3D_SPHERE_VS_CAPSULE_NARROW_PHASE_INFO_BATCH_H
// Libraries
#include <reactphysics3d/collision/narrowphase/NarrowPhaseInfoBatch.h>
/// Namespace ReactPhysics3D
namespace reactphysics3d {
// Struct SphereVsCapsuleNarrowPhaseInfoBatch
/**
* This structure collects all the potential collisions from the middle-phase algorithm
* that have to be tested during narrow-phase collision detection. This class collects all the
* sphere vs capsule collision detection tests.
*/
struct SphereVsCapsuleNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch {
public:
/// List of boolean values to know if the the sphere is the first or second shape
List<bool> isSpheresShape1;
/// List of radiuses for the spheres
List<decimal> sphereRadiuses;
/// List of radiuses for the capsules
List<decimal> capsuleRadiuses;
/// List of heights for the capsules
List<decimal> capsuleHeights;
/// Constructor
SphereVsCapsuleNarrowPhaseInfoBatch(MemoryAllocator& allocator, OverlappingPairs& overlappingPairs);
/// Destructor
virtual ~SphereVsCapsuleNarrowPhaseInfoBatch() override = default;
/// Add shapes to be tested during narrow-phase collision detection into the batch
virtual void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1,
CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform, bool needToReportContacts, MemoryAllocator& shapeAllocator) override;
// Initialize the containers using cached capacity
virtual void reserveMemory() override;
/// Clear all the objects in the batch
virtual void clear() override;
};
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -34,6 +34,7 @@ namespace reactphysics3d {
// Declarations
class ContactPoint;
struct NarrowPhaseInfoBatch;
// Class SphereVsConvexPolyhedronAlgorithm
/**
@ -70,7 +71,7 @@ class SphereVsConvexPolyhedronAlgorithm : public NarrowPhaseAlgorithm {
SphereVsConvexPolyhedronAlgorithm& operator=(const SphereVsConvexPolyhedronAlgorithm& algorithm) = delete;
/// Compute the narrow-phase collision detection between a sphere and a convex polyhedron
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems,
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint32 batchStartIndex, uint32 batchNbItems,
bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& memoryAllocator);
};

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -34,7 +34,7 @@ namespace reactphysics3d {
// Declarations
class ContactPoint;
struct SphereVsSphereNarrowPhaseInfoBatch;
struct NarrowPhaseInfoBatch;
// Class SphereVsSphereAlgorithm
/**
@ -65,8 +65,8 @@ class SphereVsSphereAlgorithm : public NarrowPhaseAlgorithm {
SphereVsSphereAlgorithm& operator=(const SphereVsSphereAlgorithm& algorithm) = delete;
/// Compute a contact info if the two bounding volume collide
bool testCollision(SphereVsSphereNarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex,
uint batchNbItems, MemoryAllocator& memoryAllocator);
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint32 batchStartIndex,
uint32 batchNbItems, MemoryAllocator& memoryAllocator);
};
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -61,12 +61,6 @@ class AABB {
/// Constructor
AABB(const Vector3& minCoordinates, const Vector3& maxCoordinates);
/// Copy-constructor
AABB(const AABB& aabb);
/// Destructor
~AABB() = default;
/// Return the center point
Vector3 getCenter() const;
@ -110,7 +104,10 @@ class AABB {
bool testCollisionTriangleAABB(const Vector3* trianglePoints) const;
/// Return true if the ray intersects the AABB
bool testRayIntersect(const Ray& ray) const;
bool testRayIntersect(const Vector3& rayOrigin, const Vector3& rayDirectionInv, decimal rayMaxFraction) const;
/// Compute the intersection of a ray and the AABB
bool raycast(const Ray& ray, Vector3& hitPoint) const;
/// Apply a scale factor to the AABB
void applyScale(const Vector3& scale);
@ -118,53 +115,50 @@ class AABB {
/// Create and return an AABB for a triangle
static AABB createAABBForTriangle(const Vector3* trianglePoints);
/// Assignment operator
AABB& operator=(const AABB& aabb);
// -------------------- Friendship -------------------- //
friend class DynamicAABBTree;
};
// Return the center point of the AABB in world coordinates
inline Vector3 AABB::getCenter() const {
RP3D_FORCE_INLINE Vector3 AABB::getCenter() const {
return (mMinCoordinates + mMaxCoordinates) * decimal(0.5);
}
// Return the minimum coordinates of the AABB
inline const Vector3& AABB::getMin() const {
RP3D_FORCE_INLINE const Vector3& AABB::getMin() const {
return mMinCoordinates;
}
// Set the minimum coordinates of the AABB
inline void AABB::setMin(const Vector3& min) {
RP3D_FORCE_INLINE void AABB::setMin(const Vector3& min) {
mMinCoordinates = min;
}
// Return the maximum coordinates of the AABB
inline const Vector3& AABB::getMax() const {
RP3D_FORCE_INLINE const Vector3& AABB::getMax() const {
return mMaxCoordinates;
}
// Set the maximum coordinates of the AABB
inline void AABB::setMax(const Vector3& max) {
RP3D_FORCE_INLINE void AABB::setMax(const Vector3& max) {
mMaxCoordinates = max;
}
// Return the size of the AABB in the three dimension x, y and z
inline Vector3 AABB::getExtent() const {
RP3D_FORCE_INLINE Vector3 AABB::getExtent() const {
return mMaxCoordinates - mMinCoordinates;
}
// Inflate each side of the AABB by a given size
inline void AABB::inflate(decimal dx, decimal dy, decimal dz) {
RP3D_FORCE_INLINE void AABB::inflate(decimal dx, decimal dy, decimal dz) {
mMaxCoordinates += Vector3(dx, dy, dz);
mMinCoordinates -= Vector3(dx, dy, dz);
}
// Return true if the current AABB is overlapping with the AABB in argument.
/// Two AABBs overlap if they overlap in the three x, y and z axis at the same time
inline bool AABB::testCollision(const AABB& aabb) const {
RP3D_FORCE_INLINE bool AABB::testCollision(const AABB& aabb) const {
if (mMaxCoordinates.x < aabb.mMinCoordinates.x ||
aabb.mMaxCoordinates.x < mMinCoordinates.x) return false;
if (mMaxCoordinates.y < aabb.mMinCoordinates.y ||
@ -175,13 +169,13 @@ inline bool AABB::testCollision(const AABB& aabb) const {
}
// Return the volume of the AABB
inline decimal AABB::getVolume() const {
RP3D_FORCE_INLINE decimal AABB::getVolume() const {
const Vector3 diff = mMaxCoordinates - mMinCoordinates;
return (diff.x * diff.y * diff.z);
}
// Return true if the AABB of a triangle intersects the AABB
inline bool AABB::testCollisionTriangleAABB(const Vector3* trianglePoints) const {
RP3D_FORCE_INLINE bool AABB::testCollisionTriangleAABB(const Vector3* trianglePoints) const {
if (min3(trianglePoints[0].x, trianglePoints[1].x, trianglePoints[2].x) > mMaxCoordinates.x) return false;
if (min3(trianglePoints[0].y, trianglePoints[1].y, trianglePoints[2].y) > mMaxCoordinates.y) return false;
@ -195,7 +189,7 @@ inline bool AABB::testCollisionTriangleAABB(const Vector3* trianglePoints) const
}
// Return true if a point is inside the AABB
inline bool AABB::contains(const Vector3& point) const {
RP3D_FORCE_INLINE bool AABB::contains(const Vector3& point) const {
return (point.x >= mMinCoordinates.x - MACHINE_EPSILON && point.x <= mMaxCoordinates.x + MACHINE_EPSILON &&
point.y >= mMinCoordinates.y - MACHINE_EPSILON && point.y <= mMaxCoordinates.y + MACHINE_EPSILON &&
@ -203,18 +197,150 @@ inline bool AABB::contains(const Vector3& point) const {
}
// Apply a scale factor to the AABB
inline void AABB::applyScale(const Vector3& scale) {
RP3D_FORCE_INLINE void AABB::applyScale(const Vector3& scale) {
mMinCoordinates = mMinCoordinates * scale;
mMaxCoordinates = mMaxCoordinates * scale;
}
// Assignment operator
inline AABB& AABB::operator=(const AABB& aabb) {
if (this != &aabb) {
mMinCoordinates = aabb.mMinCoordinates;
mMaxCoordinates = aabb.mMaxCoordinates;
// Merge the AABB in parameter with the current one
RP3D_FORCE_INLINE void AABB::mergeWithAABB(const AABB& aabb) {
mMinCoordinates.x = std::min(mMinCoordinates.x, aabb.mMinCoordinates.x);
mMinCoordinates.y = std::min(mMinCoordinates.y, aabb.mMinCoordinates.y);
mMinCoordinates.z = std::min(mMinCoordinates.z, aabb.mMinCoordinates.z);
mMaxCoordinates.x = std::max(mMaxCoordinates.x, aabb.mMaxCoordinates.x);
mMaxCoordinates.y = std::max(mMaxCoordinates.y, aabb.mMaxCoordinates.y);
mMaxCoordinates.z = std::max(mMaxCoordinates.z, aabb.mMaxCoordinates.z);
}
// Replace the current AABB with a new AABB that is the union of two AABBs in parameters
RP3D_FORCE_INLINE void AABB::mergeTwoAABBs(const AABB& aabb1, const AABB& aabb2) {
mMinCoordinates.x = std::min(aabb1.mMinCoordinates.x, aabb2.mMinCoordinates.x);
mMinCoordinates.y = std::min(aabb1.mMinCoordinates.y, aabb2.mMinCoordinates.y);
mMinCoordinates.z = std::min(aabb1.mMinCoordinates.z, aabb2.mMinCoordinates.z);
mMaxCoordinates.x = std::max(aabb1.mMaxCoordinates.x, aabb2.mMaxCoordinates.x);
mMaxCoordinates.y = std::max(aabb1.mMaxCoordinates.y, aabb2.mMaxCoordinates.y);
mMaxCoordinates.z = std::max(aabb1.mMaxCoordinates.z, aabb2.mMaxCoordinates.z);
}
// Return true if the current AABB contains the AABB given in parameter
RP3D_FORCE_INLINE bool AABB::contains(const AABB& aabb) const {
bool isInside = true;
isInside = isInside && mMinCoordinates.x <= aabb.mMinCoordinates.x;
isInside = isInside && mMinCoordinates.y <= aabb.mMinCoordinates.y;
isInside = isInside && mMinCoordinates.z <= aabb.mMinCoordinates.z;
isInside = isInside && mMaxCoordinates.x >= aabb.mMaxCoordinates.x;
isInside = isInside && mMaxCoordinates.y >= aabb.mMaxCoordinates.y;
isInside = isInside && mMaxCoordinates.z >= aabb.mMaxCoordinates.z;
return isInside;
}
// Create and return an AABB for a triangle
RP3D_FORCE_INLINE AABB AABB::createAABBForTriangle(const Vector3* trianglePoints) {
Vector3 minCoords(trianglePoints[0].x, trianglePoints[0].y, trianglePoints[0].z);
Vector3 maxCoords(trianglePoints[0].x, trianglePoints[0].y, trianglePoints[0].z);
if (trianglePoints[1].x < minCoords.x) minCoords.x = trianglePoints[1].x;
if (trianglePoints[1].y < minCoords.y) minCoords.y = trianglePoints[1].y;
if (trianglePoints[1].z < minCoords.z) minCoords.z = trianglePoints[1].z;
if (trianglePoints[2].x < minCoords.x) minCoords.x = trianglePoints[2].x;
if (trianglePoints[2].y < minCoords.y) minCoords.y = trianglePoints[2].y;
if (trianglePoints[2].z < minCoords.z) minCoords.z = trianglePoints[2].z;
if (trianglePoints[1].x > maxCoords.x) maxCoords.x = trianglePoints[1].x;
if (trianglePoints[1].y > maxCoords.y) maxCoords.y = trianglePoints[1].y;
if (trianglePoints[1].z > maxCoords.z) maxCoords.z = trianglePoints[1].z;
if (trianglePoints[2].x > maxCoords.x) maxCoords.x = trianglePoints[2].x;
if (trianglePoints[2].y > maxCoords.y) maxCoords.y = trianglePoints[2].y;
if (trianglePoints[2].z > maxCoords.z) maxCoords.z = trianglePoints[2].z;
return AABB(minCoords, maxCoords);
}
// Return true if the ray intersects the AABB
RP3D_FORCE_INLINE bool AABB::testRayIntersect(const Vector3& rayOrigin, const Vector3& rayDirectionInverse, decimal rayMaxFraction) const {
// This algorithm relies on the IEE floating point properties (division by zero). If the rayDirection is zero, rayDirectionInverse and
// therfore t1 and t2 will be +-INFINITY. If the i coordinate of the ray's origin is inside the AABB (mMinCoordinates[i] < rayOrigin[i] < mMaxCordinates[i)), we have
// t1 = -t2 = +- INFINITY. Since max(n, -INFINITY) = min(n, INFINITY) = n for all n, tMin and tMax will stay unchanged. Secondly, if the i
// coordinate of the ray's origin is outside the box (rayOrigin[i] < mMinCoordinates[i] or rayOrigin[i] > mMaxCoordinates[i]) we have
// t1 = t2 = +- INFINITY and therefore either tMin = +INFINITY or tMax = -INFINITY. One of those values will stay until the end and make the
// method to return false. Unfortunately, if the ray lies exactly on a slab (rayOrigin[i] = mMinCoordinates[i] or rayOrigin[i] = mMaxCoordinates[i]) we
// have t1 = (mMinCoordinates[i] - rayOrigin[i]) * rayDirectionInverse[i] = 0 * INFINITY = NaN which is a problem for the remaining of the algorithm.
// This will cause the method to return true when the ray is not intersecting the AABB and therefore cause to traverse more nodes than necessary in
// the BVH tree. Because this should be rare, it is not really a big issue.
// Reference: https://tavianator.com/2011/ray_box.html
decimal t1 = (mMinCoordinates[0] - rayOrigin[0]) * rayDirectionInverse[0];
decimal t2 = (mMaxCoordinates[0] - rayOrigin[0]) * rayDirectionInverse[0];
decimal tMin = std::min(t1, t2);
decimal tMax = std::max(t1, t2);
tMax = std::min(tMax, rayMaxFraction);
for (int i = 1; i < 3; i++) {
t1 = (mMinCoordinates[i] - rayOrigin[i]) * rayDirectionInverse[i];
t2 = (mMaxCoordinates[i] - rayOrigin[i]) * rayDirectionInverse[i];
tMin = std::max(tMin, std::min(t1, t2));
tMax = std::min(tMax, std::max(t1, t2));
}
return *this;
return tMax >= std::max(tMin, decimal(0.0));
}
// Compute the intersection of a ray and the AABB
RP3D_FORCE_INLINE bool AABB::raycast(const Ray& ray, Vector3& hitPoint) const {
decimal tMin = decimal(0.0);
decimal tMax = DECIMAL_LARGEST;
const decimal epsilon = decimal(0.00001);
const Vector3 rayDirection = ray.point2 - ray.point1;
// For all three slabs
for (int i=0; i < 3; i++) {
// If the ray is parallel to the slab
if (std::abs(rayDirection[i]) < epsilon) {
// If origin of the ray is not inside the slab, no hit
if (ray.point1[i] < mMinCoordinates[i] || ray.point1[i] > mMaxCoordinates[i]) return false;
}
else {
decimal rayDirectionInverse = decimal(1.0) / rayDirection[i];
decimal t1 = (mMinCoordinates[i] - ray.point1[i]) * rayDirectionInverse;
decimal t2 = (mMaxCoordinates[i] - ray.point1[i]) * rayDirectionInverse;
if (t1 > t2) {
// Swap t1 and t2
decimal tTemp = t2;
t2 = t1;
t1 = tTemp;
}
tMin = std::max(tMin, t1);
tMax = std::min(tMax, t2);
// Exit with no collision
if (tMin > tMax) return false;
}
}
// Compute the hit point
hitPoint = ray.point1 + tMin * rayDirection;
return true;
}
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -36,6 +36,7 @@ namespace reactphysics3d {
// Declarations
class CollisionBody;
class DefaultAllocator;
class PhysicsCommon;
// Class BoxShape
/**
@ -53,13 +54,13 @@ class BoxShape : public ConvexPolyhedronShape {
/// Half-extents of the box in the x, y and z direction
Vector3 mHalfExtents;
/// Half-edge structure of the polyhedron
HalfEdgeStructure mHalfEdgeStructure;
/// Reference to the physics common object
PhysicsCommon& mPhysicsCommon;
// -------------------- Methods -------------------- //
/// Constructor
BoxShape(const Vector3& halfExtents, MemoryAllocator& allocator);
BoxShape(const Vector3& halfExtents, MemoryAllocator& allocator, PhysicsCommon& physicsCommon);
/// Return a local support point in a given direction without the object margin
virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction) const override;
@ -102,28 +103,28 @@ class BoxShape : public ConvexPolyhedronShape {
virtual decimal getVolume() const override;
/// Return the number of faces of the polyhedron
virtual uint getNbFaces() const override;
virtual uint32 getNbFaces() const override;
/// Return a given face of the polyhedron
virtual const HalfEdgeStructure::Face& getFace(uint faceIndex) const override;
virtual const HalfEdgeStructure::Face& getFace(uint32 faceIndex) const override;
/// Return the number of vertices of the polyhedron
virtual uint getNbVertices() const override;
virtual uint32 getNbVertices() const override;
/// Return a given vertex of the polyhedron
virtual HalfEdgeStructure::Vertex getVertex(uint vertexIndex) const override;
virtual const HalfEdgeStructure::Vertex& getVertex(uint32 vertexIndex) const override;
/// Return the number of half-edges of the polyhedron
virtual uint getNbHalfEdges() const override;
virtual uint32 getNbHalfEdges() const override;
/// Return a given half-edge of the polyhedron
virtual const HalfEdgeStructure::Edge& getHalfEdge(uint edgeIndex) const override;
virtual const HalfEdgeStructure::Edge& getHalfEdge(uint32 edgeIndex) const override;
/// Return the position of a given vertex
virtual Vector3 getVertexPosition(uint vertexIndex) const override;
virtual Vector3 getVertexPosition(uint32 vertexIndex) const override;
/// Return the normal vector of a given face of the polyhedron
virtual Vector3 getFaceNormal(uint faceIndex) const override;
virtual Vector3 getFaceNormal(uint32 faceIndex) const override;
/// Return the centroid of the polyhedron
virtual Vector3 getCentroid() const override;
@ -140,7 +141,7 @@ class BoxShape : public ConvexPolyhedronShape {
/**
* @return The vector with the three half-extents of the box shape
*/
inline Vector3 BoxShape::getHalfExtents() const {
RP3D_FORCE_INLINE Vector3 BoxShape::getHalfExtents() const {
return mHalfExtents;
}
@ -150,7 +151,7 @@ inline Vector3 BoxShape::getHalfExtents() const {
/**
* @param halfExtents The vector with the three half-extents of the box
*/
inline void BoxShape::setHalfExtents(const Vector3& halfExtents) {
RP3D_FORCE_INLINE void BoxShape::setHalfExtents(const Vector3& halfExtents) {
mHalfExtents = halfExtents;
notifyColliderAboutChangedSize();
@ -162,7 +163,7 @@ inline void BoxShape::setHalfExtents(const Vector3& halfExtents) {
* @param min The minimum bounds of the shape in local-space coordinates
* @param max The maximum bounds of the shape in local-space coordinates
*/
inline void BoxShape::getLocalBounds(Vector3& min, Vector3& max) const {
RP3D_FORCE_INLINE void BoxShape::getLocalBounds(Vector3& min, Vector3& max) const {
// Maximum bounds
max = mHalfExtents;
@ -172,12 +173,12 @@ inline void BoxShape::getLocalBounds(Vector3& min, Vector3& max) const {
}
// Return the number of bytes used by the collision shape
inline size_t BoxShape::getSizeInBytes() const {
RP3D_FORCE_INLINE size_t BoxShape::getSizeInBytes() const {
return sizeof(BoxShape);
}
// Return a local support point in a given direction without the object margin
inline Vector3 BoxShape::getLocalSupportPointWithoutMargin(const Vector3& direction) const {
RP3D_FORCE_INLINE Vector3 BoxShape::getLocalSupportPointWithoutMargin(const Vector3& direction) const {
return Vector3(direction.x < decimal(0.0) ? -mHalfExtents.x : mHalfExtents.x,
direction.y < decimal(0.0) ? -mHalfExtents.y : mHalfExtents.y,
@ -185,49 +186,35 @@ inline Vector3 BoxShape::getLocalSupportPointWithoutMargin(const Vector3& direct
}
// Return true if a point is inside the collision shape
inline bool BoxShape::testPointInside(const Vector3& localPoint, Collider* collider) const {
RP3D_FORCE_INLINE bool BoxShape::testPointInside(const Vector3& localPoint, Collider* /*collider*/) const {
return (localPoint.x < mHalfExtents[0] && localPoint.x > -mHalfExtents[0] &&
localPoint.y < mHalfExtents[1] && localPoint.y > -mHalfExtents[1] &&
localPoint.z < mHalfExtents[2] && localPoint.z > -mHalfExtents[2]);
}
// Return the number of faces of the polyhedron
inline uint BoxShape::getNbFaces() const {
RP3D_FORCE_INLINE uint32 BoxShape::getNbFaces() const {
return 6;
}
// Return a given face of the polyhedron
inline const HalfEdgeStructure::Face& BoxShape::getFace(uint faceIndex) const {
assert(faceIndex < mHalfEdgeStructure.getNbFaces());
return mHalfEdgeStructure.getFace(faceIndex);
}
// Return the number of vertices of the polyhedron
inline uint BoxShape::getNbVertices() const {
RP3D_FORCE_INLINE uint32 BoxShape::getNbVertices() const {
return 8;
}
// Return a given vertex of the polyhedron
inline HalfEdgeStructure::Vertex BoxShape::getVertex(uint vertexIndex) const {
assert(vertexIndex < getNbVertices());
return mHalfEdgeStructure.getVertex(vertexIndex);
}
// Return the position of a given vertex
inline Vector3 BoxShape::getVertexPosition(uint vertexIndex) const {
RP3D_FORCE_INLINE Vector3 BoxShape::getVertexPosition(uint32 vertexIndex) const {
assert(vertexIndex < getNbVertices());
Vector3 extent = getHalfExtents();
switch(vertexIndex) {
case 0: return Vector3(-extent.x, -extent.y, extent.z);
case 1: return Vector3(extent.x, -extent.y, extent.z);
case 2: return Vector3(extent.x, extent.y, extent.z);
case 3: return Vector3(-extent.x, extent.y, extent.z);
case 4: return Vector3(-extent.x, -extent.y, -extent.z);
case 5: return Vector3(extent.x, -extent.y, -extent.z);
case 6: return Vector3(extent.x, extent.y, -extent.z);
case 7: return Vector3(-extent.x, extent.y, -extent.z);
case 0: return Vector3(-mHalfExtents.x, -mHalfExtents.y, mHalfExtents.z);
case 1: return Vector3(mHalfExtents.x, -mHalfExtents.y, mHalfExtents.z);
case 2: return Vector3(mHalfExtents.x, mHalfExtents.y, mHalfExtents.z);
case 3: return Vector3(-mHalfExtents.x, mHalfExtents.y, mHalfExtents.z);
case 4: return Vector3(-mHalfExtents.x, -mHalfExtents.y, -mHalfExtents.z);
case 5: return Vector3(mHalfExtents.x, -mHalfExtents.y, -mHalfExtents.z);
case 6: return Vector3(mHalfExtents.x, mHalfExtents.y, -mHalfExtents.z);
case 7: return Vector3(-mHalfExtents.x, mHalfExtents.y, -mHalfExtents.z);
}
assert(false);
@ -235,7 +222,7 @@ inline Vector3 BoxShape::getVertexPosition(uint vertexIndex) const {
}
// Return the normal vector of a given face of the polyhedron
inline Vector3 BoxShape::getFaceNormal(uint faceIndex) const {
RP3D_FORCE_INLINE Vector3 BoxShape::getFaceNormal(uint32 faceIndex) const {
assert(faceIndex < getNbFaces());
switch(faceIndex) {
@ -252,31 +239,25 @@ inline Vector3 BoxShape::getFaceNormal(uint faceIndex) const {
}
// Return the centroid of the box
inline Vector3 BoxShape::getCentroid() const {
RP3D_FORCE_INLINE Vector3 BoxShape::getCentroid() const {
return Vector3::zero();
}
// Compute and return the volume of the collision shape
inline decimal BoxShape::getVolume() const {
RP3D_FORCE_INLINE decimal BoxShape::getVolume() const {
return 8 * mHalfExtents.x * mHalfExtents.y * mHalfExtents.z;
}
// Return the string representation of the shape
inline std::string BoxShape::to_string() const {
RP3D_FORCE_INLINE std::string BoxShape::to_string() const {
return "BoxShape{extents=" + mHalfExtents.to_string() + "}";
}
// Return the number of half-edges of the polyhedron
inline uint BoxShape::getNbHalfEdges() const {
RP3D_FORCE_INLINE uint32 BoxShape::getNbHalfEdges() const {
return 24;
}
// Return a given half-edge of the polyhedron
inline const HalfEdgeStructure::Edge& BoxShape::getHalfEdge(uint edgeIndex) const {
assert(edgeIndex < getNbHalfEdges());
return mHalfEdgeStructure.getHalfEdge(edgeIndex);
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -126,7 +126,7 @@ class CapsuleShape : public ConvexShape {
/**
* @return The radius of the capsule shape (in meters)
*/
inline decimal CapsuleShape::getRadius() const {
RP3D_FORCE_INLINE decimal CapsuleShape::getRadius() const {
return mMargin;
}
@ -136,7 +136,7 @@ inline decimal CapsuleShape::getRadius() const {
/**
* @param radius The radius of the capsule (in meters)
*/
inline void CapsuleShape::setRadius(decimal radius) {
RP3D_FORCE_INLINE void CapsuleShape::setRadius(decimal radius) {
assert(radius > decimal(0.0));
mMargin = radius;
@ -148,7 +148,7 @@ inline void CapsuleShape::setRadius(decimal radius) {
/**
* @return The height of the capsule shape (in meters)
*/
inline decimal CapsuleShape::getHeight() const {
RP3D_FORCE_INLINE decimal CapsuleShape::getHeight() const {
return mHalfHeight + mHalfHeight;
}
@ -158,7 +158,7 @@ inline decimal CapsuleShape::getHeight() const {
/**
* @param height The height of the capsule (in meters)
*/
inline void CapsuleShape::setHeight(decimal height) {
RP3D_FORCE_INLINE void CapsuleShape::setHeight(decimal height) {
assert(height > decimal(0.0));
mHalfHeight = height * decimal(0.5);
@ -167,7 +167,7 @@ inline void CapsuleShape::setHeight(decimal height) {
}
// Return the number of bytes used by the collision shape
inline size_t CapsuleShape::getSizeInBytes() const {
RP3D_FORCE_INLINE size_t CapsuleShape::getSizeInBytes() const {
return sizeof(CapsuleShape);
}
@ -177,7 +177,7 @@ inline size_t CapsuleShape::getSizeInBytes() const {
* @param min The minimum bounds of the shape in local-space coordinates
* @param max The maximum bounds of the shape in local-space coordinates
*/
inline void CapsuleShape::getLocalBounds(Vector3& min, Vector3& max) const {
RP3D_FORCE_INLINE void CapsuleShape::getLocalBounds(Vector3& min, Vector3& max) const {
// Maximum bounds
max.x = mMargin;
@ -191,12 +191,12 @@ inline void CapsuleShape::getLocalBounds(Vector3& min, Vector3& max) const {
}
// Compute and return the volume of the collision shape
inline decimal CapsuleShape::getVolume() const {
return reactphysics3d::PI * mMargin * mMargin * (decimal(4.0) * mMargin / decimal(3.0) + decimal(2.0) * mHalfHeight);
RP3D_FORCE_INLINE decimal CapsuleShape::getVolume() const {
return reactphysics3d::PI_RP3D * mMargin * mMargin * (decimal(4.0) * mMargin / decimal(3.0) + decimal(2.0) * mHalfHeight);
}
// Return true if the collision shape is a polyhedron
inline bool CapsuleShape::isPolyhedron() const {
RP3D_FORCE_INLINE bool CapsuleShape::isPolyhedron() const {
return false;
}
@ -207,7 +207,7 @@ inline bool CapsuleShape::isPolyhedron() const {
/// Therefore, in this method, we compute the support points of both top and bottom spheres of
/// the capsule and return the point with the maximum dot product with the direction vector. Note
/// that the object margin is implicitly the radius and height of the capsule.
inline Vector3 CapsuleShape::getLocalSupportPointWithoutMargin(const Vector3& direction) const {
RP3D_FORCE_INLINE Vector3 CapsuleShape::getLocalSupportPointWithoutMargin(const Vector3& direction) const {
// Support point top sphere
decimal dotProductTop = mHalfHeight * direction.y;
@ -225,7 +225,7 @@ inline Vector3 CapsuleShape::getLocalSupportPointWithoutMargin(const Vector3& di
}
// Return the string representation of the shape
inline std::string CapsuleShape::to_string() const {
RP3D_FORCE_INLINE std::string CapsuleShape::to_string() const {
return "CapsuleShape{halfHeight=" + std::to_string(mHalfHeight) + ", radius=" + std::to_string(getRadius()) + "}";
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -30,7 +30,7 @@
#include <cassert>
#include <reactphysics3d/configuration.h>
#include <reactphysics3d/utils/Profiler.h>
#include <reactphysics3d/containers/List.h>
#include <reactphysics3d/containers/Array.h>
/// ReactPhysics3D namespace
namespace reactphysics3d {
@ -76,8 +76,8 @@ class CollisionShape {
/// Unique identifier of the shape inside an overlapping pair
uint32 mId;
/// List of the colliders associated with this shape
List<Collider*> mColliders;
/// Array of the colliders associated with this shape
Array<Collider*> mColliders;
#ifdef IS_RP3D_PROFILING_ENABLED
@ -89,7 +89,7 @@ class CollisionShape {
// -------------------- Methods -------------------- //
/// Return true if a point is inside the collision shape
virtual bool testPointInside(const Vector3& worldPoint, Collider* collider) const=0;
virtual bool testPointInside(const Vector3& localPoint, Collider* collider) const=0;
/// Raycast method with feedback information
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, Collider* collider, MemoryAllocator& allocator) const=0;
@ -164,6 +164,7 @@ class CollisionShape {
friend class Collider;
friend class CollisionBody;
friend class RigidBody;
friend class PhysicsWorld;
friend class BroadPhaseSystem;
};
@ -171,7 +172,7 @@ class CollisionShape {
/**
* @return The name of the collision shape (box, sphere, triangle, ...)
*/
inline CollisionShapeName CollisionShape::getName() const {
RP3D_FORCE_INLINE CollisionShapeName CollisionShape::getName() const {
return mName;
}
@ -179,29 +180,29 @@ inline CollisionShapeName CollisionShape::getName() const {
/**
* @return The type of the collision shape (sphere, capsule, convex polyhedron, concave mesh)
*/
inline CollisionShapeType CollisionShape::getType() const {
RP3D_FORCE_INLINE CollisionShapeType CollisionShape::getType() const {
return mType;
}
// Return the id of the shape
inline uint32 CollisionShape::getId() const {
RP3D_FORCE_INLINE uint32 CollisionShape::getId() const {
return mId;
}
// Assign a new collider to the collision shape
inline void CollisionShape::addCollider(Collider* collider) {
RP3D_FORCE_INLINE void CollisionShape::addCollider(Collider* collider) {
mColliders.add(collider);
}
// Remove an assigned collider from the collision shape
inline void CollisionShape::removeCollider(Collider* collider) {
RP3D_FORCE_INLINE void CollisionShape::removeCollider(Collider* collider) {
mColliders.remove(collider);
}
#ifdef IS_RP3D_PROFILING_ENABLED
// Set the profiler
inline void CollisionShape::setProfiler(Profiler* profiler) {
RP3D_FORCE_INLINE void CollisionShape::setProfiler(Profiler* profiler) {
mProfiler = profiler;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -29,7 +29,7 @@
// Libraries
#include <reactphysics3d/collision/shapes/ConcaveShape.h>
#include <reactphysics3d/collision/broadphase/DynamicAABBTree.h>
#include <reactphysics3d/containers/List.h>
#include <reactphysics3d/containers/Array.h>
namespace reactphysics3d {
@ -72,7 +72,7 @@ class ConcaveMeshRaycastCallback : public DynamicAABBTreeRaycastCallback {
private :
List<int32> mHitAABBNodes;
Array<int32> mHitAABBNodes;
const DynamicAABBTree& mDynamicAABBTree;
const ConcaveMeshShape& mConcaveMeshShape;
Collider* mCollider;
@ -142,10 +142,13 @@ class ConcaveMeshShape : public ConcaveShape {
/// if the user did not provide its own vertices normals)
Vector3** mComputedVerticesNormals;
/// Reference to the triangle half-edge structure
HalfEdgeStructure& mTriangleHalfEdgeStructure;
// -------------------- Methods -------------------- //
/// Constructor
ConcaveMeshShape(TriangleMesh* triangleMesh, MemoryAllocator& allocator, const Vector3& scaling = Vector3(1, 1, 1));
ConcaveMeshShape(TriangleMesh* triangleMesh, MemoryAllocator& allocator, HalfEdgeStructure& triangleHalfEdgeStructure, const Vector3& scaling = Vector3(1, 1, 1));
/// Raycast method with feedback information
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, Collider* collider, MemoryAllocator& allocator) const override;
@ -156,18 +159,18 @@ class ConcaveMeshShape : public ConcaveShape {
/// Insert all the triangles into the dynamic AABB tree
void initBVHTree();
/// Return the three vertices coordinates (in the list outTriangleVertices) of a triangle
void getTriangleVertices(uint subPart, uint triangleIndex, Vector3* outTriangleVertices) const;
/// Return the three vertices coordinates (in the array outTriangleVertices) of a triangle
void getTriangleVertices(uint32 subPart, uint32 triangleIndex, Vector3* outTriangleVertices) const;
/// Return the three vertex normals (in the array outVerticesNormals) of a triangle
void getTriangleVerticesNormals(uint subPart, uint triangleIndex, Vector3* outVerticesNormals) const;
void getTriangleVerticesNormals(uint32 subPart, uint32 triangleIndex, Vector3* outVerticesNormals) const;
/// Compute the shape Id for a given triangle of the mesh
uint computeTriangleShapeId(uint subPart, uint triangleIndex) const;
uint32 computeTriangleShapeId(uint32 subPart, uint32 triangleIndex) const;
/// Compute all the triangles of the mesh that are overlapping with the AABB in parameter
virtual void computeOverlappingTriangles(const AABB& localAABB, List<Vector3>& triangleVertices,
List<Vector3> &triangleVerticesNormals, List<uint>& shapeIds,
virtual void computeOverlappingTriangles(const AABB& localAABB, Array<Vector3>& triangleVertices,
Array<Vector3> &triangleVerticesNormals, Array<uint32>& shapeIds,
MemoryAllocator& allocator) const override;
/// Destructor
@ -182,13 +185,13 @@ class ConcaveMeshShape : public ConcaveShape {
ConcaveMeshShape& operator=(const ConcaveMeshShape& shape) = delete;
/// Return the number of sub parts contained in this mesh
uint getNbSubparts() const;
uint32 getNbSubparts() const;
/// Return the number of triangles in a sub part of the mesh
uint getNbTriangles(uint subPart) const;
uint32 getNbTriangles(uint32 subPart) const;
/// Return the indices of the three vertices of a given triangle in the array
void getTriangleVerticesIndices(uint subPart, uint triangleIndex, uint* outVerticesIndices) const;
void getTriangleVerticesIndices(uint32 subPart, uint32 triangleIndex, uint32* outVerticesIndices) const;
/// Return the local bounds of the shape in x, y and z directions.
virtual void getLocalBounds(Vector3& min, Vector3& max) const override;
@ -212,7 +215,7 @@ class ConcaveMeshShape : public ConcaveShape {
};
// Return the number of bytes used by the collision shape
inline size_t ConcaveMeshShape::getSizeInBytes() const {
RP3D_FORCE_INLINE size_t ConcaveMeshShape::getSizeInBytes() const {
return sizeof(ConcaveMeshShape);
}
@ -222,7 +225,7 @@ inline size_t ConcaveMeshShape::getSizeInBytes() const {
* @param min The minimum bounds of the shape in local-space coordinates
* @param max The maximum bounds of the shape in local-space coordinates
*/
inline void ConcaveMeshShape::getLocalBounds(Vector3& min, Vector3& max) const {
RP3D_FORCE_INLINE void ConcaveMeshShape::getLocalBounds(Vector3& min, Vector3& max) const {
// Get the AABB of the whole tree
AABB treeAABB = mDynamicAABBTree.getRootAABB();
@ -233,7 +236,7 @@ inline void ConcaveMeshShape::getLocalBounds(Vector3& min, Vector3& max) const {
// Called when a overlapping node has been found during the call to
// DynamicAABBTree:reportAllShapesOverlappingWithAABB()
inline void ConvexTriangleAABBOverlapCallback::notifyOverlappingNode(int nodeId) {
RP3D_FORCE_INLINE void ConvexTriangleAABBOverlapCallback::notifyOverlappingNode(int nodeId) {
// Get the node data (triangle index and mesh subpart index)
int32* data = mDynamicAABBTree.getNodeDataInt(nodeId);
@ -253,7 +256,7 @@ inline void ConvexTriangleAABBOverlapCallback::notifyOverlappingNode(int nodeId)
#ifdef IS_RP3D_PROFILING_ENABLED
// Set the profiler
inline void ConcaveMeshShape::setProfiler(Profiler* profiler) {
RP3D_FORCE_INLINE void ConcaveMeshShape::setProfiler(Profiler* profiler) {
CollisionShape::setProfiler(profiler);

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -46,7 +46,7 @@ class TriangleCallback {
virtual ~TriangleCallback() = default;
/// Report a triangle
virtual void testTriangle(const Vector3* trianglePoints, const Vector3* verticesNormals, uint shapeId)=0;
virtual void testTriangle(const Vector3* trianglePoints, const Vector3* verticesNormals, uint32 shapeId)=0;
};
@ -111,8 +111,8 @@ class ConcaveShape : public CollisionShape {
virtual bool isPolyhedron() const override;
/// Use a callback method on all triangles of the concave shape inside a given AABB
virtual void computeOverlappingTriangles(const AABB& localAABB, List<Vector3>& triangleVertices,
List<Vector3>& triangleVerticesNormals, List<uint>& shapeIds,
virtual void computeOverlappingTriangles(const AABB& localAABB, Array<Vector3>& triangleVertices,
Array<Vector3>& triangleVerticesNormals, Array<uint32>& shapeIds,
MemoryAllocator& allocator) const=0;
/// Compute and return the volume of the collision shape
@ -120,22 +120,22 @@ class ConcaveShape : public CollisionShape {
};
// Return true if the collision shape is convex, false if it is concave
inline bool ConcaveShape::isConvex() const {
RP3D_FORCE_INLINE bool ConcaveShape::isConvex() const {
return false;
}
// Return true if the collision shape is a polyhedron
inline bool ConcaveShape::isPolyhedron() const {
RP3D_FORCE_INLINE bool ConcaveShape::isPolyhedron() const {
return true;
}
// Return true if a point is inside the collision shape
inline bool ConcaveShape::testPointInside(const Vector3& localPoint, Collider* collider) const {
RP3D_FORCE_INLINE bool ConcaveShape::testPointInside(const Vector3& /*localPoint*/, Collider* /*collider*/) const {
return false;
}
// Return the raycast test type (front, back, front-back)
inline TriangleRaycastSide ConcaveShape::getRaycastTestType() const {
RP3D_FORCE_INLINE TriangleRaycastSide ConcaveShape::getRaycastTestType() const {
return mRaycastTestType;
}
@ -143,19 +143,19 @@ inline TriangleRaycastSide ConcaveShape::getRaycastTestType() const {
/**
* @param testType Raycast test type for the triangle (front, back, front-back)
*/
inline void ConcaveShape::setRaycastTestType(TriangleRaycastSide testType) {
RP3D_FORCE_INLINE void ConcaveShape::setRaycastTestType(TriangleRaycastSide testType) {
mRaycastTestType = testType;
}
// Return the scale of the shape
inline const Vector3& ConcaveShape::getScale() const {
RP3D_FORCE_INLINE const Vector3& ConcaveShape::getScale() const {
return mScale;
}
// Set the scale of the shape
/// Note that you might want to recompute the inertia tensor and center of mass of the body
/// after changing the scale of a collision shape
inline void ConcaveShape::setScale(const Vector3& scale) {
RP3D_FORCE_INLINE void ConcaveShape::setScale(const Vector3& scale) {
mScale = scale;
notifyColliderAboutChangedSize();
@ -165,7 +165,7 @@ inline void ConcaveShape::setScale(const Vector3& scale) {
/**
* @param mass Mass to use to compute the inertia tensor of the collision shape
*/
inline Vector3 ConcaveShape::getLocalInertiaTensor(decimal mass) const {
RP3D_FORCE_INLINE Vector3 ConcaveShape::getLocalInertiaTensor(decimal mass) const {
// Default inertia tensor
// Note that this is not very realistic for a concave triangle mesh.

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -109,28 +109,28 @@ class ConvexMeshShape : public ConvexPolyhedronShape {
virtual Vector3 getLocalInertiaTensor(decimal mass) const override;
/// Return the number of faces of the polyhedron
virtual uint getNbFaces() const override;
virtual uint32 getNbFaces() const override;
/// Return a given face of the polyhedron
virtual const HalfEdgeStructure::Face& getFace(uint faceIndex) const override;
virtual const HalfEdgeStructure::Face& getFace(uint32 faceIndex) const override;
/// Return the number of vertices of the polyhedron
virtual uint getNbVertices() const override;
virtual uint32 getNbVertices() const override;
/// Return a given vertex of the polyhedron
virtual HalfEdgeStructure::Vertex getVertex(uint vertexIndex) const override;
virtual const HalfEdgeStructure::Vertex& getVertex(uint32 vertexIndex) const override;
/// Return the number of half-edges of the polyhedron
virtual uint getNbHalfEdges() const override;
virtual uint32 getNbHalfEdges() const override;
/// Return a given half-edge of the polyhedron
virtual const HalfEdgeStructure::Edge& getHalfEdge(uint edgeIndex) const override;
virtual const HalfEdgeStructure::Edge& getHalfEdge(uint32 edgeIndex) const override;
/// Return the position of a given vertex
virtual Vector3 getVertexPosition(uint vertexIndex) const override;
virtual Vector3 getVertexPosition(uint32 vertexIndex) const override;
/// Return the normal vector of a given face of the polyhedron
virtual Vector3 getFaceNormal(uint faceIndex) const override;
virtual Vector3 getFaceNormal(uint32 faceIndex) const override;
/// Return the centroid of the polyhedron
virtual Vector3 getCentroid() const override;
@ -147,19 +147,19 @@ class ConvexMeshShape : public ConvexPolyhedronShape {
};
// Return the number of bytes used by the collision shape
inline size_t ConvexMeshShape::getSizeInBytes() const {
RP3D_FORCE_INLINE size_t ConvexMeshShape::getSizeInBytes() const {
return sizeof(ConvexMeshShape);
}
// Return the scaling vector
inline const Vector3& ConvexMeshShape::getScale() const {
RP3D_FORCE_INLINE const Vector3& ConvexMeshShape::getScale() const {
return mScale;
}
// Set the scale
/// Note that you might want to recompute the inertia tensor and center of mass of the body
/// after changing the scale of a collision shape
inline void ConvexMeshShape::setScale(const Vector3& scale) {
RP3D_FORCE_INLINE void ConvexMeshShape::setScale(const Vector3& scale) {
mScale = scale;
recalculateBounds();
notifyColliderAboutChangedSize();
@ -170,7 +170,7 @@ inline void ConvexMeshShape::setScale(const Vector3& scale) {
* @param min The minimum bounds of the shape in local-space coordinates
* @param max The maximum bounds of the shape in local-space coordinates
*/
inline void ConvexMeshShape::getLocalBounds(Vector3& min, Vector3& max) const {
RP3D_FORCE_INLINE void ConvexMeshShape::getLocalBounds(Vector3& min, Vector3& max) const {
min = mMinBounds;
max = mMaxBounds;
}
@ -181,7 +181,7 @@ inline void ConvexMeshShape::getLocalBounds(Vector3& min, Vector3& max) const {
/**
* @param mass Mass to use to compute the inertia tensor of the collision shape
*/
inline Vector3 ConvexMeshShape::getLocalInertiaTensor(decimal mass) const {
RP3D_FORCE_INLINE Vector3 ConvexMeshShape::getLocalInertiaTensor(decimal mass) const {
const decimal factor = (decimal(1.0) / decimal(3.0)) * mass;
const Vector3 realExtent = decimal(0.5) * (mMaxBounds - mMinBounds);
assert(realExtent.x > 0 && realExtent.y > 0 && realExtent.z > 0);
@ -192,58 +192,58 @@ inline Vector3 ConvexMeshShape::getLocalInertiaTensor(decimal mass) const {
}
// Return the number of faces of the polyhedron
inline uint ConvexMeshShape::getNbFaces() const {
RP3D_FORCE_INLINE uint32 ConvexMeshShape::getNbFaces() const {
return mPolyhedronMesh->getHalfEdgeStructure().getNbFaces();
}
// Return a given face of the polyhedron
inline const HalfEdgeStructure::Face& ConvexMeshShape::getFace(uint faceIndex) const {
RP3D_FORCE_INLINE const HalfEdgeStructure::Face& ConvexMeshShape::getFace(uint32 faceIndex) const {
assert(faceIndex < getNbFaces());
return mPolyhedronMesh->getHalfEdgeStructure().getFace(faceIndex);
}
// Return the number of vertices of the polyhedron
inline uint ConvexMeshShape::getNbVertices() const {
RP3D_FORCE_INLINE uint32 ConvexMeshShape::getNbVertices() const {
return mPolyhedronMesh->getHalfEdgeStructure().getNbVertices();
}
// Return a given vertex of the polyhedron
inline HalfEdgeStructure::Vertex ConvexMeshShape::getVertex(uint vertexIndex) const {
RP3D_FORCE_INLINE const HalfEdgeStructure::Vertex& ConvexMeshShape::getVertex(uint32 vertexIndex) const {
assert(vertexIndex < getNbVertices());
return mPolyhedronMesh->getHalfEdgeStructure().getVertex(vertexIndex);
}
// Return the number of half-edges of the polyhedron
inline uint ConvexMeshShape::getNbHalfEdges() const {
RP3D_FORCE_INLINE uint32 ConvexMeshShape::getNbHalfEdges() const {
return mPolyhedronMesh->getHalfEdgeStructure().getNbHalfEdges();
}
// Return a given half-edge of the polyhedron
inline const HalfEdgeStructure::Edge& ConvexMeshShape::getHalfEdge(uint edgeIndex) const {
RP3D_FORCE_INLINE const HalfEdgeStructure::Edge& ConvexMeshShape::getHalfEdge(uint32 edgeIndex) const {
assert(edgeIndex < getNbHalfEdges());
return mPolyhedronMesh->getHalfEdgeStructure().getHalfEdge(edgeIndex);
}
// Return the position of a given vertex
inline Vector3 ConvexMeshShape::getVertexPosition(uint vertexIndex) const {
RP3D_FORCE_INLINE Vector3 ConvexMeshShape::getVertexPosition(uint32 vertexIndex) const {
assert(vertexIndex < getNbVertices());
return mPolyhedronMesh->getVertex(vertexIndex) * mScale;
}
// Return the normal vector of a given face of the polyhedron
inline Vector3 ConvexMeshShape::getFaceNormal(uint faceIndex) const {
RP3D_FORCE_INLINE Vector3 ConvexMeshShape::getFaceNormal(uint32 faceIndex) const {
assert(faceIndex < getNbFaces());
return mPolyhedronMesh->getFaceNormal(faceIndex);
}
// Return the centroid of the polyhedron
inline Vector3 ConvexMeshShape::getCentroid() const {
RP3D_FORCE_INLINE Vector3 ConvexMeshShape::getCentroid() const {
return mPolyhedronMesh->getCentroid() * mScale;
}
// Compute and return the volume of the collision shape
inline decimal ConvexMeshShape::getVolume() const {
RP3D_FORCE_INLINE decimal ConvexMeshShape::getVolume() const {
return mPolyhedronMesh->getVolume();
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -59,28 +59,28 @@ class ConvexPolyhedronShape : public ConvexShape {
ConvexPolyhedronShape& operator=(const ConvexPolyhedronShape& shape) = delete;
/// Return the number of faces of the polyhedron
virtual uint getNbFaces() const=0;
virtual uint32 getNbFaces() const=0;
/// Return a given face of the polyhedron
virtual const HalfEdgeStructure::Face& getFace(uint faceIndex) const=0;
virtual const HalfEdgeStructure::Face& getFace(uint32 faceIndex) const=0;
/// Return the number of vertices of the polyhedron
virtual uint getNbVertices() const=0;
virtual uint32 getNbVertices() const=0;
/// Return a given vertex of the polyhedron
virtual HalfEdgeStructure::Vertex getVertex(uint vertexIndex) const=0;
virtual const HalfEdgeStructure::Vertex& getVertex(uint32 vertexIndex) const=0;
/// Return the position of a given vertex
virtual Vector3 getVertexPosition(uint vertexIndex) const=0;
virtual Vector3 getVertexPosition(uint32 vertexIndex) const=0;
/// Return the normal vector of a given face of the polyhedron
virtual Vector3 getFaceNormal(uint faceIndex) const=0;
virtual Vector3 getFaceNormal(uint32 faceIndex) const=0;
/// Return the number of half-edges of the polyhedron
virtual uint getNbHalfEdges() const=0;
virtual uint32 getNbHalfEdges() const=0;
/// Return a given half-edge of the polyhedron
virtual const HalfEdgeStructure::Edge& getHalfEdge(uint edgeIndex) const=0;
virtual const HalfEdgeStructure::Edge& getHalfEdge(uint32 edgeIndex) const=0;
/// Return true if the collision shape is a polyhedron
virtual bool isPolyhedron() const override;
@ -90,15 +90,38 @@ class ConvexPolyhedronShape : public ConvexShape {
/// Find and return the index of the polyhedron face with the most anti-parallel face
/// normal given a direction vector
uint findMostAntiParallelFace(const Vector3& direction) const;
uint32 findMostAntiParallelFace(const Vector3& direction) const;
};
// Return true if the collision shape is a polyhedron
inline bool ConvexPolyhedronShape::isPolyhedron() const {
RP3D_FORCE_INLINE bool ConvexPolyhedronShape::isPolyhedron() const {
return true;
}
// Find and return the index of the polyhedron face with the most anti-parallel face
// normal given a direction vector. This is used to find the incident face on
// a polyhedron of a given reference face of another polyhedron
RP3D_FORCE_INLINE uint32 ConvexPolyhedronShape::findMostAntiParallelFace(const Vector3& direction) const {
decimal minDotProduct = DECIMAL_LARGEST;
uint32 mostAntiParallelFace = 0;
// For each face of the polyhedron
const uint32 nbFaces = getNbFaces();
for (uint32 i=0; i < nbFaces; i++) {
// Get the face normal
const decimal dotProduct = getFaceNormal(i).dot(direction);
if (dotProduct < minDotProduct) {
minDotProduct = dotProduct;
mostAntiParallelFace = i;
}
}
return mostAntiParallelFace;
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -83,7 +83,7 @@ class ConvexShape : public CollisionShape {
};
// Return true if the collision shape is convex, false if it is concave
inline bool ConvexShape::isConvex() const {
RP3D_FORCE_INLINE bool ConvexShape::isConvex() const {
return true;
}
@ -91,7 +91,7 @@ inline bool ConvexShape::isConvex() const {
/**
* @return The margin (in meters) around the collision shape
*/
inline decimal ConvexShape::getMargin() const {
RP3D_FORCE_INLINE decimal ConvexShape::getMargin() const {
return mMargin;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -91,37 +91,41 @@ class HeightFieldShape : public ConcaveShape {
/// Local AABB of the height field (without scaling)
AABB mAABB;
/// Reference to the half-edge structure
HalfEdgeStructure& mTriangleHalfEdgeStructure;
// -------------------- Methods -------------------- //
/// Constructor
HeightFieldShape(int nbGridColumns, int nbGridRows, decimal minHeight, decimal maxHeight,
const void* heightFieldData, HeightDataType dataType, MemoryAllocator& allocator,
int upAxis = 1, decimal integerHeightScale = 1.0f,
HalfEdgeStructure& triangleHalfEdgeStructure, int upAxis = 1, decimal integerHeightScale = 1.0f,
const Vector3& scaling = Vector3(1,1,1));
/// Raycast a single triangle of the height-field
bool raycastTriangle(const Ray& ray, const Vector3& p1, const Vector3& p2, const Vector3& p3, uint32 shapeId,
Collider *collider, RaycastInfo& raycastInfo, decimal &smallestHitFraction, MemoryAllocator& allocator) const;
/// Raycast method with feedback information
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, Collider* collider, MemoryAllocator& allocator) const override;
/// Return the number of bytes used by the collision shape
virtual size_t getSizeInBytes() const override;
/// Insert all the triangles into the dynamic AABB tree
void initBVHTree();
/// Return the three vertices coordinates (in the array outTriangleVertices) of a triangle
/// given the start vertex index pointer of the triangle.
void getTriangleVerticesWithIndexPointer(int32 subPart, int32 triangleIndex,
Vector3* outTriangleVertices) const;
/// Return the closest inside integer grid value of a given floating grid value
int computeIntegerGridValue(decimal value) const;
/// Compute the min/max grid coords corresponding to the intersection of the AABB of the height field and the AABB to collide
void computeMinMaxGridCoordinates(int* minCoords, int* maxCoords, const AABB& aabbToCollide) const;
/// Compute the shape Id for a given triangle
uint computeTriangleShapeId(uint iIndex, uint jIndex, uint secondTriangleIncrement) const;
uint32 computeTriangleShapeId(uint32 iIndex, uint32 jIndex, uint32 secondTriangleIncrement) const;
/// Compute the first grid cell of the heightfield intersected by a ray
bool computeEnteringRayGridCoordinates(const Ray& ray, int& i, int& j, Vector3& outHitPoint) const;
/// Destructor
virtual ~HeightFieldShape() override = default;
@ -152,8 +156,8 @@ class HeightFieldShape : public ConcaveShape {
virtual void getLocalBounds(Vector3& min, Vector3& max) const override;
/// Use a callback method on all triangles of the concave shape inside a given AABB
virtual void computeOverlappingTriangles(const AABB& localAABB, List<Vector3>& triangleVertices,
List<Vector3>& triangleVerticesNormals, List<uint>& shapeIds,
virtual void computeOverlappingTriangles(const AABB& localAABB, Array<Vector3>& triangleVertices,
Array<Vector3>& triangleVerticesNormals, Array<uint32>& shapeIds,
MemoryAllocator& allocator) const override;
/// Return the string representation of the shape
@ -167,46 +171,41 @@ class HeightFieldShape : public ConcaveShape {
};
// Return the number of rows in the height field
inline int HeightFieldShape::getNbRows() const {
RP3D_FORCE_INLINE int HeightFieldShape::getNbRows() const {
return mNbRows;
}
// Return the number of columns in the height field
inline int HeightFieldShape::getNbColumns() const {
RP3D_FORCE_INLINE int HeightFieldShape::getNbColumns() const {
return mNbColumns;
}
// Return the type of height value in the height field
inline HeightFieldShape::HeightDataType HeightFieldShape::getHeightDataType() const {
RP3D_FORCE_INLINE HeightFieldShape::HeightDataType HeightFieldShape::getHeightDataType() const {
return mHeightDataType;
}
// Return the number of bytes used by the collision shape
inline size_t HeightFieldShape::getSizeInBytes() const {
RP3D_FORCE_INLINE size_t HeightFieldShape::getSizeInBytes() const {
return sizeof(HeightFieldShape);
}
// Return the height of a given (x,y) point in the height field
inline decimal HeightFieldShape::getHeightAt(int x, int y) const {
RP3D_FORCE_INLINE decimal HeightFieldShape::getHeightAt(int x, int y) const {
assert(x >= 0 && x < mNbColumns);
assert(y >= 0 && y < mNbRows);
switch(mHeightDataType) {
case HeightDataType::HEIGHT_FLOAT_TYPE : return ((float*)mHeightFieldData)[y * mNbColumns + x];
case HeightDataType::HEIGHT_DOUBLE_TYPE : return ((double*)mHeightFieldData)[y * mNbColumns + x];
case HeightDataType::HEIGHT_INT_TYPE : return ((int*)mHeightFieldData)[y * mNbColumns + x] * mIntegerHeightScale;
case HeightDataType::HEIGHT_FLOAT_TYPE : return decimal(((float*)mHeightFieldData)[y * mNbColumns + x]);
case HeightDataType::HEIGHT_DOUBLE_TYPE : return decimal(((double*)mHeightFieldData)[y * mNbColumns + x]);
case HeightDataType::HEIGHT_INT_TYPE : return decimal(((int*)mHeightFieldData)[y * mNbColumns + x] * mIntegerHeightScale);
default: assert(false); return 0;
}
}
// Return the closest inside integer grid value of a given floating grid value
inline int HeightFieldShape::computeIntegerGridValue(decimal value) const {
return (value < decimal(0.0)) ? value - decimal(0.5) : value + decimal(0.5);
}
// Compute the shape Id for a given triangle
inline uint HeightFieldShape::computeTriangleShapeId(uint iIndex, uint jIndex, uint secondTriangleIncrement) const {
RP3D_FORCE_INLINE uint32 HeightFieldShape::computeTriangleShapeId(uint32 iIndex, uint32 jIndex, uint32 secondTriangleIncrement) const {
return (jIndex * (mNbColumns - 1) + iIndex) * 2 + secondTriangleIncrement;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -111,7 +111,7 @@ class SphereShape : public ConvexShape {
/**
* @return Radius of the sphere
*/
inline decimal SphereShape::getRadius() const {
RP3D_FORCE_INLINE decimal SphereShape::getRadius() const {
return mMargin;
}
@ -121,7 +121,7 @@ inline decimal SphereShape::getRadius() const {
/**
* @param radius Radius of the sphere
*/
inline void SphereShape::setRadius(decimal radius) {
RP3D_FORCE_INLINE void SphereShape::setRadius(decimal radius) {
assert(radius > decimal(0.0));
mMargin = radius;
@ -132,7 +132,7 @@ inline void SphereShape::setRadius(decimal radius) {
/**
* @return False because the sphere shape is not a polyhedron
*/
inline bool SphereShape::isPolyhedron() const {
RP3D_FORCE_INLINE bool SphereShape::isPolyhedron() const {
return false;
}
@ -140,12 +140,12 @@ inline bool SphereShape::isPolyhedron() const {
/**
* @return The size (in bytes) of the sphere shape
*/
inline size_t SphereShape::getSizeInBytes() const {
RP3D_FORCE_INLINE size_t SphereShape::getSizeInBytes() const {
return sizeof(SphereShape);
}
// Return a local support point in a given direction without the object margin
inline Vector3 SphereShape::getLocalSupportPointWithoutMargin(const Vector3& direction) const {
RP3D_FORCE_INLINE Vector3 SphereShape::getLocalSupportPointWithoutMargin(const Vector3& /*direction*/) const {
// Return the center of the sphere (the radius is taken into account in the object margin)
return Vector3(0.0, 0.0, 0.0);
@ -157,7 +157,7 @@ inline Vector3 SphereShape::getLocalSupportPointWithoutMargin(const Vector3& dir
* @param min The minimum bounds of the shape in local-space coordinates
* @param max The maximum bounds of the shape in local-space coordinates
*/
inline void SphereShape::getLocalBounds(Vector3& min, Vector3& max) const {
RP3D_FORCE_INLINE void SphereShape::getLocalBounds(Vector3& min, Vector3& max) const {
// Maximum bounds
max.x = mMargin;
@ -174,23 +174,23 @@ inline void SphereShape::getLocalBounds(Vector3& min, Vector3& max) const {
/**
* @param mass Mass to use to compute the inertia tensor of the collision shape
*/
inline Vector3 SphereShape::getLocalInertiaTensor(decimal mass) const {
RP3D_FORCE_INLINE Vector3 SphereShape::getLocalInertiaTensor(decimal mass) const {
decimal diag = decimal(0.4) * mass * mMargin * mMargin;
return Vector3(diag, diag, diag);
}
// Compute and return the volume of the collision shape
inline decimal SphereShape::getVolume() const {
return decimal(4.0) / decimal(3.0) * reactphysics3d::PI * mMargin * mMargin * mMargin;
RP3D_FORCE_INLINE decimal SphereShape::getVolume() const {
return decimal(4.0) / decimal(3.0) * reactphysics3d::PI_RP3D * mMargin * mMargin * mMargin;
}
// Return true if a point is inside the collision shape
inline bool SphereShape::testPointInside(const Vector3& localPoint, Collider* collider) const {
RP3D_FORCE_INLINE bool SphereShape::testPointInside(const Vector3& localPoint, Collider* /*collider*/) const {
return (localPoint.lengthSquare() < mMargin * mMargin);
}
// Return the string representation of the shape
inline std::string SphereShape::to_string() const {
RP3D_FORCE_INLINE std::string SphereShape::to_string() const {
return "SphereShape{radius=" + std::to_string(getRadius()) + "}";
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -33,6 +33,9 @@
/// ReactPhysics3D namespace
namespace reactphysics3d {
// Forward declarations
class PhysicsCommon;
/// Raycast test side for the triangle
enum class TriangleRaycastSide {
@ -73,11 +76,8 @@ class TriangleShape : public ConvexPolyhedronShape {
/// Raycast test type for the triangle (front, back, front-back)
TriangleRaycastSide mRaycastTestType;
/// Faces information for the two faces of the triangle
HalfEdgeStructure::Face mFaces[2];
/// Edges information for the six edges of the triangle
HalfEdgeStructure::Edge mEdges[6];
/// Reference to triangle half-edge structure
HalfEdgeStructure& mTriangleHalfEdgeStructure;
// -------------------- Methods -------------------- //
@ -91,8 +91,7 @@ class TriangleShape : public ConvexPolyhedronShape {
virtual bool testPointInside(const Vector3& localPoint, Collider* collider) const override;
/// Raycast method with feedback information
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, Collider* collider,
MemoryAllocator& allocator) const override;
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, Collider* collider, MemoryAllocator& allocator) const override;
/// Return the number of bytes used by the collision shape
virtual size_t getSizeInBytes() const override;
@ -108,8 +107,11 @@ class TriangleShape : public ConvexPolyhedronShape {
Vector3& outNewLocalContactPointOtherShape, Vector3& outSmoothWorldContactTriangleNormal) const;
/// Constructor
TriangleShape(const Vector3* vertices, const Vector3* verticesNormals,
uint shapeId, MemoryAllocator& allocator);
TriangleShape(const Vector3* vertices, const Vector3* verticesNormals, uint32 shapeId, HalfEdgeStructure& triangleHalfEdgeStructure,
MemoryAllocator& allocator);
/// Constructor
TriangleShape(const Vector3* vertices, uint32 shapeId, HalfEdgeStructure& triangleHalfEdgeStructure, MemoryAllocator& allocator);
/// Destructor
virtual ~TriangleShape() override = default;
@ -140,28 +142,28 @@ class TriangleShape : public ConvexPolyhedronShape {
void setRaycastTestType(TriangleRaycastSide testType);
/// Return the number of faces of the polyhedron
virtual uint getNbFaces() const override;
virtual uint32 getNbFaces() const override;
/// Return a given face of the polyhedron
virtual const HalfEdgeStructure::Face& getFace(uint faceIndex) const override;
virtual const HalfEdgeStructure::Face& getFace(uint32 faceIndex) const override;
/// Return the number of vertices of the polyhedron
virtual uint getNbVertices() const override;
virtual uint32 getNbVertices() const override;
/// Return a given vertex of the polyhedron
virtual HalfEdgeStructure::Vertex getVertex(uint vertexIndex) const override;
virtual const HalfEdgeStructure::Vertex& getVertex(uint32 vertexIndex) const override;
/// Return the position of a given vertex
virtual Vector3 getVertexPosition(uint vertexIndex) const override;
virtual Vector3 getVertexPosition(uint32 vertexIndex) const override;
/// Return the normal vector of a given face of the polyhedron
virtual Vector3 getFaceNormal(uint faceIndex) const override;
virtual Vector3 getFaceNormal(uint32 faceIndex) const override;
/// Return the number of half-edges of the polyhedron
virtual uint getNbHalfEdges() const override;
virtual uint32 getNbHalfEdges() const override;
/// Return a given half-edge of the polyhedron
virtual const HalfEdgeStructure::Edge& getHalfEdge(uint edgeIndex) const override;
virtual const HalfEdgeStructure::Edge& getHalfEdge(uint32 edgeIndex) const override;
/// Return the centroid of the polyhedron
virtual Vector3 getCentroid() const override;
@ -188,12 +190,12 @@ class TriangleShape : public ConvexPolyhedronShape {
};
// Return the number of bytes used by the collision shape
inline size_t TriangleShape::getSizeInBytes() const {
RP3D_FORCE_INLINE size_t TriangleShape::getSizeInBytes() const {
return sizeof(TriangleShape);
}
// Return a local support point in a given direction without the object margin
inline Vector3 TriangleShape::getLocalSupportPointWithoutMargin(const Vector3& direction) const {
RP3D_FORCE_INLINE Vector3 TriangleShape::getLocalSupportPointWithoutMargin(const Vector3& direction) const {
Vector3 dotProducts(direction.dot(mPoints[0]), direction.dot(mPoints[1]), direction.dot(mPoints[2]));
return mPoints[dotProducts.getMaxAxis()];
}
@ -204,7 +206,7 @@ inline Vector3 TriangleShape::getLocalSupportPointWithoutMargin(const Vector3& d
* @param min The minimum bounds of the shape in local-space coordinates
* @param max The maximum bounds of the shape in local-space coordinates
*/
inline void TriangleShape::getLocalBounds(Vector3& min, Vector3& max) const {
RP3D_FORCE_INLINE void TriangleShape::getLocalBounds(Vector3& min, Vector3& max) const {
const Vector3 xAxis(mPoints[0].x, mPoints[1].x, mPoints[2].x);
const Vector3 yAxis(mPoints[0].y, mPoints[1].y, mPoints[2].y);
@ -222,74 +224,56 @@ inline void TriangleShape::getLocalBounds(Vector3& min, Vector3& max) const {
* coordinates
* @param mass Mass to use to compute the inertia tensor of the collision shape
*/
inline Vector3 TriangleShape::getLocalInertiaTensor(decimal mass) const {
RP3D_FORCE_INLINE Vector3 TriangleShape::getLocalInertiaTensor(decimal /*mass*/) const {
return Vector3(0, 0, 0);
}
// Return true if a point is inside the collision shape
inline bool TriangleShape::testPointInside(const Vector3& localPoint, Collider* collider) const {
RP3D_FORCE_INLINE bool TriangleShape::testPointInside(const Vector3& /*localPoint*/, Collider* /*collider*/) const {
return false;
}
// Return the number of faces of the polyhedron
inline uint TriangleShape::getNbFaces() const {
RP3D_FORCE_INLINE uint32 TriangleShape::getNbFaces() const {
return 2;
}
// Return a given face of the polyhedron
inline const HalfEdgeStructure::Face& TriangleShape::getFace(uint faceIndex) const {
assert(faceIndex < 2);
return mFaces[faceIndex];
}
// Return the number of vertices of the polyhedron
inline uint TriangleShape::getNbVertices() const {
RP3D_FORCE_INLINE uint32 TriangleShape::getNbVertices() const {
return 3;
}
// Return a given vertex of the polyhedron
inline HalfEdgeStructure::Vertex TriangleShape::getVertex(uint vertexIndex) const {
RP3D_FORCE_INLINE const HalfEdgeStructure::Vertex& TriangleShape::getVertex(uint32 vertexIndex) const {
assert(vertexIndex < 3);
HalfEdgeStructure::Vertex vertex(vertexIndex);
switch (vertexIndex) {
case 0: vertex.edgeIndex = 0; break;
case 1: vertex.edgeIndex = 2; break;
case 2: vertex.edgeIndex = 4; break;
}
return vertex;
}
// Return a given half-edge of the polyhedron
inline const HalfEdgeStructure::Edge& TriangleShape::getHalfEdge(uint edgeIndex) const {
assert(edgeIndex < getNbHalfEdges());
return mEdges[edgeIndex];
return mTriangleHalfEdgeStructure.getVertex(vertexIndex);
}
// Return the position of a given vertex
inline Vector3 TriangleShape::getVertexPosition(uint vertexIndex) const {
RP3D_FORCE_INLINE Vector3 TriangleShape::getVertexPosition(uint32 vertexIndex) const {
assert(vertexIndex < 3);
return mPoints[vertexIndex];
}
// Return the normal vector of a given face of the polyhedron
inline Vector3 TriangleShape::getFaceNormal(uint faceIndex) const {
RP3D_FORCE_INLINE Vector3 TriangleShape::getFaceNormal(uint32 faceIndex) const {
assert(faceIndex < 2);
assert(mNormal.length() > decimal(0.0));
return faceIndex == 0 ? mNormal : -mNormal;
}
// Return the centroid of the box
inline Vector3 TriangleShape::getCentroid() const {
RP3D_FORCE_INLINE Vector3 TriangleShape::getCentroid() const {
return (mPoints[0] + mPoints[1] + mPoints[2]) / decimal(3.0);
}
// Return the number of half-edges of the polyhedron
inline uint TriangleShape::getNbHalfEdges() const {
RP3D_FORCE_INLINE uint32 TriangleShape::getNbHalfEdges() const {
return 6;
}
// Return the raycast test type (front, back, front-back)
inline TriangleRaycastSide TriangleShape::getRaycastTestType() const {
RP3D_FORCE_INLINE TriangleRaycastSide TriangleShape::getRaycastTestType() const {
return mRaycastTestType;
}
@ -297,21 +281,100 @@ inline TriangleRaycastSide TriangleShape::getRaycastTestType() const {
/**
* @param testType Raycast test type for the triangle (front, back, front-back)
*/
inline void TriangleShape::setRaycastTestType(TriangleRaycastSide testType) {
RP3D_FORCE_INLINE void TriangleShape::setRaycastTestType(TriangleRaycastSide testType) {
mRaycastTestType = testType;
}
// Return the string representation of the shape
inline std::string TriangleShape::to_string() const {
RP3D_FORCE_INLINE std::string TriangleShape::to_string() const {
return "TriangleShape{v1=" + mPoints[0].to_string() + ", v2=" + mPoints[1].to_string() + "," +
"v3=" + mPoints[2].to_string() + "}";
}
// Compute and return the volume of the collision shape
inline decimal TriangleShape::getVolume() const {
RP3D_FORCE_INLINE decimal TriangleShape::getVolume() const {
return decimal(0.0);
}
// Get a smooth contact normal for collision for a triangle of the mesh
/// This is used to avoid the internal edges issue that occurs when a shape is colliding with
/// several triangles of a concave mesh. If the shape collide with an edge of the triangle for instance,
/// the computed contact normal from this triangle edge is not necessarily in the direction of the surface
/// normal of the mesh at this point. The idea to solve this problem is to use the real (smooth) surface
/// normal of the mesh at this point as the contact normal. This technique is described in the chapter 5
/// of the Game Physics Pearl book by Gino van der Bergen and Dirk Gregorius. The vertices normals of the
/// mesh are either provided by the user or precomputed if the user did not provide them. Note that we only
/// use the interpolated normal if the contact point is on an edge of the triangle. If the contact is in the
/// middle of the triangle, we return the true triangle normal.
RP3D_FORCE_INLINE Vector3 TriangleShape::computeSmoothLocalContactNormalForTriangle(const Vector3& localContactPoint) const {
assert(mNormal.length() > decimal(0.0));
// Compute the barycentric coordinates of the point in the triangle
decimal u, v, w;
computeBarycentricCoordinatesInTriangle(mPoints[0], mPoints[1], mPoints[2], localContactPoint, u, v, w);
// If the contact is in the middle of the triangle face (not on the edges)
if (u > MACHINE_EPSILON && v > MACHINE_EPSILON && w > MACHINE_EPSILON) {
// We return the true triangle face normal (not the interpolated one)
return mNormal;
}
// We compute the contact normal as the barycentric interpolation of the three vertices normals
const Vector3 interpolatedNormal = u * mVerticesNormals[0] + v * mVerticesNormals[1] + w * mVerticesNormals[2];
// If the interpolated normal is degenerated
if (interpolatedNormal.lengthSquare() < MACHINE_EPSILON) {
// Return the original normal
return mNormal;
}
return interpolatedNormal.getUnit();
}
// This method compute the smooth mesh contact with a triangle in case one of the two collision
// shapes is a triangle. The idea in this case is to use a smooth vertex normal of the triangle mesh
// at the contact point instead of the triangle normal to avoid the internal edge collision issue.
// This method will return the new smooth world contact
// normal of the triangle and the the local contact point on the other shape.
RP3D_FORCE_INLINE void TriangleShape::computeSmoothTriangleMeshContact(const CollisionShape* shape1, const CollisionShape* shape2,
Vector3& localContactPointShape1, Vector3& localContactPointShape2,
const Transform& shape1ToWorld, const Transform& shape2ToWorld,
decimal penetrationDepth, Vector3& outSmoothVertexNormal) {
assert(shape1->getName() != CollisionShapeName::TRIANGLE || shape2->getName() != CollisionShapeName::TRIANGLE);
// If one the shape is a triangle
bool isShape1Triangle = shape1->getName() == CollisionShapeName::TRIANGLE;
if (isShape1Triangle || shape2->getName() == CollisionShapeName::TRIANGLE) {
const TriangleShape* triangleShape = isShape1Triangle ? static_cast<const TriangleShape*>(shape1):
static_cast<const TriangleShape*>(shape2);
// Compute the smooth triangle mesh contact normal and recompute the local contact point on the other shape
triangleShape->computeSmoothMeshContact(isShape1Triangle ? localContactPointShape1 : localContactPointShape2,
isShape1Triangle ? shape1ToWorld : shape2ToWorld,
isShape1Triangle ? shape2ToWorld.getInverse() : shape1ToWorld.getInverse(),
penetrationDepth, isShape1Triangle,
isShape1Triangle ? localContactPointShape2 : localContactPointShape1,
outSmoothVertexNormal);
}
}
// Return a given face of the polyhedron
RP3D_FORCE_INLINE const HalfEdgeStructure::Face& TriangleShape::getFace(uint32 faceIndex) const {
assert(faceIndex < 2);
return mTriangleHalfEdgeStructure.getFace(faceIndex);
}
// Return a given half-edge of the polyhedron
RP3D_FORCE_INLINE const HalfEdgeStructure::Edge& TriangleShape::getHalfEdge(uint32 edgeIndex) const {
assert(edgeIndex < getNbHalfEdges());
return mTriangleHalfEdgeStructure.getHalfEdge(edgeIndex);
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -85,6 +85,27 @@ class BallAndSocketJointComponents : public Components {
/// Accumulated impulse
Vector3* mImpulse;
/// True if the joint cone limit is enabled
bool* mIsConeLimitEnabled;
/// Cone limit impulse
decimal* mConeLimitImpulse;
/// Cone limit half angle
decimal* mConeLimitHalfAngle;
/// Inverse of mass matrix K=JM^-1J^t for the cone limit
decimal* mInverseMassMatrixConeLimit;
/// Bias of the cone limit constraint
decimal* mBConeLimit;
/// True if the cone limit is violated
bool* mIsConeLimitViolated;
/// Cross product of cone limit axis of both bodies
Vector3* mConeLimitACrossB;
// -------------------- Methods -------------------- //
/// Allocate memory for a given number of components
@ -104,8 +125,12 @@ class BallAndSocketJointComponents : public Components {
/// Structure for the data of a transform component
struct BallAndSocketJointComponent {
bool isConeLimitEnabled;
decimal coneLimitHalfAngle;
/// Constructor
BallAndSocketJointComponent() {
BallAndSocketJointComponent(bool isConeLimitEnabled, decimal coneLimitHalfAngle)
: isConeLimitEnabled(isConeLimitEnabled), coneLimitHalfAngle(coneLimitHalfAngle) {
}
};
@ -181,6 +206,42 @@ class BallAndSocketJointComponents : public Components {
/// Set the accumulated impulse
void setImpulse(Entity jointEntity, const Vector3& impulse);
/// Return true if the cone limit is enabled
bool getIsConeLimitEnabled(Entity jointEntity) const;
/// Set to true if the cone limit is enabled
void setIsConeLimitEnabled(Entity jointEntity, bool isLimitEnabled);
/// Return the cone limit impulse
bool getConeLimitImpulse(Entity jointEntity) const;
/// Set the cone limit impulse
void setConeLimitImpulse(Entity jointEntity, decimal impulse);
/// Return the cone limit half angle
decimal getConeLimitHalfAngle(Entity jointEntity) const;
/// Set the cone limit half angle
void setConeLimitHalfAngle(Entity jointEntity, decimal halfAngle);
/// Return the inverse mass matrix cone limit
bool getInverseMassMatrixConeLimit(Entity jointEntity) const;
/// Set the inverse mass matrix cone limit
void setInverseMassMatrixConeLimit(Entity jointEntity, decimal inverseMassMatrix);
/// Get the cone limit local axis of body 1
Vector3 getConeLimitLocalAxisBody1(Entity jointEntity) const;
/// Set the cone limit local axis of body 1
void setConeLimitLocalAxisBody1(Entity jointEntity, const Vector3& localAxisBody1);
/// Get the cone limit local axis of body 2
Vector3 getConeLimitLocalAxisBody2(Entity jointEntity) const;
/// Set the cone limit local axis of body 2
void setConeLimitLocalAxisBody2(Entity jointEntity, const Vector3& localAxisBody2);
// -------------------- Friendship -------------------- //
friend class BroadPhaseSystem;
@ -188,145 +249,201 @@ class BallAndSocketJointComponents : public Components {
};
// Return a pointer to a given joint
inline BallAndSocketJoint* BallAndSocketJointComponents::getJoint(Entity jointEntity) const {
RP3D_FORCE_INLINE BallAndSocketJoint* BallAndSocketJointComponents::getJoint(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mJoints[mMapEntityToComponentIndex[jointEntity]];
}
// Set the joint pointer to a given joint
inline void BallAndSocketJointComponents::setJoint(Entity jointEntity, BallAndSocketJoint* joint) const {
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setJoint(Entity jointEntity, BallAndSocketJoint* joint) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mJoints[mMapEntityToComponentIndex[jointEntity]] = joint;
}
// Return the local anchor point of body 1 for a given joint
inline const Vector3& BallAndSocketJointComponents::getLocalAnchorPointBody1(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& BallAndSocketJointComponents::getLocalAnchorPointBody1(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mLocalAnchorPointBody1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the local anchor point of body 1 for a given joint
inline void BallAndSocketJointComponents::setLocalAnchorPointBody1(Entity jointEntity, const Vector3& localAnchoirPointBody1) {
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setLocalAnchorPointBody1(Entity jointEntity, const Vector3& localAnchoirPointBody1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mLocalAnchorPointBody1[mMapEntityToComponentIndex[jointEntity]] = localAnchoirPointBody1;
}
// Return the local anchor point of body 2 for a given joint
inline const Vector3& BallAndSocketJointComponents::getLocalAnchorPointBody2(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& BallAndSocketJointComponents::getLocalAnchorPointBody2(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mLocalAnchorPointBody2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the local anchor point of body 2 for a given joint
inline void BallAndSocketJointComponents::setLocalAnchorPointBody2(Entity jointEntity, const Vector3& localAnchoirPointBody2) {
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setLocalAnchorPointBody2(Entity jointEntity, const Vector3& localAnchoirPointBody2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mLocalAnchorPointBody2[mMapEntityToComponentIndex[jointEntity]] = localAnchoirPointBody2;
}
// Return the vector from center of body 1 to anchor point in world-space
inline const Vector3& BallAndSocketJointComponents::getR1World(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& BallAndSocketJointComponents::getR1World(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR1World[mMapEntityToComponentIndex[jointEntity]];
}
// Set the vector from center of body 1 to anchor point in world-space
inline void BallAndSocketJointComponents::setR1World(Entity jointEntity, const Vector3& r1World) {
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setR1World(Entity jointEntity, const Vector3& r1World) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR1World[mMapEntityToComponentIndex[jointEntity]] = r1World;
}
// Return the vector from center of body 2 to anchor point in world-space
inline const Vector3& BallAndSocketJointComponents::getR2World(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& BallAndSocketJointComponents::getR2World(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR2World[mMapEntityToComponentIndex[jointEntity]];
}
// Set the vector from center of body 2 to anchor point in world-space
inline void BallAndSocketJointComponents::setR2World(Entity jointEntity, const Vector3& r2World) {
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setR2World(Entity jointEntity, const Vector3& r2World) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR2World[mMapEntityToComponentIndex[jointEntity]] = r2World;
}
// Return the inertia tensor of body 1 (in world-space coordinates)
inline const Matrix3x3& BallAndSocketJointComponents::getI1(Entity jointEntity) const {
RP3D_FORCE_INLINE const Matrix3x3& BallAndSocketJointComponents::getI1(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mI1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the inertia tensor of body 1 (in world-space coordinates)
inline void BallAndSocketJointComponents::setI1(Entity jointEntity, const Matrix3x3& i1) {
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setI1(Entity jointEntity, const Matrix3x3& i1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mI1[mMapEntityToComponentIndex[jointEntity]] = i1;
}
// Return the inertia tensor of body 2 (in world-space coordinates)
inline const Matrix3x3& BallAndSocketJointComponents::getI2(Entity jointEntity) const {
RP3D_FORCE_INLINE const Matrix3x3& BallAndSocketJointComponents::getI2(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mI2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the inertia tensor of body 2 (in world-space coordinates)
inline void BallAndSocketJointComponents::setI2(Entity jointEntity, const Matrix3x3& i2) {
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setI2(Entity jointEntity, const Matrix3x3& i2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mI2[mMapEntityToComponentIndex[jointEntity]] = i2;
}
// Return the bias vector for the constraint
inline Vector3 &BallAndSocketJointComponents::getBiasVector(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3 &BallAndSocketJointComponents::getBiasVector(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBiasVector[mMapEntityToComponentIndex[jointEntity]];
}
// Set the bias vector for the constraint
inline void BallAndSocketJointComponents::setBiasVector(Entity jointEntity, const Vector3& biasVector) {
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setBiasVector(Entity jointEntity, const Vector3& biasVector) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mBiasVector[mMapEntityToComponentIndex[jointEntity]] = biasVector;
}
// Return the inverse mass matrix K=JM^-1J^-t of the constraint
inline Matrix3x3& BallAndSocketJointComponents::getInverseMassMatrix(Entity jointEntity) {
RP3D_FORCE_INLINE Matrix3x3& BallAndSocketJointComponents::getInverseMassMatrix(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInverseMassMatrix[mMapEntityToComponentIndex[jointEntity]];
}
// Set the inverse mass matrix K=JM^-1J^-t of the constraint
inline void BallAndSocketJointComponents::setInverseMassMatrix(Entity jointEntity, const Matrix3x3& inverseMassMatrix) {
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setInverseMassMatrix(Entity jointEntity, const Matrix3x3& inverseMassMatrix) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInverseMassMatrix[mMapEntityToComponentIndex[jointEntity]] = inverseMassMatrix;
}
// Return the accumulated impulse
inline Vector3 &BallAndSocketJointComponents::getImpulse(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& BallAndSocketJointComponents::getImpulse(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulse[mMapEntityToComponentIndex[jointEntity]];
}
// Set the accumulated impulse
inline void BallAndSocketJointComponents::setImpulse(Entity jointEntity, const Vector3& impulse) {
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setImpulse(Entity jointEntity, const Vector3& impulse) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulse[mMapEntityToComponentIndex[jointEntity]] = impulse;
}
// Return true if the cone limit is enabled
RP3D_FORCE_INLINE bool BallAndSocketJointComponents::getIsConeLimitEnabled(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mIsConeLimitEnabled[mMapEntityToComponentIndex[jointEntity]];
}
// Set to true if the cone limit is enabled
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setIsConeLimitEnabled(Entity jointEntity, bool isLimitEnabled) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mIsConeLimitEnabled[mMapEntityToComponentIndex[jointEntity]] = isLimitEnabled;
}
// Return the cone limit impulse
RP3D_FORCE_INLINE bool BallAndSocketJointComponents::getConeLimitImpulse(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mConeLimitImpulse[mMapEntityToComponentIndex[jointEntity]];
}
// Set the cone limit impulse
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setConeLimitImpulse(Entity jointEntity, decimal impulse) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mConeLimitImpulse[mMapEntityToComponentIndex[jointEntity]] = impulse;
}
// Return the cone limit half angle
RP3D_FORCE_INLINE decimal BallAndSocketJointComponents::getConeLimitHalfAngle(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mConeLimitHalfAngle[mMapEntityToComponentIndex[jointEntity]];
}
// Set the cone limit half angle
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setConeLimitHalfAngle(Entity jointEntity, decimal halfAngle) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mConeLimitHalfAngle[mMapEntityToComponentIndex[jointEntity]] = halfAngle;
}
// Return the inverse mass matrix cone limit
RP3D_FORCE_INLINE bool BallAndSocketJointComponents::getInverseMassMatrixConeLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInverseMassMatrixConeLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the inverse mass matrix cone limit
RP3D_FORCE_INLINE void BallAndSocketJointComponents::setInverseMassMatrixConeLimit(Entity jointEntity, decimal inverseMassMatrix) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInverseMassMatrixConeLimit[mMapEntityToComponentIndex[jointEntity]] = inverseMassMatrix;
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -32,6 +32,7 @@
#include <reactphysics3d/containers/Map.h>
#include <reactphysics3d/collision/shapes/AABB.h>
#include <reactphysics3d/components/Components.h>
#include <reactphysics3d/engine/Material.h>
// ReactPhysics3D namespace
namespace reactphysics3d {
@ -89,8 +90,8 @@ class ColliderComponents : public Components {
/// Array with the local-to-world transforms of the colliders
Transform* mLocalToWorldTransforms;
/// Array with the list of involved overlapping pairs for each collider
List<uint64>* mOverlappingPairs;
/// Array with the involved overlapping pairs for each collider
Array<uint64>* mOverlappingPairs;
/// True if the size of the collision shape associated with the collider
/// has been changed by the user
@ -99,6 +100,9 @@ class ColliderComponents : public Components {
/// True if the collider is a trigger
bool* mIsTrigger;
/// Array with the material of each collider
Material* mMaterials;
// -------------------- Methods -------------------- //
@ -127,14 +131,15 @@ class ColliderComponents : public Components {
unsigned short collisionCategoryBits;
unsigned short collideWithMaskBits;
const Transform& localToWorldTransform;
const Material& material;
/// Constructor
ColliderComponent(Entity bodyEntity, Collider* collider, AABB localBounds, const Transform& localToBodyTransform,
CollisionShape* collisionShape, unsigned short collisionCategoryBits,
unsigned short collideWithMaskBits, const Transform& localToWorldTransform)
unsigned short collideWithMaskBits, const Transform& localToWorldTransform, const Material& material)
:bodyEntity(bodyEntity), collider(collider), localBounds(localBounds), localToBodyTransform(localToBodyTransform),
collisionShape(collisionShape), collisionCategoryBits(collisionCategoryBits), collideWithMaskBits(collideWithMaskBits),
localToWorldTransform(localToWorldTransform) {
localToWorldTransform(localToWorldTransform), material(material) {
}
};
@ -189,8 +194,8 @@ class ColliderComponents : public Components {
/// Set the local-to-world transform of a collider
void setLocalToWorldTransform(Entity colliderEntity, const Transform& transform);
/// Return a reference to the list of overlapping pairs for a given collider
List<uint64>& getOverlappingPairs(Entity colliderEntity);
/// Return a reference to the array of overlapping pairs for a given collider
Array<uint64>& getOverlappingPairs(Entity colliderEntity);
/// Return true if the size of collision shape of the collider has been changed by the user
bool getHasCollisionShapeChangedSize(Entity colliderEntity) const;
@ -204,16 +209,24 @@ class ColliderComponents : public Components {
/// Set whether a collider is a trigger
void setIsTrigger(Entity colliderEntity, bool isTrigger);
/// Return a reference to the material of a collider
Material& getMaterial(Entity colliderEntity);
/// Set the material of a collider
void setMaterial(Entity colliderEntity, const Material& material);
// -------------------- Friendship -------------------- //
friend class BroadPhaseSystem;
friend class CollisionDetectionSystem;
friend class ContactSolverSystem;
friend class DynamicsSystem;
friend class OverlappingPairs;
friend class RigidBody;
};
// Return the body entity of a given collider
inline Entity ColliderComponents::getBody(Entity colliderEntity) const {
RP3D_FORCE_INLINE Entity ColliderComponents::getBody(Entity colliderEntity) const {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -221,7 +234,7 @@ inline Entity ColliderComponents::getBody(Entity colliderEntity) const {
}
// Return a pointer to a given collider
inline Collider *ColliderComponents::getCollider(Entity colliderEntity) const {
RP3D_FORCE_INLINE Collider *ColliderComponents::getCollider(Entity colliderEntity) const {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -229,7 +242,7 @@ inline Collider *ColliderComponents::getCollider(Entity colliderEntity) const {
}
// Return the local-to-body transform of a collider
inline const Transform& ColliderComponents::getLocalToBodyTransform(Entity colliderEntity) const {
RP3D_FORCE_INLINE const Transform& ColliderComponents::getLocalToBodyTransform(Entity colliderEntity) const {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -237,7 +250,7 @@ inline const Transform& ColliderComponents::getLocalToBodyTransform(Entity colli
}
// Set the local-to-body transform of a collider
inline void ColliderComponents::setLocalToBodyTransform(Entity colliderEntity, const Transform& transform) {
RP3D_FORCE_INLINE void ColliderComponents::setLocalToBodyTransform(Entity colliderEntity, const Transform& transform) {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -245,7 +258,7 @@ inline void ColliderComponents::setLocalToBodyTransform(Entity colliderEntity, c
}
// Return a pointer to the collision shape of a collider
inline CollisionShape* ColliderComponents::getCollisionShape(Entity colliderEntity) const {
RP3D_FORCE_INLINE CollisionShape* ColliderComponents::getCollisionShape(Entity colliderEntity) const {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -253,7 +266,7 @@ inline CollisionShape* ColliderComponents::getCollisionShape(Entity colliderEnti
}
// Return the broad-phase id of a given collider
inline int32 ColliderComponents::getBroadPhaseId(Entity colliderEntity) const {
RP3D_FORCE_INLINE int32 ColliderComponents::getBroadPhaseId(Entity colliderEntity) const {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -261,7 +274,7 @@ inline int32 ColliderComponents::getBroadPhaseId(Entity colliderEntity) const {
}
// Set the broad-phase id of a given collider
inline void ColliderComponents::setBroadPhaseId(Entity colliderEntity, int32 broadPhaseId) {
RP3D_FORCE_INLINE void ColliderComponents::setBroadPhaseId(Entity colliderEntity, int32 broadPhaseId) {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -269,7 +282,7 @@ inline void ColliderComponents::setBroadPhaseId(Entity colliderEntity, int32 bro
}
// Return the collision category bits of a given collider
inline unsigned short ColliderComponents::getCollisionCategoryBits(Entity colliderEntity) const {
RP3D_FORCE_INLINE unsigned short ColliderComponents::getCollisionCategoryBits(Entity colliderEntity) const {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -277,7 +290,7 @@ inline unsigned short ColliderComponents::getCollisionCategoryBits(Entity collid
}
// Return the "collide with" mask bits of a given collider
inline unsigned short ColliderComponents::getCollideWithMaskBits(Entity colliderEntity) const {
RP3D_FORCE_INLINE unsigned short ColliderComponents::getCollideWithMaskBits(Entity colliderEntity) const {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -285,7 +298,7 @@ inline unsigned short ColliderComponents::getCollideWithMaskBits(Entity collider
}
// Set the collision category bits of a given collider
inline void ColliderComponents::setCollisionCategoryBits(Entity colliderEntity, unsigned short collisionCategoryBits) {
RP3D_FORCE_INLINE void ColliderComponents::setCollisionCategoryBits(Entity colliderEntity, unsigned short collisionCategoryBits) {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -293,7 +306,7 @@ inline void ColliderComponents::setCollisionCategoryBits(Entity colliderEntity,
}
// Set the "collide with" mask bits of a given collider
inline void ColliderComponents::setCollideWithMaskBits(Entity colliderEntity, unsigned short collideWithMaskBits) {
RP3D_FORCE_INLINE void ColliderComponents::setCollideWithMaskBits(Entity colliderEntity, unsigned short collideWithMaskBits) {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -301,7 +314,7 @@ inline void ColliderComponents::setCollideWithMaskBits(Entity colliderEntity, un
}
// Return the local-to-world transform of a collider
inline const Transform& ColliderComponents::getLocalToWorldTransform(Entity colliderEntity) const {
RP3D_FORCE_INLINE const Transform& ColliderComponents::getLocalToWorldTransform(Entity colliderEntity) const {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -309,15 +322,15 @@ inline const Transform& ColliderComponents::getLocalToWorldTransform(Entity coll
}
// Set the local-to-world transform of a collider
inline void ColliderComponents::setLocalToWorldTransform(Entity colliderEntity, const Transform& transform) {
RP3D_FORCE_INLINE void ColliderComponents::setLocalToWorldTransform(Entity colliderEntity, const Transform& transform) {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
mLocalToWorldTransforms[mMapEntityToComponentIndex[colliderEntity]] = transform;
}
// Return a reference to the list of overlapping pairs for a given collider
inline List<uint64>& ColliderComponents::getOverlappingPairs(Entity colliderEntity) {
// Return a reference to the array of overlapping pairs for a given collider
RP3D_FORCE_INLINE Array<uint64>& ColliderComponents::getOverlappingPairs(Entity colliderEntity) {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -325,7 +338,7 @@ inline List<uint64>& ColliderComponents::getOverlappingPairs(Entity colliderEnti
}
// Return true if the size of collision shape of the collider has been changed by the user
inline bool ColliderComponents::getHasCollisionShapeChangedSize(Entity colliderEntity) const {
RP3D_FORCE_INLINE bool ColliderComponents::getHasCollisionShapeChangedSize(Entity colliderEntity) const {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -333,7 +346,7 @@ inline bool ColliderComponents::getHasCollisionShapeChangedSize(Entity colliderE
}
// Return true if the size of collision shape of the collider has been changed by the user
inline void ColliderComponents::setHasCollisionShapeChangedSize(Entity colliderEntity, bool hasCollisionShapeChangedSize) {
RP3D_FORCE_INLINE void ColliderComponents::setHasCollisionShapeChangedSize(Entity colliderEntity, bool hasCollisionShapeChangedSize) {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -342,7 +355,7 @@ inline void ColliderComponents::setHasCollisionShapeChangedSize(Entity colliderE
// Return true if a collider is a trigger
inline bool ColliderComponents::getIsTrigger(Entity colliderEntity) const {
RP3D_FORCE_INLINE bool ColliderComponents::getIsTrigger(Entity colliderEntity) const {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
@ -350,13 +363,29 @@ inline bool ColliderComponents::getIsTrigger(Entity colliderEntity) const {
}
// Set whether a collider is a trigger
inline void ColliderComponents::setIsTrigger(Entity colliderEntity, bool isTrigger) {
RP3D_FORCE_INLINE void ColliderComponents::setIsTrigger(Entity colliderEntity, bool isTrigger) {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
mIsTrigger[mMapEntityToComponentIndex[colliderEntity]] = isTrigger;
}
// Return a reference to the material of a collider
RP3D_FORCE_INLINE Material& ColliderComponents::getMaterial(Entity colliderEntity) {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
return mMaterials[mMapEntityToComponentIndex[colliderEntity]];
}
// Set the material of a collider
RP3D_FORCE_INLINE void ColliderComponents::setMaterial(Entity colliderEntity, const Material& material) {
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
mMaterials[mMapEntityToComponentIndex[colliderEntity]] = material;
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -57,8 +57,8 @@ class CollisionBodyComponents : public Components {
/// Array of pointers to the corresponding bodies
CollisionBody** mBodies;
/// Array with the list of colliders of each body
List<Entity>* mColliders;
/// Array with the colliders of each body
Array<Entity>* mColliders;
/// Array of boolean values to know if the body is active.
bool* mIsActive;
@ -113,8 +113,8 @@ class CollisionBodyComponents : public Components {
/// Return a pointer to a body
CollisionBody* getBody(Entity bodyEntity);
/// Return the list of colliders of a body
const List<Entity>& getColliders(Entity bodyEntity) const;
/// Return the array of colliders of a body
const Array<Entity>& getColliders(Entity bodyEntity) const;
/// Return true if the body is active
bool getIsActive(Entity bodyEntity) const;
@ -130,7 +130,7 @@ class CollisionBodyComponents : public Components {
};
// Add a collider to a body component
inline void CollisionBodyComponents::addColliderToBody(Entity bodyEntity, Entity colliderEntity) {
RP3D_FORCE_INLINE void CollisionBodyComponents::addColliderToBody(Entity bodyEntity, Entity colliderEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -138,7 +138,7 @@ inline void CollisionBodyComponents::addColliderToBody(Entity bodyEntity, Entity
}
// Remove a collider from a body component
inline void CollisionBodyComponents::removeColliderFromBody(Entity bodyEntity, Entity colliderEntity) {
RP3D_FORCE_INLINE void CollisionBodyComponents::removeColliderFromBody(Entity bodyEntity, Entity colliderEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -146,15 +146,15 @@ inline void CollisionBodyComponents::removeColliderFromBody(Entity bodyEntity, E
}
// Return a pointer to a body
inline CollisionBody *CollisionBodyComponents::getBody(Entity bodyEntity) {
RP3D_FORCE_INLINE CollisionBody *CollisionBodyComponents::getBody(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
return mBodies[mMapEntityToComponentIndex[bodyEntity]];
}
// Return the list of colliders of a body
inline const List<Entity>& CollisionBodyComponents::getColliders(Entity bodyEntity) const {
// Return the array of colliders of a body
RP3D_FORCE_INLINE const Array<Entity>& CollisionBodyComponents::getColliders(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -162,7 +162,7 @@ inline const List<Entity>& CollisionBodyComponents::getColliders(Entity bodyEnti
}
// Return true if the body is active
inline bool CollisionBodyComponents::getIsActive(Entity bodyEntity) const {
RP3D_FORCE_INLINE bool CollisionBodyComponents::getIsActive(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -170,7 +170,7 @@ inline bool CollisionBodyComponents::getIsActive(Entity bodyEntity) const {
}
// Set the value to know if the body is active
inline void CollisionBodyComponents::setIsActive(Entity bodyEntity, bool isActive) const {
RP3D_FORCE_INLINE void CollisionBodyComponents::setIsActive(Entity bodyEntity, bool isActive) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -178,7 +178,7 @@ inline void CollisionBodyComponents::setIsActive(Entity bodyEntity, bool isActiv
}
// Return the user data associated with the body
inline void* CollisionBodyComponents::getUserData(Entity bodyEntity) const {
RP3D_FORCE_INLINE void* CollisionBodyComponents::getUserData(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -186,7 +186,7 @@ inline void* CollisionBodyComponents::getUserData(Entity bodyEntity) const {
}
// Set the user data associated with the body
inline void CollisionBodyComponents::setUserData(Entity bodyEntity, void* userData) const {
RP3D_FORCE_INLINE void CollisionBodyComponents::setUserData(Entity bodyEntity, void* userData) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -113,6 +113,9 @@ class Components {
/// Return true if there is a component for a given entity
bool hasComponent(Entity entity) const;
/// Return true if there is a component for a given entiy and if so set the entity index
bool hasComponentGetIndex(Entity entity, uint32& entityIndex) const;
/// Return the number of components
uint32 getNbComponents() const;
@ -124,28 +127,41 @@ class Components {
};
// Return true if an entity is sleeping
inline bool Components::getIsEntityDisabled(Entity entity) const {
RP3D_FORCE_INLINE bool Components::getIsEntityDisabled(Entity entity) const {
assert(hasComponent(entity));
return mMapEntityToComponentIndex[entity] >= mDisabledStartIndex;
}
// Return true if there is a component for a given entity
inline bool Components::hasComponent(Entity entity) const {
RP3D_FORCE_INLINE bool Components::hasComponent(Entity entity) const {
return mMapEntityToComponentIndex.containsKey(entity);
}
// Return true if there is a component for a given entiy and if so set the entity index
RP3D_FORCE_INLINE bool Components::hasComponentGetIndex(Entity entity, uint32& entityIndex) const {
auto it = mMapEntityToComponentIndex.find(entity);
if (it != mMapEntityToComponentIndex.end()) {
entityIndex = it->second;
return true;
}
return false;
}
// Return the number of components
inline uint32 Components::getNbComponents() const {
RP3D_FORCE_INLINE uint32 Components::getNbComponents() const {
return mNbComponents;
}
// Return the number of enabled components
inline uint32 Components::getNbEnabledComponents() const {
RP3D_FORCE_INLINE uint32 Components::getNbEnabledComponents() const {
return mDisabledStartIndex;
}
// Return the index in the arrays for a given entity
inline uint32 Components::getEntityIndex(Entity entity) const {
RP3D_FORCE_INLINE uint32 Components::getEntityIndex(Entity entity) const {
assert(hasComponent(entity));
return mMapEntityToComponentIndex[entity];
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -224,133 +224,133 @@ class FixedJointComponents : public Components {
};
// Return a pointer to a given joint
inline FixedJoint* FixedJointComponents::getJoint(Entity jointEntity) const {
RP3D_FORCE_INLINE FixedJoint* FixedJointComponents::getJoint(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mJoints[mMapEntityToComponentIndex[jointEntity]];
}
// Set the joint pointer to a given joint
inline void FixedJointComponents::setJoint(Entity jointEntity, FixedJoint* joint) const {
RP3D_FORCE_INLINE void FixedJointComponents::setJoint(Entity jointEntity, FixedJoint* joint) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mJoints[mMapEntityToComponentIndex[jointEntity]] = joint;
}
// Return the local anchor point of body 1 for a given joint
inline const Vector3& FixedJointComponents::getLocalAnchorPointBody1(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& FixedJointComponents::getLocalAnchorPointBody1(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mLocalAnchorPointBody1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the local anchor point of body 1 for a given joint
inline void FixedJointComponents::setLocalAnchorPointBody1(Entity jointEntity, const Vector3& localAnchorPointBody1) {
RP3D_FORCE_INLINE void FixedJointComponents::setLocalAnchorPointBody1(Entity jointEntity, const Vector3& localAnchorPointBody1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mLocalAnchorPointBody1[mMapEntityToComponentIndex[jointEntity]] = localAnchorPointBody1;
}
// Return the local anchor point of body 2 for a given joint
inline const Vector3& FixedJointComponents::getLocalAnchorPointBody2(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& FixedJointComponents::getLocalAnchorPointBody2(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mLocalAnchorPointBody2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the local anchor point of body 2 for a given joint
inline void FixedJointComponents::setLocalAnchorPointBody2(Entity jointEntity, const Vector3& localAnchorPointBody2) {
RP3D_FORCE_INLINE void FixedJointComponents::setLocalAnchorPointBody2(Entity jointEntity, const Vector3& localAnchorPointBody2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mLocalAnchorPointBody2[mMapEntityToComponentIndex[jointEntity]] = localAnchorPointBody2;
}
// Return the vector from center of body 1 to anchor point in world-space
inline const Vector3& FixedJointComponents::getR1World(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& FixedJointComponents::getR1World(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR1World[mMapEntityToComponentIndex[jointEntity]];
}
// Set the vector from center of body 1 to anchor point in world-space
inline void FixedJointComponents::setR1World(Entity jointEntity, const Vector3& r1World) {
RP3D_FORCE_INLINE void FixedJointComponents::setR1World(Entity jointEntity, const Vector3& r1World) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR1World[mMapEntityToComponentIndex[jointEntity]] = r1World;
}
// Return the vector from center of body 2 to anchor point in world-space
inline const Vector3& FixedJointComponents::getR2World(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& FixedJointComponents::getR2World(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR2World[mMapEntityToComponentIndex[jointEntity]];
}
// Set the vector from center of body 2 to anchor point in world-space
inline void FixedJointComponents::setR2World(Entity jointEntity, const Vector3& r2World) {
RP3D_FORCE_INLINE void FixedJointComponents::setR2World(Entity jointEntity, const Vector3& r2World) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR2World[mMapEntityToComponentIndex[jointEntity]] = r2World;
}
// Return the inertia tensor of body 1 (in world-space coordinates)
inline const Matrix3x3& FixedJointComponents::getI1(Entity jointEntity) const {
RP3D_FORCE_INLINE const Matrix3x3& FixedJointComponents::getI1(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mI1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the inertia tensor of body 1 (in world-space coordinates)
inline void FixedJointComponents::setI1(Entity jointEntity, const Matrix3x3& i1) {
RP3D_FORCE_INLINE void FixedJointComponents::setI1(Entity jointEntity, const Matrix3x3& i1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mI1[mMapEntityToComponentIndex[jointEntity]] = i1;
}
// Return the inertia tensor of body 2 (in world-space coordinates)
inline const Matrix3x3& FixedJointComponents::getI2(Entity jointEntity) const {
RP3D_FORCE_INLINE const Matrix3x3& FixedJointComponents::getI2(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mI2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the inertia tensor of body 2 (in world-space coordinates)
inline void FixedJointComponents::setI2(Entity jointEntity, const Matrix3x3& i2) {
RP3D_FORCE_INLINE void FixedJointComponents::setI2(Entity jointEntity, const Matrix3x3& i2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mI2[mMapEntityToComponentIndex[jointEntity]] = i2;
}
// Return the translation impulse
inline Vector3& FixedJointComponents::getImpulseTranslation(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& FixedJointComponents::getImpulseTranslation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulseTranslation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the translation impulse
inline void FixedJointComponents::setImpulseTranslation(Entity jointEntity, const Vector3& impulseTranslation) {
RP3D_FORCE_INLINE void FixedJointComponents::setImpulseTranslation(Entity jointEntity, const Vector3& impulseTranslation) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulseTranslation[mMapEntityToComponentIndex[jointEntity]] = impulseTranslation;
}
// Return the translation impulse
inline Vector3& FixedJointComponents::getImpulseRotation(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& FixedJointComponents::getImpulseRotation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulseRotation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the translation impulse
inline void FixedJointComponents::setImpulseRotation(Entity jointEntity, const Vector3& impulseTranslation) {
RP3D_FORCE_INLINE void FixedJointComponents::setImpulseRotation(Entity jointEntity, const Vector3& impulseTranslation) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulseRotation[mMapEntityToComponentIndex[jointEntity]] = impulseTranslation;
}
// Return the translation inverse mass matrix of the constraint
inline Matrix3x3& FixedJointComponents::getInverseMassMatrixTranslation(Entity jointEntity) {
RP3D_FORCE_INLINE Matrix3x3& FixedJointComponents::getInverseMassMatrixTranslation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInverseMassMatrixTranslation[mMapEntityToComponentIndex[jointEntity]];
@ -358,63 +358,63 @@ inline Matrix3x3& FixedJointComponents::getInverseMassMatrixTranslation(Entity j
// Set the translation inverse mass matrix of the constraint
inline void FixedJointComponents::setInverseMassMatrixTranslation(Entity jointEntity, const Matrix3x3& inverseMassMatrix) {
RP3D_FORCE_INLINE void FixedJointComponents::setInverseMassMatrixTranslation(Entity jointEntity, const Matrix3x3& inverseMassMatrix) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInverseMassMatrixTranslation[mMapEntityToComponentIndex[jointEntity]] = inverseMassMatrix;
}
// Return the rotation inverse mass matrix of the constraint
inline Matrix3x3& FixedJointComponents::getInverseMassMatrixRotation(Entity jointEntity) {
RP3D_FORCE_INLINE Matrix3x3& FixedJointComponents::getInverseMassMatrixRotation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInverseMassMatrixRotation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the rotation inverse mass matrix of the constraint
inline void FixedJointComponents::setInverseMassMatrixRotation(Entity jointEntity, const Matrix3x3& inverseMassMatrix) {
RP3D_FORCE_INLINE void FixedJointComponents::setInverseMassMatrixRotation(Entity jointEntity, const Matrix3x3& inverseMassMatrix) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInverseMassMatrixRotation[mMapEntityToComponentIndex[jointEntity]] = inverseMassMatrix;
}
// Return the translation bias
inline Vector3& FixedJointComponents::getBiasTranslation(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& FixedJointComponents::getBiasTranslation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBiasTranslation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the translation impulse
inline void FixedJointComponents::setBiasTranslation(Entity jointEntity, const Vector3 &impulseTranslation) {
RP3D_FORCE_INLINE void FixedJointComponents::setBiasTranslation(Entity jointEntity, const Vector3 &impulseTranslation) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mBiasTranslation[mMapEntityToComponentIndex[jointEntity]] = impulseTranslation;
}
// Return the rotation bias
inline Vector3& FixedJointComponents::getBiasRotation(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& FixedJointComponents::getBiasRotation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBiasRotation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the rotation impulse
inline void FixedJointComponents::setBiasRotation(Entity jointEntity, const Vector3& impulseRotation) {
RP3D_FORCE_INLINE void FixedJointComponents::setBiasRotation(Entity jointEntity, const Vector3& impulseRotation) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mBiasRotation[mMapEntityToComponentIndex[jointEntity]] = impulseRotation;
}
// Return the initial orientation difference
inline Quaternion& FixedJointComponents::getInitOrientationDifferenceInv(Entity jointEntity) {
RP3D_FORCE_INLINE Quaternion& FixedJointComponents::getInitOrientationDifferenceInv(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInitOrientationDifferenceInv[mMapEntityToComponentIndex[jointEntity]];
}
// Set the rotation impulse
inline void FixedJointComponents::setInitOrientationDifferenceInv(Entity jointEntity, const Quaternion& initOrientationDifferenceInv) {
RP3D_FORCE_INLINE void FixedJointComponents::setInitOrientationDifferenceInv(Entity jointEntity, const Quaternion& initOrientationDifferenceInv) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInitOrientationDifferenceInv[mMapEntityToComponentIndex[jointEntity]] = initOrientationDifferenceInv;

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -140,10 +140,10 @@ class HingeJointComponents : public Components {
/// True if the motor of the joint in enabled
bool* mIsMotorEnabled;
/// Lower limit (minimum allowed rotation angle in radian)
/// Lower limit (minimum allowed rotation angle in radians)
decimal* mLowerLimit;
/// Upper limit (maximum translation distance)
/// Upper limit (maximum allowed rotation angle in radians)
decimal* mUpperLimit;
/// True if the lower limit is violated
@ -412,136 +412,137 @@ class HingeJointComponents : public Components {
friend class BroadPhaseSystem;
friend class SolveHingeJointSystem;
friend class HingeJoint;
};
// Return a pointer to a given joint
inline HingeJoint* HingeJointComponents::getJoint(Entity jointEntity) const {
RP3D_FORCE_INLINE HingeJoint* HingeJointComponents::getJoint(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mJoints[mMapEntityToComponentIndex[jointEntity]];
}
// Set the joint pointer to a given joint
inline void HingeJointComponents::setJoint(Entity jointEntity, HingeJoint* joint) const {
RP3D_FORCE_INLINE void HingeJointComponents::setJoint(Entity jointEntity, HingeJoint* joint) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mJoints[mMapEntityToComponentIndex[jointEntity]] = joint;
}
// Return the local anchor point of body 1 for a given joint
inline const Vector3& HingeJointComponents::getLocalAnchorPointBody1(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& HingeJointComponents::getLocalAnchorPointBody1(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mLocalAnchorPointBody1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the local anchor point of body 1 for a given joint
inline void HingeJointComponents::setLocalAnchorPointBody1(Entity jointEntity, const Vector3& localAnchoirPointBody1) {
RP3D_FORCE_INLINE void HingeJointComponents::setLocalAnchorPointBody1(Entity jointEntity, const Vector3& localAnchoirPointBody1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mLocalAnchorPointBody1[mMapEntityToComponentIndex[jointEntity]] = localAnchoirPointBody1;
}
// Return the local anchor point of body 2 for a given joint
inline const Vector3& HingeJointComponents::getLocalAnchorPointBody2(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& HingeJointComponents::getLocalAnchorPointBody2(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mLocalAnchorPointBody2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the local anchor point of body 2 for a given joint
inline void HingeJointComponents::setLocalAnchorPointBody2(Entity jointEntity, const Vector3& localAnchoirPointBody2) {
RP3D_FORCE_INLINE void HingeJointComponents::setLocalAnchorPointBody2(Entity jointEntity, const Vector3& localAnchoirPointBody2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mLocalAnchorPointBody2[mMapEntityToComponentIndex[jointEntity]] = localAnchoirPointBody2;
}
// Return the vector from center of body 1 to anchor point in world-space
inline const Vector3& HingeJointComponents::getR1World(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& HingeJointComponents::getR1World(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR1World[mMapEntityToComponentIndex[jointEntity]];
}
// Set the vector from center of body 1 to anchor point in world-space
inline void HingeJointComponents::setR1World(Entity jointEntity, const Vector3& r1World) {
RP3D_FORCE_INLINE void HingeJointComponents::setR1World(Entity jointEntity, const Vector3& r1World) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR1World[mMapEntityToComponentIndex[jointEntity]] = r1World;
}
// Return the vector from center of body 2 to anchor point in world-space
inline const Vector3& HingeJointComponents::getR2World(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& HingeJointComponents::getR2World(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR2World[mMapEntityToComponentIndex[jointEntity]];
}
// Set the vector from center of body 2 to anchor point in world-space
inline void HingeJointComponents::setR2World(Entity jointEntity, const Vector3& r2World) {
RP3D_FORCE_INLINE void HingeJointComponents::setR2World(Entity jointEntity, const Vector3& r2World) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR2World[mMapEntityToComponentIndex[jointEntity]] = r2World;
}
// Return the inertia tensor of body 1 (in world-space coordinates)
inline const Matrix3x3& HingeJointComponents::getI1(Entity jointEntity) const {
RP3D_FORCE_INLINE const Matrix3x3& HingeJointComponents::getI1(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mI1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the inertia tensor of body 1 (in world-space coordinates)
inline void HingeJointComponents::setI1(Entity jointEntity, const Matrix3x3& i1) {
RP3D_FORCE_INLINE void HingeJointComponents::setI1(Entity jointEntity, const Matrix3x3& i1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mI1[mMapEntityToComponentIndex[jointEntity]] = i1;
}
// Return the inertia tensor of body 2 (in world-space coordinates)
inline const Matrix3x3& HingeJointComponents::getI2(Entity jointEntity) const {
RP3D_FORCE_INLINE const Matrix3x3& HingeJointComponents::getI2(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mI2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the inertia tensor of body 2 (in world-space coordinates)
inline void HingeJointComponents::setI2(Entity jointEntity, const Matrix3x3& i2) {
RP3D_FORCE_INLINE void HingeJointComponents::setI2(Entity jointEntity, const Matrix3x3& i2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mI2[mMapEntityToComponentIndex[jointEntity]] = i2;
}
// Return the translation impulse
inline Vector3& HingeJointComponents::getImpulseTranslation(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& HingeJointComponents::getImpulseTranslation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulseTranslation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the translation impulse
inline void HingeJointComponents::setImpulseTranslation(Entity jointEntity, const Vector3& impulseTranslation) {
RP3D_FORCE_INLINE void HingeJointComponents::setImpulseTranslation(Entity jointEntity, const Vector3& impulseTranslation) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulseTranslation[mMapEntityToComponentIndex[jointEntity]] = impulseTranslation;
}
// Return the translation impulse
inline Vector2& HingeJointComponents::getImpulseRotation(Entity jointEntity) {
RP3D_FORCE_INLINE Vector2& HingeJointComponents::getImpulseRotation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulseRotation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the translation impulse
inline void HingeJointComponents::setImpulseRotation(Entity jointEntity, const Vector2& impulseTranslation) {
RP3D_FORCE_INLINE void HingeJointComponents::setImpulseRotation(Entity jointEntity, const Vector2& impulseTranslation) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulseRotation[mMapEntityToComponentIndex[jointEntity]] = impulseTranslation;
}
// Return the translation inverse mass matrix of the constraint
inline Matrix3x3& HingeJointComponents::getInverseMassMatrixTranslation(Entity jointEntity) {
RP3D_FORCE_INLINE Matrix3x3& HingeJointComponents::getInverseMassMatrixTranslation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInverseMassMatrixTranslation[mMapEntityToComponentIndex[jointEntity]];
@ -549,91 +550,91 @@ inline Matrix3x3& HingeJointComponents::getInverseMassMatrixTranslation(Entity j
// Set the translation inverse mass matrix of the constraint
inline void HingeJointComponents::setInverseMassMatrixTranslation(Entity jointEntity, const Matrix3x3& inverseMassMatrix) {
RP3D_FORCE_INLINE void HingeJointComponents::setInverseMassMatrixTranslation(Entity jointEntity, const Matrix3x3& inverseMassMatrix) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInverseMassMatrixTranslation[mMapEntityToComponentIndex[jointEntity]] = inverseMassMatrix;
}
// Return the rotation inverse mass matrix of the constraint
inline Matrix2x2& HingeJointComponents::getInverseMassMatrixRotation(Entity jointEntity) {
RP3D_FORCE_INLINE Matrix2x2& HingeJointComponents::getInverseMassMatrixRotation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInverseMassMatrixRotation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the rotation inverse mass matrix of the constraint
inline void HingeJointComponents::setInverseMassMatrixRotation(Entity jointEntity, const Matrix2x2& inverseMassMatrix) {
RP3D_FORCE_INLINE void HingeJointComponents::setInverseMassMatrixRotation(Entity jointEntity, const Matrix2x2& inverseMassMatrix) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInverseMassMatrixRotation[mMapEntityToComponentIndex[jointEntity]] = inverseMassMatrix;
}
// Return the translation bias
inline Vector3& HingeJointComponents::getBiasTranslation(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& HingeJointComponents::getBiasTranslation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBiasTranslation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the translation impulse
inline void HingeJointComponents::setBiasTranslation(Entity jointEntity, const Vector3 &impulseTranslation) {
RP3D_FORCE_INLINE void HingeJointComponents::setBiasTranslation(Entity jointEntity, const Vector3 &impulseTranslation) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mBiasTranslation[mMapEntityToComponentIndex[jointEntity]] = impulseTranslation;
}
// Return the rotation bias
inline Vector2 &HingeJointComponents::getBiasRotation(Entity jointEntity) {
RP3D_FORCE_INLINE Vector2 &HingeJointComponents::getBiasRotation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBiasRotation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the rotation impulse
inline void HingeJointComponents::setBiasRotation(Entity jointEntity, const Vector2& impulseRotation) {
RP3D_FORCE_INLINE void HingeJointComponents::setBiasRotation(Entity jointEntity, const Vector2& impulseRotation) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mBiasRotation[mMapEntityToComponentIndex[jointEntity]] = impulseRotation;
}
// Return the initial orientation difference
inline Quaternion& HingeJointComponents::getInitOrientationDifferenceInv(Entity jointEntity) {
RP3D_FORCE_INLINE Quaternion& HingeJointComponents::getInitOrientationDifferenceInv(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInitOrientationDifferenceInv[mMapEntityToComponentIndex[jointEntity]];
}
// Set the rotation impulse
inline void HingeJointComponents::setInitOrientationDifferenceInv(Entity jointEntity, const Quaternion& initOrientationDifferenceInv) {
RP3D_FORCE_INLINE void HingeJointComponents::setInitOrientationDifferenceInv(Entity jointEntity, const Quaternion& initOrientationDifferenceInv) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInitOrientationDifferenceInv[mMapEntityToComponentIndex[jointEntity]] = initOrientationDifferenceInv;
}
// Return the hinge rotation axis (in local-space coordinates of body 1)
inline Vector3& HingeJointComponents::getHingeLocalAxisBody1(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& HingeJointComponents::getHingeLocalAxisBody1(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mHingeLocalAxisBody1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the hinge rotation axis (in local-space coordinates of body 1)
inline void HingeJointComponents::setHingeLocalAxisBody1(Entity jointEntity, const Vector3& hingeLocalAxisBody1) {
RP3D_FORCE_INLINE void HingeJointComponents::setHingeLocalAxisBody1(Entity jointEntity, const Vector3& hingeLocalAxisBody1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mHingeLocalAxisBody1[mMapEntityToComponentIndex[jointEntity]] = hingeLocalAxisBody1;
}
// Return the hinge rotation axis (in local-space coordiantes of body 2)
inline Vector3& HingeJointComponents::getHingeLocalAxisBody2(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& HingeJointComponents::getHingeLocalAxisBody2(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mHingeLocalAxisBody2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the hinge rotation axis (in local-space coordiantes of body 2)
inline void HingeJointComponents::setHingeLocalAxisBody2(Entity jointEntity, const Vector3& hingeLocalAxisBody2) {
RP3D_FORCE_INLINE void HingeJointComponents::setHingeLocalAxisBody2(Entity jointEntity, const Vector3& hingeLocalAxisBody2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mHingeLocalAxisBody2[mMapEntityToComponentIndex[jointEntity]] = hingeLocalAxisBody2;
@ -641,56 +642,56 @@ inline void HingeJointComponents::setHingeLocalAxisBody2(Entity jointEntity, con
// Return the hinge rotation axis (in world-space coordinates) computed from body 1
inline Vector3& HingeJointComponents::getA1(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& HingeJointComponents::getA1(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mA1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the hinge rotation axis (in world-space coordinates) computed from body 1
inline void HingeJointComponents::setA1(Entity jointEntity, const Vector3& a1) {
RP3D_FORCE_INLINE void HingeJointComponents::setA1(Entity jointEntity, const Vector3& a1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mA1[mMapEntityToComponentIndex[jointEntity]] = a1;
}
// Return the cross product of vector b2 and a1
inline Vector3& HingeJointComponents::getB2CrossA1(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& HingeJointComponents::getB2CrossA1(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mB2CrossA1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the cross product of vector b2 and a1
inline void HingeJointComponents::setB2CrossA1(Entity jointEntity, const Vector3& b2CrossA1) {
RP3D_FORCE_INLINE void HingeJointComponents::setB2CrossA1(Entity jointEntity, const Vector3& b2CrossA1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mB2CrossA1[mMapEntityToComponentIndex[jointEntity]] = b2CrossA1;
}
// Return the cross product of vector c2 and a1;
inline Vector3& HingeJointComponents::getC2CrossA1(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& HingeJointComponents::getC2CrossA1(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mC2CrossA1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the cross product of vector c2 and a1;
inline void HingeJointComponents::setC2CrossA1(Entity jointEntity, const Vector3& c2CrossA1) {
RP3D_FORCE_INLINE void HingeJointComponents::setC2CrossA1(Entity jointEntity, const Vector3& c2CrossA1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mC2CrossA1[mMapEntityToComponentIndex[jointEntity]] = c2CrossA1;
}
// Return the accumulated impulse for the lower limit constraint
inline decimal HingeJointComponents::getImpulseLowerLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal HingeJointComponents::getImpulseLowerLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulseLowerLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the accumulated impulse for the lower limit constraint
inline void HingeJointComponents::setImpulseLowerLimit(Entity jointEntity, decimal impulseLowerLimit) {
RP3D_FORCE_INLINE void HingeJointComponents::setImpulseLowerLimit(Entity jointEntity, decimal impulseLowerLimit) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulseLowerLimit[mMapEntityToComponentIndex[jointEntity]] = impulseLowerLimit;
@ -698,14 +699,14 @@ inline void HingeJointComponents::setImpulseLowerLimit(Entity jointEntity, decim
// Return the accumulated impulse for the upper limit constraint
inline decimal HingeJointComponents::getImpulseUpperLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal HingeJointComponents::getImpulseUpperLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulseUpperLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the accumulated impulse for the upper limit constraint
inline void HingeJointComponents::setImpulseUpperLimit(Entity jointEntity, decimal impulseUpperLimit) const {
RP3D_FORCE_INLINE void HingeJointComponents::setImpulseUpperLimit(Entity jointEntity, decimal impulseUpperLimit) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulseUpperLimit[mMapEntityToComponentIndex[jointEntity]] = impulseUpperLimit;
@ -713,182 +714,182 @@ inline void HingeJointComponents::setImpulseUpperLimit(Entity jointEntity, decim
// Return the accumulated impulse for the motor constraint;
inline decimal HingeJointComponents::getImpulseMotor(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal HingeJointComponents::getImpulseMotor(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulseMotor[mMapEntityToComponentIndex[jointEntity]];
}
// Set the accumulated impulse for the motor constraint;
inline void HingeJointComponents::setImpulseMotor(Entity jointEntity, decimal impulseMotor) {
RP3D_FORCE_INLINE void HingeJointComponents::setImpulseMotor(Entity jointEntity, decimal impulseMotor) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulseMotor[mMapEntityToComponentIndex[jointEntity]] = impulseMotor;
}
// Return the inverse of mass matrix K=JM^-1J^t for the limits and motor constraints (1x1 matrix)
inline decimal HingeJointComponents::getInverseMassMatrixLimitMotor(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal HingeJointComponents::getInverseMassMatrixLimitMotor(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInverseMassMatrixLimitMotor[mMapEntityToComponentIndex[jointEntity]];
}
// Set the inverse of mass matrix K=JM^-1J^t for the limits and motor constraints (1x1 matrix)
inline void HingeJointComponents::setInverseMassMatrixLimitMotor(Entity jointEntity, decimal inverseMassMatrixLimitMotor) {
RP3D_FORCE_INLINE void HingeJointComponents::setInverseMassMatrixLimitMotor(Entity jointEntity, decimal inverseMassMatrixLimitMotor) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInverseMassMatrixLimitMotor[mMapEntityToComponentIndex[jointEntity]] = inverseMassMatrixLimitMotor;
}
// Return the inverse of mass matrix K=JM^-1J^t for the motor
inline decimal HingeJointComponents::getInverseMassMatrixMotor(Entity jointEntity) {
RP3D_FORCE_INLINE decimal HingeJointComponents::getInverseMassMatrixMotor(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInverseMassMatrixMotor[mMapEntityToComponentIndex[jointEntity]];
}
// Return the inverse of mass matrix K=JM^-1J^t for the motor
inline void HingeJointComponents::setInverseMassMatrixMotor(Entity jointEntity, decimal inverseMassMatrixMotor) {
RP3D_FORCE_INLINE void HingeJointComponents::setInverseMassMatrixMotor(Entity jointEntity, decimal inverseMassMatrixMotor) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInverseMassMatrixMotor[mMapEntityToComponentIndex[jointEntity]] = inverseMassMatrixMotor;
}
// Return the bias of the lower limit constraint
inline decimal HingeJointComponents::getBLowerLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal HingeJointComponents::getBLowerLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBLowerLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the bias of the lower limit constraint
inline void HingeJointComponents::setBLowerLimit(Entity jointEntity, decimal bLowerLimit) const {
RP3D_FORCE_INLINE void HingeJointComponents::setBLowerLimit(Entity jointEntity, decimal bLowerLimit) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mBLowerLimit[mMapEntityToComponentIndex[jointEntity]] = bLowerLimit;
}
// Return the bias of the upper limit constraint
inline decimal HingeJointComponents::getBUpperLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal HingeJointComponents::getBUpperLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBUpperLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the bias of the upper limit constraint
inline void HingeJointComponents::setBUpperLimit(Entity jointEntity, decimal bUpperLimit) {
RP3D_FORCE_INLINE void HingeJointComponents::setBUpperLimit(Entity jointEntity, decimal bUpperLimit) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mBUpperLimit[mMapEntityToComponentIndex[jointEntity]] = bUpperLimit;
}
// Return true if the joint limits are enabled
inline bool HingeJointComponents::getIsLimitEnabled(Entity jointEntity) const {
RP3D_FORCE_INLINE bool HingeJointComponents::getIsLimitEnabled(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mIsLimitEnabled[mMapEntityToComponentIndex[jointEntity]];
}
// Set to true if the joint limits are enabled
inline void HingeJointComponents::setIsLimitEnabled(Entity jointEntity, bool isLimitEnabled) {
RP3D_FORCE_INLINE void HingeJointComponents::setIsLimitEnabled(Entity jointEntity, bool isLimitEnabled) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mIsLimitEnabled[mMapEntityToComponentIndex[jointEntity]] = isLimitEnabled;
}
// Return true if the motor of the joint in enabled
inline bool HingeJointComponents::getIsMotorEnabled(Entity jointEntity) const {
RP3D_FORCE_INLINE bool HingeJointComponents::getIsMotorEnabled(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mIsMotorEnabled[mMapEntityToComponentIndex[jointEntity]];
}
// Set to true if the motor of the joint in enabled
inline void HingeJointComponents::setIsMotorEnabled(Entity jointEntity, bool isMotorEnabled) const {
RP3D_FORCE_INLINE void HingeJointComponents::setIsMotorEnabled(Entity jointEntity, bool isMotorEnabled) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mIsMotorEnabled[mMapEntityToComponentIndex[jointEntity]] = isMotorEnabled;
}
// Return the Lower limit (minimum allowed rotation angle in radian)
inline decimal HingeJointComponents::getLowerLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal HingeJointComponents::getLowerLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mLowerLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the Lower limit (minimum allowed rotation angle in radian)
inline void HingeJointComponents::setLowerLimit(Entity jointEntity, decimal lowerLimit) const {
RP3D_FORCE_INLINE void HingeJointComponents::setLowerLimit(Entity jointEntity, decimal lowerLimit) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mLowerLimit[mMapEntityToComponentIndex[jointEntity]] = lowerLimit;
}
// Return the upper limit (maximum translation distance)
inline decimal HingeJointComponents::getUpperLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal HingeJointComponents::getUpperLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mUpperLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the upper limit (maximum translation distance)
inline void HingeJointComponents::setUpperLimit(Entity jointEntity, decimal upperLimit) {
RP3D_FORCE_INLINE void HingeJointComponents::setUpperLimit(Entity jointEntity, decimal upperLimit) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mUpperLimit[mMapEntityToComponentIndex[jointEntity]] = upperLimit;
}
// Return true if the lower limit is violated
inline bool HingeJointComponents::getIsLowerLimitViolated(Entity jointEntity) const {
RP3D_FORCE_INLINE bool HingeJointComponents::getIsLowerLimitViolated(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mIsLowerLimitViolated[mMapEntityToComponentIndex[jointEntity]];
}
// Set to true if the lower limit is violated
inline void HingeJointComponents::setIsLowerLimitViolated(Entity jointEntity, bool isLowerLimitViolated) {
RP3D_FORCE_INLINE void HingeJointComponents::setIsLowerLimitViolated(Entity jointEntity, bool isLowerLimitViolated) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mIsLowerLimitViolated[mMapEntityToComponentIndex[jointEntity]] = isLowerLimitViolated;
}
// Return true if the upper limit is violated
inline bool HingeJointComponents::getIsUpperLimitViolated(Entity jointEntity) const {
RP3D_FORCE_INLINE bool HingeJointComponents::getIsUpperLimitViolated(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mIsUpperLimitViolated[mMapEntityToComponentIndex[jointEntity]];
}
// Set to true if the upper limit is violated
inline void HingeJointComponents::setIsUpperLimitViolated(Entity jointEntity, bool isUpperLimitViolated) const {
RP3D_FORCE_INLINE void HingeJointComponents::setIsUpperLimitViolated(Entity jointEntity, bool isUpperLimitViolated) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mIsUpperLimitViolated[mMapEntityToComponentIndex[jointEntity]] = isUpperLimitViolated;
}
// Return the motor speed (in rad/s)
inline decimal HingeJointComponents::getMotorSpeed(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal HingeJointComponents::getMotorSpeed(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mMotorSpeed[mMapEntityToComponentIndex[jointEntity]];
}
// Set the motor speed (in rad/s)
inline void HingeJointComponents::setMotorSpeed(Entity jointEntity, decimal motorSpeed) {
RP3D_FORCE_INLINE void HingeJointComponents::setMotorSpeed(Entity jointEntity, decimal motorSpeed) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mMotorSpeed[mMapEntityToComponentIndex[jointEntity]] = motorSpeed;
}
// Return the maximum motor torque (in Newtons) that can be applied to reach to desired motor speed
inline decimal HingeJointComponents::getMaxMotorTorque(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal HingeJointComponents::getMaxMotorTorque(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mMaxMotorTorque[mMapEntityToComponentIndex[jointEntity]];
}
// Set the maximum motor torque (in Newtons) that can be applied to reach to desired motor speed
inline void HingeJointComponents::setMaxMotorTorque(Entity jointEntity, decimal maxMotorTorque) {
RP3D_FORCE_INLINE void HingeJointComponents::setMaxMotorTorque(Entity jointEntity, decimal maxMotorTorque) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mMaxMotorTorque[mMapEntityToComponentIndex[jointEntity]] = maxMotorTorque;

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -138,7 +138,7 @@ class JointComponents : public Components {
JointsPositionCorrectionTechnique getPositionCorrectionTechnique(Entity jointEntity) const;
/// Set the position correction technique of a joint
void getPositionCorrectionTechnique(Entity jointEntity, JointsPositionCorrectionTechnique positionCorrectionTechnique);
void setPositionCorrectionTechnique(Entity jointEntity, JointsPositionCorrectionTechnique positionCorrectionTechnique);
/// Return true if the collision is enabled between the two bodies of a joint
bool getIsCollisionEnabled(Entity jointEntity) const;
@ -157,64 +157,69 @@ class JointComponents : public Components {
friend class BroadPhaseSystem;
friend class ConstraintSolverSystem;
friend class PhysicsWorld;
friend class SolveBallAndSocketJointSystem;
friend class SolveFixedJointSystem;
friend class SolveHingeJointSystem;
friend class SolveSliderJointSystem;
};
// Return the entity of the first body of a joint
inline Entity JointComponents::getBody1Entity(Entity jointEntity) const {
RP3D_FORCE_INLINE Entity JointComponents::getBody1Entity(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBody1Entities[mMapEntityToComponentIndex[jointEntity]];
}
// Return the entity of the second body of a joint
inline Entity JointComponents::getBody2Entity(Entity jointEntity) const {
RP3D_FORCE_INLINE Entity JointComponents::getBody2Entity(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBody2Entities[mMapEntityToComponentIndex[jointEntity]];
}
// Return a pointer to the joint
inline Joint* JointComponents::getJoint(Entity jointEntity) const {
RP3D_FORCE_INLINE Joint* JointComponents::getJoint(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mJoints[mMapEntityToComponentIndex[jointEntity]];
}
// Return the type of a joint
inline JointType JointComponents::getType(Entity jointEntity) const {
RP3D_FORCE_INLINE JointType JointComponents::getType(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mTypes[mMapEntityToComponentIndex[jointEntity]];
}
// Return the position correction technique of a joint
inline JointsPositionCorrectionTechnique JointComponents::getPositionCorrectionTechnique(Entity jointEntity) const {
RP3D_FORCE_INLINE JointsPositionCorrectionTechnique JointComponents::getPositionCorrectionTechnique(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mPositionCorrectionTechniques[mMapEntityToComponentIndex[jointEntity]];
}
// Set the position correction technique of a joint
inline void JointComponents::getPositionCorrectionTechnique(Entity jointEntity, JointsPositionCorrectionTechnique positionCorrectionTechnique) {
RP3D_FORCE_INLINE void JointComponents::setPositionCorrectionTechnique(Entity jointEntity, JointsPositionCorrectionTechnique positionCorrectionTechnique) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mPositionCorrectionTechniques[mMapEntityToComponentIndex[jointEntity]] = positionCorrectionTechnique;
}
// Return true if the collision is enabled between the two bodies of a joint
inline bool JointComponents::getIsCollisionEnabled(Entity jointEntity) const {
RP3D_FORCE_INLINE bool JointComponents::getIsCollisionEnabled(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mIsCollisionEnabled[mMapEntityToComponentIndex[jointEntity]];
}
// Set whether the collision is enabled between the two bodies of a joint
inline void JointComponents::setIsCollisionEnabled(Entity jointEntity, bool isCollisionEnabled) {
RP3D_FORCE_INLINE void JointComponents::setIsCollisionEnabled(Entity jointEntity, bool isCollisionEnabled) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mIsCollisionEnabled[mMapEntityToComponentIndex[jointEntity]] = isCollisionEnabled;
}
// Return true if the joint has already been added into an island during island creation
inline bool JointComponents::getIsAlreadyInIsland(Entity jointEntity) const {
RP3D_FORCE_INLINE bool JointComponents::getIsAlreadyInIsland(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mIsAlreadyInIsland[mMapEntityToComponentIndex[jointEntity]];
}
// Set to true if the joint has already been added into an island during island creation
inline void JointComponents::setIsAlreadyInIsland(Entity jointEntity, bool isAlreadyInIsland) {
RP3D_FORCE_INLINE void JointComponents::setIsAlreadyInIsland(Entity jointEntity, bool isAlreadyInIsland) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mIsAlreadyInIsland[mMapEntityToComponentIndex[jointEntity]] = isAlreadyInIsland;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -109,9 +109,12 @@ class RigidBodyComponents : public Components {
/// Array with the inertia tensor of each component
Vector3* mLocalInertiaTensors;
/// Array with the inverse of the inertia tensor of each component
/// Array with the inverse of the local inertia tensor of each component
Vector3* mInverseInertiaTensorsLocal;
/// Array with the inverse of the world inertia tensor of each component
Matrix3x3* mInverseInertiaTensorsWorld;
/// Array with the constrained linear velocity of each component
Vector3* mConstrainedLinearVelocities;
@ -142,8 +145,17 @@ class RigidBodyComponents : public Components {
/// Array with the boolean value to know if the body has already been added into an island
bool* mIsAlreadyInIsland;
/// For each body, the list of joints entities the body is part of
List<Entity>* mJoints;
/// For each body, the array of joints entities the body is part of
Array<Entity>* mJoints;
/// For each body, the array of the indices of contact pairs in which the body is involved
Array<uint>* mContactPairs;
/// For each body, the vector of lock translation vectors
Vector3* mLinearLockAxisFactors;
/// For each body, the vector of lock rotation vectors
Vector3* mAngularLockAxisFactors;
// -------------------- Methods -------------------- //
@ -258,6 +270,9 @@ class RigidBodyComponents : public Components {
/// Return the inverse local inertia tensor of an entity
const Vector3& getInertiaTensorLocalInverse(Entity bodyEntity);
/// Return the inverse world inertia tensor of an entity
const Matrix3x3& getInertiaTensorWorldInverse(Entity bodyEntity);
/// Set the external force of an entity
void setExternalForce(Entity bodyEntity, const Vector3& externalForce);
@ -303,6 +318,12 @@ class RigidBodyComponents : public Components {
/// Return true if the entity is already in an island
bool getIsAlreadyInIsland(Entity bodyEntity) const;
/// Return the lock translation factor
const Vector3& getLinearLockAxisFactor(Entity bodyEntity) const;
/// Return the lock rotation factor
const Vector3& getAngularLockAxisFactor(Entity bodyEntity) const;
/// Set the constrained linear velocity of an entity
void setConstrainedLinearVelocity(Entity bodyEntity, const Vector3& constrainedLinearVelocity);
@ -333,8 +354,14 @@ class RigidBodyComponents : public Components {
/// Set the value to know if the entity is already in an island
void setIsAlreadyInIsland(Entity bodyEntity, bool isAlreadyInIsland);
/// Return the list of joints of a body
const List<Entity>& getJoints(Entity bodyEntity) const;
/// Set the linear lock axis factor
void setLinearLockAxisFactor(Entity bodyEntity, const Vector3& linearLockAxisFactor);
/// Set the angular lock axis factor
void setAngularLockAxisFactor(Entity bodyEntity, const Vector3& rotationTranslationFactor);
/// Return the array of joints of a body
const Array<Entity>& getJoints(Entity bodyEntity) const;
/// Add a joint to a body component
void addJointToBody(Entity bodyEntity, Entity jointEntity);
@ -342,10 +369,14 @@ class RigidBodyComponents : public Components {
/// Remove a joint from a body component
void removeJointFromBody(Entity bodyEntity, Entity jointEntity);
/// A an associated contact pairs into the contact pairs array of the body
void addContacPair(Entity bodyEntity, uint32 contactPairIndex);
// -------------------- Friendship -------------------- //
friend class PhysicsWorld;
friend class ContactSolverSystem;
friend class CollisionDetectionSystem;
friend class SolveBallAndSocketJointSystem;
friend class SolveFixedJointSystem;
friend class SolveHingeJointSystem;
@ -358,7 +389,7 @@ class RigidBodyComponents : public Components {
};
// Return a pointer to a body rigid
inline RigidBody* RigidBodyComponents::getRigidBody(Entity bodyEntity) {
RP3D_FORCE_INLINE RigidBody* RigidBodyComponents::getRigidBody(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -366,7 +397,7 @@ inline RigidBody* RigidBodyComponents::getRigidBody(Entity bodyEntity) {
}
// Return true if the body is allowed to sleep
inline bool RigidBodyComponents::getIsAllowedToSleep(Entity bodyEntity) const {
RP3D_FORCE_INLINE bool RigidBodyComponents::getIsAllowedToSleep(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -374,7 +405,7 @@ inline bool RigidBodyComponents::getIsAllowedToSleep(Entity bodyEntity) const {
}
// Set the value to know if the body is allowed to sleep
inline void RigidBodyComponents::setIsAllowedToSleep(Entity bodyEntity, bool isAllowedToSleep) const {
RP3D_FORCE_INLINE void RigidBodyComponents::setIsAllowedToSleep(Entity bodyEntity, bool isAllowedToSleep) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -382,7 +413,7 @@ inline void RigidBodyComponents::setIsAllowedToSleep(Entity bodyEntity, bool isA
}
// Return true if the body is sleeping
inline bool RigidBodyComponents::getIsSleeping(Entity bodyEntity) const {
RP3D_FORCE_INLINE bool RigidBodyComponents::getIsSleeping(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -390,7 +421,7 @@ inline bool RigidBodyComponents::getIsSleeping(Entity bodyEntity) const {
}
// Set the value to know if the body is sleeping
inline void RigidBodyComponents::setIsSleeping(Entity bodyEntity, bool isSleeping) const {
RP3D_FORCE_INLINE void RigidBodyComponents::setIsSleeping(Entity bodyEntity, bool isSleeping) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -398,7 +429,7 @@ inline void RigidBodyComponents::setIsSleeping(Entity bodyEntity, bool isSleepin
}
// Return the sleep time
inline decimal RigidBodyComponents::getSleepTime(Entity bodyEntity) const {
RP3D_FORCE_INLINE decimal RigidBodyComponents::getSleepTime(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -406,7 +437,7 @@ inline decimal RigidBodyComponents::getSleepTime(Entity bodyEntity) const {
}
// Set the sleep time
inline void RigidBodyComponents::setSleepTime(Entity bodyEntity, decimal sleepTime) const {
RP3D_FORCE_INLINE void RigidBodyComponents::setSleepTime(Entity bodyEntity, decimal sleepTime) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -414,7 +445,7 @@ inline void RigidBodyComponents::setSleepTime(Entity bodyEntity, decimal sleepTi
}
// Return the body type of a body
inline BodyType RigidBodyComponents::getBodyType(Entity bodyEntity) {
RP3D_FORCE_INLINE BodyType RigidBodyComponents::getBodyType(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -422,7 +453,7 @@ inline BodyType RigidBodyComponents::getBodyType(Entity bodyEntity) {
}
// Set the body type of a body
inline void RigidBodyComponents::setBodyType(Entity bodyEntity, BodyType bodyType) {
RP3D_FORCE_INLINE void RigidBodyComponents::setBodyType(Entity bodyEntity, BodyType bodyType) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -430,7 +461,7 @@ inline void RigidBodyComponents::setBodyType(Entity bodyEntity, BodyType bodyTyp
}
// Return the linear velocity of an entity
inline const Vector3& RigidBodyComponents::getLinearVelocity(Entity bodyEntity) const {
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getLinearVelocity(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -438,7 +469,7 @@ inline const Vector3& RigidBodyComponents::getLinearVelocity(Entity bodyEntity)
}
// Return the angular velocity of an entity
inline const Vector3& RigidBodyComponents::getAngularVelocity(Entity bodyEntity) const {
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getAngularVelocity(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -446,7 +477,7 @@ inline const Vector3& RigidBodyComponents::getAngularVelocity(Entity bodyEntity)
}
// Set the linear velocity of an entity
inline void RigidBodyComponents::setLinearVelocity(Entity bodyEntity, const Vector3& linearVelocity) {
RP3D_FORCE_INLINE void RigidBodyComponents::setLinearVelocity(Entity bodyEntity, const Vector3& linearVelocity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -454,7 +485,7 @@ inline void RigidBodyComponents::setLinearVelocity(Entity bodyEntity, const Vect
}
// Set the angular velocity of an entity
inline void RigidBodyComponents::setAngularVelocity(Entity bodyEntity, const Vector3& angularVelocity) {
RP3D_FORCE_INLINE void RigidBodyComponents::setAngularVelocity(Entity bodyEntity, const Vector3& angularVelocity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -462,7 +493,7 @@ inline void RigidBodyComponents::setAngularVelocity(Entity bodyEntity, const Vec
}
// Return the external force of an entity
inline const Vector3& RigidBodyComponents::getExternalForce(Entity bodyEntity) const {
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getExternalForce(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -470,7 +501,7 @@ inline const Vector3& RigidBodyComponents::getExternalForce(Entity bodyEntity) c
}
// Return the external torque of an entity
inline const Vector3& RigidBodyComponents::getExternalTorque(Entity bodyEntity) const {
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getExternalTorque(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -478,7 +509,7 @@ inline const Vector3& RigidBodyComponents::getExternalTorque(Entity bodyEntity)
}
// Return the linear damping factor of an entity
inline decimal RigidBodyComponents::getLinearDamping(Entity bodyEntity) const {
RP3D_FORCE_INLINE decimal RigidBodyComponents::getLinearDamping(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -486,7 +517,7 @@ inline decimal RigidBodyComponents::getLinearDamping(Entity bodyEntity) const {
}
// Return the angular damping factor of an entity
inline decimal RigidBodyComponents::getAngularDamping(Entity bodyEntity) const {
RP3D_FORCE_INLINE decimal RigidBodyComponents::getAngularDamping(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -494,7 +525,7 @@ inline decimal RigidBodyComponents::getAngularDamping(Entity bodyEntity) const {
}
// Return the mass of an entity
inline decimal RigidBodyComponents::getMass(Entity bodyEntity) const {
RP3D_FORCE_INLINE decimal RigidBodyComponents::getMass(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -502,7 +533,7 @@ inline decimal RigidBodyComponents::getMass(Entity bodyEntity) const {
}
// Return the inverse mass of an entity
inline decimal RigidBodyComponents::getMassInverse(Entity bodyEntity) const {
RP3D_FORCE_INLINE decimal RigidBodyComponents::getMassInverse(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -510,15 +541,23 @@ inline decimal RigidBodyComponents::getMassInverse(Entity bodyEntity) const {
}
// Return the inverse local inertia tensor of an entity
inline const Vector3& RigidBodyComponents::getInertiaTensorLocalInverse(Entity bodyEntity) {
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getInertiaTensorLocalInverse(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
return mInverseInertiaTensorsLocal[mMapEntityToComponentIndex[bodyEntity]];
}
// Return the inverse world inertia tensor of an entity
RP3D_FORCE_INLINE const Matrix3x3& RigidBodyComponents::getInertiaTensorWorldInverse(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
return mInverseInertiaTensorsWorld[mMapEntityToComponentIndex[bodyEntity]];
}
// Set the external force of an entity
inline void RigidBodyComponents::setExternalForce(Entity bodyEntity, const Vector3& externalForce) {
RP3D_FORCE_INLINE void RigidBodyComponents::setExternalForce(Entity bodyEntity, const Vector3& externalForce) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -526,7 +565,7 @@ inline void RigidBodyComponents::setExternalForce(Entity bodyEntity, const Vecto
}
// Set the external force of an entity
inline void RigidBodyComponents::setExternalTorque(Entity bodyEntity, const Vector3& externalTorque) {
RP3D_FORCE_INLINE void RigidBodyComponents::setExternalTorque(Entity bodyEntity, const Vector3& externalTorque) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -534,7 +573,7 @@ inline void RigidBodyComponents::setExternalTorque(Entity bodyEntity, const Vect
}
// Set the linear damping factor of an entity
inline void RigidBodyComponents::setLinearDamping(Entity bodyEntity, decimal linearDamping) {
RP3D_FORCE_INLINE void RigidBodyComponents::setLinearDamping(Entity bodyEntity, decimal linearDamping) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -542,7 +581,7 @@ inline void RigidBodyComponents::setLinearDamping(Entity bodyEntity, decimal lin
}
// Set the angular damping factor of an entity
inline void RigidBodyComponents::setAngularDamping(Entity bodyEntity, decimal angularDamping) {
RP3D_FORCE_INLINE void RigidBodyComponents::setAngularDamping(Entity bodyEntity, decimal angularDamping) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -550,7 +589,7 @@ inline void RigidBodyComponents::setAngularDamping(Entity bodyEntity, decimal an
}
// Set the mass of an entity
inline void RigidBodyComponents::setMass(Entity bodyEntity, decimal mass) {
RP3D_FORCE_INLINE void RigidBodyComponents::setMass(Entity bodyEntity, decimal mass) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -558,7 +597,7 @@ inline void RigidBodyComponents::setMass(Entity bodyEntity, decimal mass) {
}
// Set the mass inverse of an entity
inline void RigidBodyComponents::setMassInverse(Entity bodyEntity, decimal inverseMass) {
RP3D_FORCE_INLINE void RigidBodyComponents::setMassInverse(Entity bodyEntity, decimal inverseMass) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -566,7 +605,7 @@ inline void RigidBodyComponents::setMassInverse(Entity bodyEntity, decimal inver
}
// Return the local inertia tensor of an entity
inline const Vector3& RigidBodyComponents::getLocalInertiaTensor(Entity bodyEntity) {
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getLocalInertiaTensor(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -574,7 +613,7 @@ inline const Vector3& RigidBodyComponents::getLocalInertiaTensor(Entity bodyEnti
}
// Set the local inertia tensor of an entity
inline void RigidBodyComponents::setLocalInertiaTensor(Entity bodyEntity, const Vector3& inertiaTensorLocal) {
RP3D_FORCE_INLINE void RigidBodyComponents::setLocalInertiaTensor(Entity bodyEntity, const Vector3& inertiaTensorLocal) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -582,7 +621,7 @@ inline void RigidBodyComponents::setLocalInertiaTensor(Entity bodyEntity, const
}
// Set the inverse local inertia tensor of an entity
inline void RigidBodyComponents::setInverseInertiaTensorLocal(Entity bodyEntity, const Vector3& inertiaTensorLocalInverse) {
RP3D_FORCE_INLINE void RigidBodyComponents::setInverseInertiaTensorLocal(Entity bodyEntity, const Vector3& inertiaTensorLocalInverse) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -590,7 +629,7 @@ inline void RigidBodyComponents::setInverseInertiaTensorLocal(Entity bodyEntity,
}
// Return the constrained linear velocity of an entity
inline const Vector3& RigidBodyComponents::getConstrainedLinearVelocity(Entity bodyEntity) const {
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getConstrainedLinearVelocity(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -598,7 +637,7 @@ inline const Vector3& RigidBodyComponents::getConstrainedLinearVelocity(Entity b
}
// Return the constrained angular velocity of an entity
inline const Vector3& RigidBodyComponents::getConstrainedAngularVelocity(Entity bodyEntity) const {
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getConstrainedAngularVelocity(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -606,7 +645,7 @@ inline const Vector3& RigidBodyComponents::getConstrainedAngularVelocity(Entity
}
// Return the split linear velocity of an entity
inline const Vector3& RigidBodyComponents::getSplitLinearVelocity(Entity bodyEntity) const {
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getSplitLinearVelocity(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -614,7 +653,7 @@ inline const Vector3& RigidBodyComponents::getSplitLinearVelocity(Entity bodyEnt
}
// Return the split angular velocity of an entity
inline const Vector3& RigidBodyComponents::getSplitAngularVelocity(Entity bodyEntity) const {
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getSplitAngularVelocity(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -622,7 +661,7 @@ inline const Vector3& RigidBodyComponents::getSplitAngularVelocity(Entity bodyEn
}
// Return the constrained position of an entity
inline Vector3& RigidBodyComponents::getConstrainedPosition(Entity bodyEntity) {
RP3D_FORCE_INLINE Vector3& RigidBodyComponents::getConstrainedPosition(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -630,7 +669,7 @@ inline Vector3& RigidBodyComponents::getConstrainedPosition(Entity bodyEntity) {
}
// Return the constrained orientation of an entity
inline Quaternion& RigidBodyComponents::getConstrainedOrientation(Entity bodyEntity) {
RP3D_FORCE_INLINE Quaternion& RigidBodyComponents::getConstrainedOrientation(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -638,7 +677,7 @@ inline Quaternion& RigidBodyComponents::getConstrainedOrientation(Entity bodyEnt
}
// Return the local center of mass of an entity
inline const Vector3& RigidBodyComponents::getCenterOfMassLocal(Entity bodyEntity) {
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getCenterOfMassLocal(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -646,7 +685,7 @@ inline const Vector3& RigidBodyComponents::getCenterOfMassLocal(Entity bodyEntit
}
// Return the world center of mass of an entity
inline const Vector3& RigidBodyComponents::getCenterOfMassWorld(Entity bodyEntity) {
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getCenterOfMassWorld(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -654,7 +693,7 @@ inline const Vector3& RigidBodyComponents::getCenterOfMassWorld(Entity bodyEntit
}
// Set the constrained linear velocity of an entity
inline void RigidBodyComponents::setConstrainedLinearVelocity(Entity bodyEntity, const Vector3& constrainedLinearVelocity) {
RP3D_FORCE_INLINE void RigidBodyComponents::setConstrainedLinearVelocity(Entity bodyEntity, const Vector3& constrainedLinearVelocity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -662,7 +701,7 @@ inline void RigidBodyComponents::setConstrainedLinearVelocity(Entity bodyEntity,
}
// Set the constrained angular velocity of an entity
inline void RigidBodyComponents::setConstrainedAngularVelocity(Entity bodyEntity, const Vector3& constrainedAngularVelocity) {
RP3D_FORCE_INLINE void RigidBodyComponents::setConstrainedAngularVelocity(Entity bodyEntity, const Vector3& constrainedAngularVelocity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -670,7 +709,7 @@ inline void RigidBodyComponents::setConstrainedAngularVelocity(Entity bodyEntity
}
// Set the split linear velocity of an entity
inline void RigidBodyComponents::setSplitLinearVelocity(Entity bodyEntity, const Vector3& splitLinearVelocity) {
RP3D_FORCE_INLINE void RigidBodyComponents::setSplitLinearVelocity(Entity bodyEntity, const Vector3& splitLinearVelocity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -678,7 +717,7 @@ inline void RigidBodyComponents::setSplitLinearVelocity(Entity bodyEntity, const
}
// Set the split angular velocity of an entity
inline void RigidBodyComponents::setSplitAngularVelocity(Entity bodyEntity, const Vector3& splitAngularVelocity) {
RP3D_FORCE_INLINE void RigidBodyComponents::setSplitAngularVelocity(Entity bodyEntity, const Vector3& splitAngularVelocity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -686,7 +725,7 @@ inline void RigidBodyComponents::setSplitAngularVelocity(Entity bodyEntity, cons
}
// Set the constrained position of an entity
inline void RigidBodyComponents::setConstrainedPosition(Entity bodyEntity, const Vector3& constrainedPosition) {
RP3D_FORCE_INLINE void RigidBodyComponents::setConstrainedPosition(Entity bodyEntity, const Vector3& constrainedPosition) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -694,7 +733,7 @@ inline void RigidBodyComponents::setConstrainedPosition(Entity bodyEntity, const
}
// Set the constrained orientation of an entity
inline void RigidBodyComponents::setConstrainedOrientation(Entity bodyEntity, const Quaternion& constrainedOrientation) {
RP3D_FORCE_INLINE void RigidBodyComponents::setConstrainedOrientation(Entity bodyEntity, const Quaternion& constrainedOrientation) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -702,7 +741,7 @@ inline void RigidBodyComponents::setConstrainedOrientation(Entity bodyEntity, co
}
// Set the local center of mass of an entity
inline void RigidBodyComponents::setCenterOfMassLocal(Entity bodyEntity, const Vector3& centerOfMassLocal) {
RP3D_FORCE_INLINE void RigidBodyComponents::setCenterOfMassLocal(Entity bodyEntity, const Vector3& centerOfMassLocal) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -710,7 +749,7 @@ inline void RigidBodyComponents::setCenterOfMassLocal(Entity bodyEntity, const V
}
// Set the world center of mass of an entity
inline void RigidBodyComponents::setCenterOfMassWorld(Entity bodyEntity, const Vector3& centerOfMassWorld) {
RP3D_FORCE_INLINE void RigidBodyComponents::setCenterOfMassWorld(Entity bodyEntity, const Vector3& centerOfMassWorld) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -718,7 +757,7 @@ inline void RigidBodyComponents::setCenterOfMassWorld(Entity bodyEntity, const V
}
// Return true if gravity is enabled for this entity
inline bool RigidBodyComponents::getIsGravityEnabled(Entity bodyEntity) const {
RP3D_FORCE_INLINE bool RigidBodyComponents::getIsGravityEnabled(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -726,15 +765,32 @@ inline bool RigidBodyComponents::getIsGravityEnabled(Entity bodyEntity) const {
}
// Return true if the entity is already in an island
inline bool RigidBodyComponents::getIsAlreadyInIsland(Entity bodyEntity) const {
RP3D_FORCE_INLINE bool RigidBodyComponents::getIsAlreadyInIsland(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
return mIsAlreadyInIsland[mMapEntityToComponentIndex[bodyEntity]];
}
// Return the linear lock axis factor
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getLinearLockAxisFactor(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
return mLinearLockAxisFactors[mMapEntityToComponentIndex[bodyEntity]];
}
// Return the angular lock axis factor
RP3D_FORCE_INLINE const Vector3& RigidBodyComponents::getAngularLockAxisFactor(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
return mAngularLockAxisFactors[mMapEntityToComponentIndex[bodyEntity]];
}
// Set the value to know if the gravity is enabled for this entity
inline void RigidBodyComponents::setIsGravityEnabled(Entity bodyEntity, bool isGravityEnabled) {
RP3D_FORCE_INLINE void RigidBodyComponents::setIsGravityEnabled(Entity bodyEntity, bool isGravityEnabled) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
@ -742,33 +798,54 @@ inline void RigidBodyComponents::setIsGravityEnabled(Entity bodyEntity, bool isG
}
// Set the value to know if the entity is already in an island
inline void RigidBodyComponents::setIsAlreadyInIsland(Entity bodyEntity, bool isAlreadyInIsland) {
RP3D_FORCE_INLINE void RigidBodyComponents::setIsAlreadyInIsland(Entity bodyEntity, bool isAlreadyInIsland) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
mIsAlreadyInIsland[mMapEntityToComponentIndex[bodyEntity]] = isAlreadyInIsland;
}
// Return the list of joints of a body
inline const List<Entity>& RigidBodyComponents::getJoints(Entity bodyEntity) const {
// Set the linear lock axis factor
RP3D_FORCE_INLINE void RigidBodyComponents::setLinearLockAxisFactor(Entity bodyEntity, const Vector3& linearLockAxisFactor) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
mLinearLockAxisFactors[mMapEntityToComponentIndex[bodyEntity]] = linearLockAxisFactor;
}
// Set the angular lock axis factor
RP3D_FORCE_INLINE void RigidBodyComponents::setAngularLockAxisFactor(Entity bodyEntity, const Vector3& angularLockAxisFactor) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
mAngularLockAxisFactors[mMapEntityToComponentIndex[bodyEntity]] = angularLockAxisFactor;
}
// Return the array of joints of a body
RP3D_FORCE_INLINE const Array<Entity>& RigidBodyComponents::getJoints(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
return mJoints[mMapEntityToComponentIndex[bodyEntity]];
}
// Add a joint to a body component
inline void RigidBodyComponents::addJointToBody(Entity bodyEntity, Entity jointEntity) {
RP3D_FORCE_INLINE void RigidBodyComponents::addJointToBody(Entity bodyEntity, Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
mJoints[mMapEntityToComponentIndex[bodyEntity]].add(jointEntity);
}
// Remove a joint from a body component
inline void RigidBodyComponents::removeJointFromBody(Entity bodyEntity, Entity jointEntity) {
RP3D_FORCE_INLINE void RigidBodyComponents::removeJointFromBody(Entity bodyEntity, Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
mJoints[mMapEntityToComponentIndex[bodyEntity]].remove(jointEntity);
}
// A an associated contact pairs into the contact pairs array of the body
RP3D_FORCE_INLINE void RigidBodyComponents::addContacPair(Entity bodyEntity, uint32 contactPairIndex) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
mContactPairs[mMapEntityToComponentIndex[bodyEntity]].add(contactPairIndex);
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -457,269 +457,270 @@ class SliderJointComponents : public Components {
friend class BroadPhaseSystem;
friend class SolveSliderJointSystem;
friend class SliderJoint;
};
// Return a pointer to a given joint
inline SliderJoint* SliderJointComponents::getJoint(Entity jointEntity) const {
RP3D_FORCE_INLINE SliderJoint* SliderJointComponents::getJoint(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mJoints[mMapEntityToComponentIndex[jointEntity]];
}
// Set the joint pointer to a given joint
inline void SliderJointComponents::setJoint(Entity jointEntity, SliderJoint* joint) const {
RP3D_FORCE_INLINE void SliderJointComponents::setJoint(Entity jointEntity, SliderJoint* joint) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mJoints[mMapEntityToComponentIndex[jointEntity]] = joint;
}
// Return the local anchor point of body 1 for a given joint
inline const Vector3& SliderJointComponents::getLocalAnchorPointBody1(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& SliderJointComponents::getLocalAnchorPointBody1(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mLocalAnchorPointBody1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the local anchor point of body 1 for a given joint
inline void SliderJointComponents::setLocalAnchorPointBody1(Entity jointEntity, const Vector3& localAnchoirPointBody1) {
RP3D_FORCE_INLINE void SliderJointComponents::setLocalAnchorPointBody1(Entity jointEntity, const Vector3& localAnchoirPointBody1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mLocalAnchorPointBody1[mMapEntityToComponentIndex[jointEntity]] = localAnchoirPointBody1;
}
// Return the local anchor point of body 2 for a given joint
inline const Vector3& SliderJointComponents::getLocalAnchorPointBody2(Entity jointEntity) const {
RP3D_FORCE_INLINE const Vector3& SliderJointComponents::getLocalAnchorPointBody2(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mLocalAnchorPointBody2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the local anchor point of body 2 for a given joint
inline void SliderJointComponents::setLocalAnchorPointBody2(Entity jointEntity, const Vector3& localAnchoirPointBody2) {
RP3D_FORCE_INLINE void SliderJointComponents::setLocalAnchorPointBody2(Entity jointEntity, const Vector3& localAnchoirPointBody2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mLocalAnchorPointBody2[mMapEntityToComponentIndex[jointEntity]] = localAnchoirPointBody2;
}
// Return the inertia tensor of body 1 (in world-space coordinates)
inline const Matrix3x3& SliderJointComponents::getI1(Entity jointEntity) const {
RP3D_FORCE_INLINE const Matrix3x3& SliderJointComponents::getI1(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mI1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the inertia tensor of body 1 (in world-space coordinates)
inline void SliderJointComponents::setI1(Entity jointEntity, const Matrix3x3& i1) {
RP3D_FORCE_INLINE void SliderJointComponents::setI1(Entity jointEntity, const Matrix3x3& i1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mI1[mMapEntityToComponentIndex[jointEntity]] = i1;
}
// Return the inertia tensor of body 2 (in world-space coordinates)
inline const Matrix3x3& SliderJointComponents::getI2(Entity jointEntity) const {
RP3D_FORCE_INLINE const Matrix3x3& SliderJointComponents::getI2(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mI2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the inertia tensor of body 2 (in world-space coordinates)
inline void SliderJointComponents::setI2(Entity jointEntity, const Matrix3x3& i2) {
RP3D_FORCE_INLINE void SliderJointComponents::setI2(Entity jointEntity, const Matrix3x3& i2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mI2[mMapEntityToComponentIndex[jointEntity]] = i2;
}
// Return the translation impulse
inline Vector2& SliderJointComponents::getImpulseTranslation(Entity jointEntity) {
RP3D_FORCE_INLINE Vector2& SliderJointComponents::getImpulseTranslation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulseTranslation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the translation impulse
inline void SliderJointComponents::setImpulseTranslation(Entity jointEntity, const Vector2& impulseTranslation) {
RP3D_FORCE_INLINE void SliderJointComponents::setImpulseTranslation(Entity jointEntity, const Vector2& impulseTranslation) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulseTranslation[mMapEntityToComponentIndex[jointEntity]] = impulseTranslation;
}
// Return the translation impulse
inline Vector3& SliderJointComponents::getImpulseRotation(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getImpulseRotation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulseRotation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the translation impulse
inline void SliderJointComponents::setImpulseRotation(Entity jointEntity, const Vector3& impulseTranslation) {
RP3D_FORCE_INLINE void SliderJointComponents::setImpulseRotation(Entity jointEntity, const Vector3& impulseTranslation) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulseRotation[mMapEntityToComponentIndex[jointEntity]] = impulseTranslation;
}
// Return the translation inverse mass matrix of the constraint
inline Matrix2x2& SliderJointComponents::getInverseMassMatrixTranslation(Entity jointEntity) {
RP3D_FORCE_INLINE Matrix2x2& SliderJointComponents::getInverseMassMatrixTranslation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInverseMassMatrixTranslation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the translation inverse mass matrix of the constraint
inline void SliderJointComponents::setInverseMassMatrixTranslation(Entity jointEntity, const Matrix2x2& inverseMassMatrix) {
RP3D_FORCE_INLINE void SliderJointComponents::setInverseMassMatrixTranslation(Entity jointEntity, const Matrix2x2& inverseMassMatrix) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInverseMassMatrixTranslation[mMapEntityToComponentIndex[jointEntity]] = inverseMassMatrix;
}
// Return the rotation inverse mass matrix of the constraint
inline Matrix3x3& SliderJointComponents::getInverseMassMatrixRotation(Entity jointEntity) {
RP3D_FORCE_INLINE Matrix3x3& SliderJointComponents::getInverseMassMatrixRotation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInverseMassMatrixRotation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the rotation inverse mass matrix of the constraint
inline void SliderJointComponents::setInverseMassMatrixRotation(Entity jointEntity, const Matrix3x3& inverseMassMatrix) {
RP3D_FORCE_INLINE void SliderJointComponents::setInverseMassMatrixRotation(Entity jointEntity, const Matrix3x3& inverseMassMatrix) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInverseMassMatrixRotation[mMapEntityToComponentIndex[jointEntity]] = inverseMassMatrix;
}
// Return the translation bias
inline Vector2& SliderJointComponents::getBiasTranslation(Entity jointEntity) {
RP3D_FORCE_INLINE Vector2& SliderJointComponents::getBiasTranslation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBiasTranslation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the translation impulse
inline void SliderJointComponents::setBiasTranslation(Entity jointEntity, const Vector2& impulseTranslation) {
RP3D_FORCE_INLINE void SliderJointComponents::setBiasTranslation(Entity jointEntity, const Vector2& impulseTranslation) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mBiasTranslation[mMapEntityToComponentIndex[jointEntity]] = impulseTranslation;
}
// Return the rotation bias
inline Vector3& SliderJointComponents::getBiasRotation(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getBiasRotation(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBiasRotation[mMapEntityToComponentIndex[jointEntity]];
}
// Set the rotation impulse
inline void SliderJointComponents::setBiasRotation(Entity jointEntity, const Vector3& impulseRotation) {
RP3D_FORCE_INLINE void SliderJointComponents::setBiasRotation(Entity jointEntity, const Vector3& impulseRotation) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mBiasRotation[mMapEntityToComponentIndex[jointEntity]] = impulseRotation;
}
// Return the initial orientation difference
inline Quaternion& SliderJointComponents::getInitOrientationDifferenceInv(Entity jointEntity) {
RP3D_FORCE_INLINE Quaternion& SliderJointComponents::getInitOrientationDifferenceInv(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInitOrientationDifferenceInv[mMapEntityToComponentIndex[jointEntity]];
}
// Set the rotation impulse
inline void SliderJointComponents::setInitOrientationDifferenceInv(Entity jointEntity, const Quaternion& initOrientationDifferenceInv) {
RP3D_FORCE_INLINE void SliderJointComponents::setInitOrientationDifferenceInv(Entity jointEntity, const Quaternion& initOrientationDifferenceInv) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInitOrientationDifferenceInv[mMapEntityToComponentIndex[jointEntity]] = initOrientationDifferenceInv;
}
// Return the slider axis (in local-space coordinates of body 1)
inline Vector3& SliderJointComponents::getSliderAxisBody1(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getSliderAxisBody1(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mSliderAxisBody1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the slider axis (in local-space coordinates of body 1)
inline void SliderJointComponents::setSliderAxisBody1(Entity jointEntity, const Vector3& sliderAxisBody1) {
RP3D_FORCE_INLINE void SliderJointComponents::setSliderAxisBody1(Entity jointEntity, const Vector3& sliderAxisBody1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mSliderAxisBody1[mMapEntityToComponentIndex[jointEntity]] = sliderAxisBody1;
}
// Retunr the slider axis in world-space coordinates
inline Vector3& SliderJointComponents::getSliderAxisWorld(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getSliderAxisWorld(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mSliderAxisWorld[mMapEntityToComponentIndex[jointEntity]];
}
// Set the slider axis in world-space coordinates
inline void SliderJointComponents::setSliderAxisWorld(Entity jointEntity, const Vector3& sliderAxisWorld) {
RP3D_FORCE_INLINE void SliderJointComponents::setSliderAxisWorld(Entity jointEntity, const Vector3& sliderAxisWorld) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mSliderAxisWorld[mMapEntityToComponentIndex[jointEntity]] = sliderAxisWorld;
}
// Return the vector r1 in world-space coordinates
inline Vector3& SliderJointComponents::getR1(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getR1(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the vector r1 in world-space coordinates
inline void SliderJointComponents::setR1(Entity jointEntity, const Vector3& r1) {
RP3D_FORCE_INLINE void SliderJointComponents::setR1(Entity jointEntity, const Vector3& r1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR1[mMapEntityToComponentIndex[jointEntity]] = r1;
}
// Return the vector r2 in world-space coordinates
inline Vector3& SliderJointComponents::getR2(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getR2(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the vector r2 in world-space coordinates
inline void SliderJointComponents::setR2(Entity jointEntity, const Vector3& r2) {
RP3D_FORCE_INLINE void SliderJointComponents::setR2(Entity jointEntity, const Vector3& r2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR2[mMapEntityToComponentIndex[jointEntity]] = r2;
}
// Return the first vector orthogonal to the slider axis local-space of body 1
inline Vector3& SliderJointComponents::getN1(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getN1(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mN1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the first vector orthogonal to the slider axis local-space of body 1
inline void SliderJointComponents::setN1(Entity jointEntity, const Vector3& n1) {
RP3D_FORCE_INLINE void SliderJointComponents::setN1(Entity jointEntity, const Vector3& n1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mN1[mMapEntityToComponentIndex[jointEntity]] = n1;
}
// Return the second vector orthogonal to the slider axis and mN1 in local-space of body 1
inline Vector3& SliderJointComponents::getN2(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getN2(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mN2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the second vector orthogonal to the slider axis and mN1 in local-space of body 1
inline void SliderJointComponents::setN2(Entity jointEntity, const Vector3& n2) {
RP3D_FORCE_INLINE void SliderJointComponents::setN2(Entity jointEntity, const Vector3& n2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mN2[mMapEntityToComponentIndex[jointEntity]] = n2;
}
// Return the accumulated impulse for the lower limit constraint
inline decimal SliderJointComponents::getImpulseLowerLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal SliderJointComponents::getImpulseLowerLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulseLowerLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the accumulated impulse for the lower limit constraint
inline void SliderJointComponents::setImpulseLowerLimit(Entity jointEntity, decimal impulseLowerLimit) {
RP3D_FORCE_INLINE void SliderJointComponents::setImpulseLowerLimit(Entity jointEntity, decimal impulseLowerLimit) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulseLowerLimit[mMapEntityToComponentIndex[jointEntity]] = impulseLowerLimit;
@ -727,14 +728,14 @@ inline void SliderJointComponents::setImpulseLowerLimit(Entity jointEntity, deci
// Return the accumulated impulse for the upper limit constraint
inline decimal SliderJointComponents::getImpulseUpperLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal SliderJointComponents::getImpulseUpperLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulseUpperLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the accumulated impulse for the upper limit constraint
inline void SliderJointComponents::setImpulseUpperLimit(Entity jointEntity, decimal impulseUpperLimit) const {
RP3D_FORCE_INLINE void SliderJointComponents::setImpulseUpperLimit(Entity jointEntity, decimal impulseUpperLimit) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulseUpperLimit[mMapEntityToComponentIndex[jointEntity]] = impulseUpperLimit;
@ -742,266 +743,266 @@ inline void SliderJointComponents::setImpulseUpperLimit(Entity jointEntity, deci
// Return the accumulated impulse for the motor constraint;
inline decimal SliderJointComponents::getImpulseMotor(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal SliderJointComponents::getImpulseMotor(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mImpulseMotor[mMapEntityToComponentIndex[jointEntity]];
}
// Set the accumulated impulse for the motor constraint;
inline void SliderJointComponents::setImpulseMotor(Entity jointEntity, decimal impulseMotor) {
RP3D_FORCE_INLINE void SliderJointComponents::setImpulseMotor(Entity jointEntity, decimal impulseMotor) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mImpulseMotor[mMapEntityToComponentIndex[jointEntity]] = impulseMotor;
}
// Return the inverse of mass matrix K=JM^-1J^t for the limits (1x1 matrix)
inline decimal SliderJointComponents::getInverseMassMatrixLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal SliderJointComponents::getInverseMassMatrixLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInverseMassMatrixLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the inverse of mass matrix K=JM^-1J^t for the limits (1x1 matrix)
inline void SliderJointComponents::setInverseMassMatrixLimit(Entity jointEntity, decimal inverseMassMatrixLimitMotor) {
RP3D_FORCE_INLINE void SliderJointComponents::setInverseMassMatrixLimit(Entity jointEntity, decimal inverseMassMatrixLimitMotor) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInverseMassMatrixLimit[mMapEntityToComponentIndex[jointEntity]] = inverseMassMatrixLimitMotor;
}
// Return the inverse of mass matrix K=JM^-1J^t for the motor
inline decimal SliderJointComponents::getInverseMassMatrixMotor(Entity jointEntity) {
RP3D_FORCE_INLINE decimal SliderJointComponents::getInverseMassMatrixMotor(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mInverseMassMatrixMotor[mMapEntityToComponentIndex[jointEntity]];
}
// Return the inverse of mass matrix K=JM^-1J^t for the motor
inline void SliderJointComponents::setInverseMassMatrixMotor(Entity jointEntity, decimal inverseMassMatrixMotor) {
RP3D_FORCE_INLINE void SliderJointComponents::setInverseMassMatrixMotor(Entity jointEntity, decimal inverseMassMatrixMotor) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mInverseMassMatrixMotor[mMapEntityToComponentIndex[jointEntity]] = inverseMassMatrixMotor;
}
// Return the bias of the lower limit constraint
inline decimal SliderJointComponents::getBLowerLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal SliderJointComponents::getBLowerLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBLowerLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the bias of the lower limit constraint
inline void SliderJointComponents::setBLowerLimit(Entity jointEntity, decimal bLowerLimit) const {
RP3D_FORCE_INLINE void SliderJointComponents::setBLowerLimit(Entity jointEntity, decimal bLowerLimit) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mBLowerLimit[mMapEntityToComponentIndex[jointEntity]] = bLowerLimit;
}
// Return the bias of the upper limit constraint
inline decimal SliderJointComponents::getBUpperLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal SliderJointComponents::getBUpperLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mBUpperLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the bias of the upper limit constraint
inline void SliderJointComponents::setBUpperLimit(Entity jointEntity, decimal bUpperLimit) {
RP3D_FORCE_INLINE void SliderJointComponents::setBUpperLimit(Entity jointEntity, decimal bUpperLimit) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mBUpperLimit[mMapEntityToComponentIndex[jointEntity]] = bUpperLimit;
}
// Return true if the joint limits are enabled
inline bool SliderJointComponents::getIsLimitEnabled(Entity jointEntity) const {
RP3D_FORCE_INLINE bool SliderJointComponents::getIsLimitEnabled(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mIsLimitEnabled[mMapEntityToComponentIndex[jointEntity]];
}
// Set to true if the joint limits are enabled
inline void SliderJointComponents::setIsLimitEnabled(Entity jointEntity, bool isLimitEnabled) {
RP3D_FORCE_INLINE void SliderJointComponents::setIsLimitEnabled(Entity jointEntity, bool isLimitEnabled) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mIsLimitEnabled[mMapEntityToComponentIndex[jointEntity]] = isLimitEnabled;
}
// Return true if the motor of the joint in enabled
inline bool SliderJointComponents::getIsMotorEnabled(Entity jointEntity) const {
RP3D_FORCE_INLINE bool SliderJointComponents::getIsMotorEnabled(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mIsMotorEnabled[mMapEntityToComponentIndex[jointEntity]];
}
// Set to true if the motor of the joint in enabled
inline void SliderJointComponents::setIsMotorEnabled(Entity jointEntity, bool isMotorEnabled) const {
RP3D_FORCE_INLINE void SliderJointComponents::setIsMotorEnabled(Entity jointEntity, bool isMotorEnabled) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mIsMotorEnabled[mMapEntityToComponentIndex[jointEntity]] = isMotorEnabled;
}
// Return the Lower limit (minimum allowed rotation angle in radian)
inline decimal SliderJointComponents::getLowerLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal SliderJointComponents::getLowerLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mLowerLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the Lower limit (minimum allowed rotation angle in radian)
inline void SliderJointComponents::setLowerLimit(Entity jointEntity, decimal lowerLimit) const {
RP3D_FORCE_INLINE void SliderJointComponents::setLowerLimit(Entity jointEntity, decimal lowerLimit) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mLowerLimit[mMapEntityToComponentIndex[jointEntity]] = lowerLimit;
}
// Return the upper limit (maximum translation distance)
inline decimal SliderJointComponents::getUpperLimit(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal SliderJointComponents::getUpperLimit(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mUpperLimit[mMapEntityToComponentIndex[jointEntity]];
}
// Set the upper limit (maximum translation distance)
inline void SliderJointComponents::setUpperLimit(Entity jointEntity, decimal upperLimit) {
RP3D_FORCE_INLINE void SliderJointComponents::setUpperLimit(Entity jointEntity, decimal upperLimit) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mUpperLimit[mMapEntityToComponentIndex[jointEntity]] = upperLimit;
}
// Return true if the lower limit is violated
inline bool SliderJointComponents::getIsLowerLimitViolated(Entity jointEntity) const {
RP3D_FORCE_INLINE bool SliderJointComponents::getIsLowerLimitViolated(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mIsLowerLimitViolated[mMapEntityToComponentIndex[jointEntity]];
}
// Set to true if the lower limit is violated
inline void SliderJointComponents::setIsLowerLimitViolated(Entity jointEntity, bool isLowerLimitViolated) {
RP3D_FORCE_INLINE void SliderJointComponents::setIsLowerLimitViolated(Entity jointEntity, bool isLowerLimitViolated) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mIsLowerLimitViolated[mMapEntityToComponentIndex[jointEntity]] = isLowerLimitViolated;
}
// Return true if the upper limit is violated
inline bool SliderJointComponents::getIsUpperLimitViolated(Entity jointEntity) const {
RP3D_FORCE_INLINE bool SliderJointComponents::getIsUpperLimitViolated(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mIsUpperLimitViolated[mMapEntityToComponentIndex[jointEntity]];
}
// Set to true if the upper limit is violated
inline void SliderJointComponents::setIsUpperLimitViolated(Entity jointEntity, bool isUpperLimitViolated) const {
RP3D_FORCE_INLINE void SliderJointComponents::setIsUpperLimitViolated(Entity jointEntity, bool isUpperLimitViolated) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mIsUpperLimitViolated[mMapEntityToComponentIndex[jointEntity]] = isUpperLimitViolated;
}
// Return the motor speed (in rad/s)
inline decimal SliderJointComponents::getMotorSpeed(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal SliderJointComponents::getMotorSpeed(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mMotorSpeed[mMapEntityToComponentIndex[jointEntity]];
}
// Set the motor speed (in rad/s)
inline void SliderJointComponents::setMotorSpeed(Entity jointEntity, decimal motorSpeed) {
RP3D_FORCE_INLINE void SliderJointComponents::setMotorSpeed(Entity jointEntity, decimal motorSpeed) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mMotorSpeed[mMapEntityToComponentIndex[jointEntity]] = motorSpeed;
}
// Return the maximum motor torque (in Newtons) that can be applied to reach to desired motor speed
inline decimal SliderJointComponents::getMaxMotorForce(Entity jointEntity) const {
RP3D_FORCE_INLINE decimal SliderJointComponents::getMaxMotorForce(Entity jointEntity) const {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mMaxMotorForce[mMapEntityToComponentIndex[jointEntity]];
}
// Set the maximum motor torque (in Newtons) that can be applied to reach to desired motor speed
inline void SliderJointComponents::setMaxMotorForce(Entity jointEntity, decimal maxMotorForce) {
RP3D_FORCE_INLINE void SliderJointComponents::setMaxMotorForce(Entity jointEntity, decimal maxMotorForce) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mMaxMotorForce[mMapEntityToComponentIndex[jointEntity]] = maxMotorForce;
}
// Return the cross product of r2 and n1
inline Vector3& SliderJointComponents::getR2CrossN1(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getR2CrossN1(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR2CrossN1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the cross product of r2 and n1
inline void SliderJointComponents::setR2CrossN1(Entity jointEntity, const Vector3& r2CrossN1) {
RP3D_FORCE_INLINE void SliderJointComponents::setR2CrossN1(Entity jointEntity, const Vector3& r2CrossN1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR2CrossN1[mMapEntityToComponentIndex[jointEntity]] = r2CrossN1;
}
// Return the cross product of r2 and n2
inline Vector3& SliderJointComponents::getR2CrossN2(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getR2CrossN2(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR2CrossN2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the cross product of r2 and n2
inline void SliderJointComponents::setR2CrossN2(Entity jointEntity, const Vector3& r2CrossN2) {
RP3D_FORCE_INLINE void SliderJointComponents::setR2CrossN2(Entity jointEntity, const Vector3& r2CrossN2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR2CrossN2[mMapEntityToComponentIndex[jointEntity]] = r2CrossN2;
}
// Return the cross product of r2 and the slider axis
inline Vector3& SliderJointComponents::getR2CrossSliderAxis(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getR2CrossSliderAxis(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR2CrossSliderAxis[mMapEntityToComponentIndex[jointEntity]];
}
// Set the cross product of r2 and the slider axis
inline void SliderJointComponents::setR2CrossSliderAxis(Entity jointEntity, const Vector3& r2CrossSliderAxis) {
RP3D_FORCE_INLINE void SliderJointComponents::setR2CrossSliderAxis(Entity jointEntity, const Vector3& r2CrossSliderAxis) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR2CrossSliderAxis[mMapEntityToComponentIndex[jointEntity]] = r2CrossSliderAxis;
}
// Return the cross product of vector (r1 + u) and n1
inline Vector3& SliderJointComponents::getR1PlusUCrossN1(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getR1PlusUCrossN1(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR1PlusUCrossN1[mMapEntityToComponentIndex[jointEntity]];
}
// Set the cross product of vector (r1 + u) and n1
inline void SliderJointComponents::setR1PlusUCrossN1(Entity jointEntity, const Vector3& r1PlusUCrossN1) {
RP3D_FORCE_INLINE void SliderJointComponents::setR1PlusUCrossN1(Entity jointEntity, const Vector3& r1PlusUCrossN1) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR1PlusUCrossN1[mMapEntityToComponentIndex[jointEntity]] = r1PlusUCrossN1;
}
// Return the cross product of vector (r1 + u) and n2
inline Vector3& SliderJointComponents::getR1PlusUCrossN2(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getR1PlusUCrossN2(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR1PlusUCrossN2[mMapEntityToComponentIndex[jointEntity]];
}
// Set the cross product of vector (r1 + u) and n2
inline void SliderJointComponents::setR1PlusUCrossN2(Entity jointEntity, const Vector3& r1PlusUCrossN2) {
RP3D_FORCE_INLINE void SliderJointComponents::setR1PlusUCrossN2(Entity jointEntity, const Vector3& r1PlusUCrossN2) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR1PlusUCrossN2[mMapEntityToComponentIndex[jointEntity]] = r1PlusUCrossN2;
}
// Return the cross product of vector (r1 + u) and the slider axis
inline Vector3& SliderJointComponents::getR1PlusUCrossSliderAxis(Entity jointEntity) {
RP3D_FORCE_INLINE Vector3& SliderJointComponents::getR1PlusUCrossSliderAxis(Entity jointEntity) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
return mR1PlusUCrossSliderAxis[mMapEntityToComponentIndex[jointEntity]];
}
// Set the cross product of vector (r1 + u) and the slider axis
inline void SliderJointComponents::setR1PlusUCrossSliderAxis(Entity jointEntity, const Vector3& r1PlusUCrossSliderAxis) {
RP3D_FORCE_INLINE void SliderJointComponents::setR1PlusUCrossSliderAxis(Entity jointEntity, const Vector3& r1PlusUCrossSliderAxis) {
assert(mMapEntityToComponentIndex.containsKey(jointEntity));
mR1PlusUCrossSliderAxis[mMapEntityToComponentIndex[jointEntity]] = r1PlusUCrossSliderAxis;

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -107,13 +107,13 @@ class TransformComponents : public Components {
};
// Return the transform of an entity
inline Transform& TransformComponents::getTransform(Entity bodyEntity) const {
RP3D_FORCE_INLINE Transform& TransformComponents::getTransform(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
return mTransforms[mMapEntityToComponentIndex[bodyEntity]];
}
// Set the transform of an entity
inline void TransformComponents::setTransform(Entity bodyEntity, const Transform& transform) {
RP3D_FORCE_INLINE void TransformComponents::setTransform(Entity bodyEntity, const Transform& transform) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
mTransforms[mMapEntityToComponentIndex[bodyEntity]] = transform;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -35,13 +35,24 @@
#include <reactphysics3d/decimal.h>
#include <reactphysics3d/containers/Pair.h>
// Windows platform
#if defined(WIN32) ||defined(_WIN32) || defined(_WIN64) ||defined(__WIN32__) || defined(__WINDOWS__)
#define WINDOWS_OS
#elif defined(__APPLE__) // Apple platform
#define APPLE_OS
#elif defined(__linux__) || defined(linux) || defined(__linux) // Linux platform
#define LINUX_OS
// Compilers
#if defined(_MSC_VER)
#define RP3D_COMPILER_VISUAL_STUDIO
#elif defined(__clang__)
#define RP3D_COMPILER_CLANG
#elif defined(__GNUC__)
#define RP3D_COMPILER_GCC
#else
#define RP3D_COMPILER_UNKNOWN
#endif
// Force RP3D_FORCE_INLINE macro
#if defined(RP3D_COMPILER_VISUAL_STUDIO)
#define RP3D_FORCE_INLINE __forceinline
#elif defined(RP3D_COMPILER_GCC) || defined(RP3D_COMPILER_CLANG)
#define RP3D_FORCE_INLINE inline __attribute__((always_inline))
#else
#define RP3D_FORCE_INLINE inline
#endif
/// Namespace reactphysics3d
@ -93,7 +104,7 @@ const decimal DECIMAL_LARGEST = std::numeric_limits<decimal>::max();
const decimal MACHINE_EPSILON = std::numeric_limits<decimal>::epsilon();
/// Pi constant
constexpr decimal PI = decimal(3.14159265);
constexpr decimal PI_RP3D = decimal(3.141592653589);
/// 2*Pi constant
constexpr decimal PI_TIMES_2 = decimal(6.28318530);
@ -103,8 +114,23 @@ constexpr decimal PI_TIMES_2 = decimal(6.28318530);
/// without triggering a large modification of the tree each frame which can be costly
constexpr decimal DYNAMIC_TREE_FAT_AABB_INFLATE_PERCENTAGE = decimal(0.08);
/// Maximum number of contact points in a narrow phase info object
constexpr uint8 NB_MAX_CONTACT_POINTS_IN_NARROWPHASE_INFO = 16;
/// Maximum number of contact manifolds in an overlapping pair
constexpr uint8 NB_MAX_CONTACT_MANIFOLDS = 3;
/// Maximum number of potential contact manifolds in an overlapping pair
constexpr uint8 NB_MAX_POTENTIAL_CONTACT_MANIFOLDS = 4 * NB_MAX_CONTACT_MANIFOLDS;
/// Maximum number of contact points in potential contact manifold
constexpr uint16 NB_MAX_CONTACT_POINTS_IN_POTENTIAL_MANIFOLD = 256;
/// Distance threshold to consider that two contact points in a manifold are the same
constexpr decimal SAME_CONTACT_POINT_DISTANCE_THRESHOLD = decimal(0.01);
/// Current version of ReactPhysics3D
const std::string RP3D_VERSION = std::string("0.8.0");
const std::string RP3D_VERSION = std::string("0.9.0");
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -43,9 +43,18 @@ struct BallAndSocketJointInfo : public JointInfo {
// -------------------- Attributes -------------------- //
/// True if this object has been constructed using local-space anchors
bool isUsingLocalSpaceAnchors;
/// Anchor point (in world-space coordinates)
Vector3 anchorPointWorldSpace;
/// Anchor point on body 1 (in local-space coordinates)
Vector3 anchorPointBody1LocalSpace;
/// Anchor point on body 2 (in local-space coordinates)
Vector3 anchorPointBody2LocalSpace;
/// Constructor
/**
* @param rigidBody1 Pointer to the first body of the joint
@ -56,7 +65,23 @@ struct BallAndSocketJointInfo : public JointInfo {
BallAndSocketJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
const Vector3& initAnchorPointWorldSpace)
: JointInfo(rigidBody1, rigidBody2, JointType::BALLSOCKETJOINT),
isUsingLocalSpaceAnchors(false),
anchorPointWorldSpace(initAnchorPointWorldSpace) {}
/// Constructor
/**
* @param rigidBody1 Pointer to the first body of the joint
* @param rigidBody2 Pointer to the second body of the joint
* @param anchorPointBody1LocalSpace The anchor point on body 1 in local-space coordinates
* @param anchorPointBody2LocalSpace The anchor point on body 2 in local-space coordinates
*/
BallAndSocketJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
const Vector3& anchorPointBody1LocalSpace,
const Vector3& anchorPointBody2LocalSpace)
: JointInfo(rigidBody1, rigidBody2, JointType::BALLSOCKETJOINT),
isUsingLocalSpaceAnchors(true),
anchorPointBody1LocalSpace(anchorPointBody1LocalSpace),
anchorPointBody2LocalSpace(anchorPointBody2LocalSpace) {}
};
// Class BallAndSocketJoint
@ -82,6 +107,8 @@ class BallAndSocketJoint : public Joint {
/// Return the number of bytes used by the joint
virtual size_t getSizeInBytes() const override;
/// Reset the limits
void resetLimits();
public :
@ -96,6 +123,27 @@ class BallAndSocketJoint : public Joint {
/// Deleted copy-constructor
BallAndSocketJoint(const BallAndSocketJoint& constraint) = delete;
/// Enable/disable the cone limit of the joint
void enableConeLimit(bool isLimitEnabled);
/// Return true if the cone limit or the joint is enabled
bool isConeLimitEnabled() const;
/// Set the cone limit half angle
void setConeLimitHalfAngle(decimal coneHalfAngle);
/// Return the cone limit half angle (in radians)
decimal getConeLimitHalfAngle() const;
/// Return the current cone half angle (in radians)
decimal getConeHalfAngle() const;
/// Return the force (in Newtons) on body 2 required to satisfy the joint constraint in world-space
virtual Vector3 getReactionForce(decimal timeStep) const override;
/// Return the torque (in Newtons * meters) on body 2 required to satisfy the joint constraint in world-space
virtual Vector3 getReactionTorque(decimal timeStep) const override;
/// Return a string representation
virtual std::string to_string() const override;
@ -104,7 +152,7 @@ class BallAndSocketJoint : public Joint {
};
// Return the number of bytes used by the joint
inline size_t BallAndSocketJoint::getSizeInBytes() const {
RP3D_FORCE_INLINE size_t BallAndSocketJoint::getSizeInBytes() const {
return sizeof(BallAndSocketJoint);
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -144,7 +144,7 @@ class ContactPoint {
/**
* @return The contact normal
*/
inline const Vector3& ContactPoint::getNormal() const {
RP3D_FORCE_INLINE const Vector3& ContactPoint::getNormal() const {
return mNormal;
}
@ -152,7 +152,7 @@ inline const Vector3& ContactPoint::getNormal() const {
/**
* @return The contact point on the first collider in the local-space of the collider
*/
inline const Vector3& ContactPoint::getLocalPointOnShape1() const {
RP3D_FORCE_INLINE const Vector3& ContactPoint::getLocalPointOnShape1() const {
return mLocalPointOnShape1;
}
@ -160,7 +160,7 @@ inline const Vector3& ContactPoint::getLocalPointOnShape1() const {
/**
* @return The contact point on the second collider in the local-space of the collider
*/
inline const Vector3& ContactPoint::getLocalPointOnShape2() const {
RP3D_FORCE_INLINE const Vector3& ContactPoint::getLocalPointOnShape2() const {
return mLocalPointOnShape2;
}
@ -168,12 +168,12 @@ inline const Vector3& ContactPoint::getLocalPointOnShape2() const {
/**
* @return The penetration impulse
*/
inline decimal ContactPoint::getPenetrationImpulse() const {
RP3D_FORCE_INLINE decimal ContactPoint::getPenetrationImpulse() const {
return mPenetrationImpulse;
}
// Return true if the contact point is similar (close enougth) to another given contact point
inline bool ContactPoint::isSimilarWithContactPoint(const ContactPointInfo* localContactPointBody1) const {
RP3D_FORCE_INLINE bool ContactPoint::isSimilarWithContactPoint(const ContactPointInfo* localContactPointBody1) const {
return (localContactPointBody1->localPoint1 - mLocalPointOnShape1).lengthSquare() <= (mPersistentContactDistanceThreshold *
mPersistentContactDistanceThreshold);
}
@ -182,7 +182,7 @@ inline bool ContactPoint::isSimilarWithContactPoint(const ContactPointInfo* loca
/**
* @param impulse Penetration impulse
*/
inline void ContactPoint::setPenetrationImpulse(decimal impulse) {
RP3D_FORCE_INLINE void ContactPoint::setPenetrationImpulse(decimal impulse) {
mPenetrationImpulse = impulse;
}
@ -190,7 +190,7 @@ inline void ContactPoint::setPenetrationImpulse(decimal impulse) {
/**
* @return True if it is a resting contact
*/
inline bool ContactPoint::getIsRestingContact() const {
RP3D_FORCE_INLINE bool ContactPoint::getIsRestingContact() const {
return mIsRestingContact;
}
@ -198,7 +198,7 @@ inline bool ContactPoint::getIsRestingContact() const {
/**
* @param isRestingContact True if it is a resting contact
*/
inline void ContactPoint::setIsRestingContact(bool isRestingContact) {
RP3D_FORCE_INLINE void ContactPoint::setIsRestingContact(bool isRestingContact) {
mIsRestingContact = isRestingContact;
}
@ -206,7 +206,7 @@ inline void ContactPoint::setIsRestingContact(bool isRestingContact) {
/**
* @return the penetration depth (in meters)
*/
inline decimal ContactPoint::getPenetrationDepth() const {
RP3D_FORCE_INLINE decimal ContactPoint::getPenetrationDepth() const {
return mPenetrationDepth;
}
@ -214,7 +214,7 @@ inline decimal ContactPoint::getPenetrationDepth() const {
/**
* @return The size of the contact point in memory (in bytes)
*/
inline size_t ContactPoint::getSizeInBytes() const {
RP3D_FORCE_INLINE size_t ContactPoint::getSizeInBytes() const {
return sizeof(ContactPoint);
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -43,9 +43,18 @@ struct FixedJointInfo : public JointInfo {
// -------------------- Attributes -------------------- //
/// True if this object has been constructed using local-space anchors
bool isUsingLocalSpaceAnchors;
/// Anchor point (in world-space coordinates)
Vector3 anchorPointWorldSpace;
/// Anchor point on body 1 (in local-space coordinates)
Vector3 anchorPointBody1LocalSpace;
/// Anchor point on body 2 (in local-space coordinates)
Vector3 anchorPointBody2LocalSpace;
/// Constructor
/**
* @param rigidBody1 The first body of the joint
@ -56,7 +65,23 @@ struct FixedJointInfo : public JointInfo {
FixedJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
const Vector3& initAnchorPointWorldSpace)
: JointInfo(rigidBody1, rigidBody2, JointType::FIXEDJOINT),
isUsingLocalSpaceAnchors(false),
anchorPointWorldSpace(initAnchorPointWorldSpace){}
/// Constructor
/**
* @param rigidBody1 Pointer to the first body of the joint
* @param rigidBody2 Pointer to the second body of the joint
* @param anchorPointBody1LocalSpace The anchor point on body 1 in local-space coordinates
* @param anchorPointBody2LocalSpace The anchor point on body 2 in local-space coordinates
*/
FixedJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
const Vector3& anchorPointBody1LocalSpace,
const Vector3& anchorPointBody2LocalSpace)
: JointInfo(rigidBody1, rigidBody2, JointType::FIXEDJOINT),
isUsingLocalSpaceAnchors(true),
anchorPointBody1LocalSpace(anchorPointBody1LocalSpace),
anchorPointBody2LocalSpace(anchorPointBody2LocalSpace) {}
};
// Class FixedJoint
@ -86,6 +111,12 @@ class FixedJoint : public Joint {
/// Deleted copy-constructor
FixedJoint(const FixedJoint& constraint) = delete;
/// Return the force (in Newtons) on body 2 required to satisfy the joint constraint in world-space
virtual Vector3 getReactionForce(decimal timeStep) const override;
/// Return the torque (in Newtons * meters) on body 2 required to satisfy the joint constraint in world-space
virtual Vector3 getReactionTorque(decimal timeStep) const override;
/// Return a string representation
virtual std::string to_string() const override;
@ -94,7 +125,7 @@ class FixedJoint : public Joint {
};
// Return the number of bytes used by the joint
inline size_t FixedJoint::getSizeInBytes() const {
RP3D_FORCE_INLINE size_t FixedJoint::getSizeInBytes() const {
return sizeof(FixedJoint);
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -43,12 +43,27 @@ struct HingeJointInfo : public JointInfo {
// -------------------- Attributes -------------------- //
/// True if this object has been constructed using local-space anchors
bool isUsingLocalSpaceAnchors;
/// Anchor point (in world-space coordinates)
Vector3 anchorPointWorldSpace;
/// Anchor point on body 1 (in local-space coordinates)
Vector3 anchorPointBody1LocalSpace;
/// Anchor point on body 2 (in local-space coordinates)
Vector3 anchorPointBody2LocalSpace;
/// Hinge rotation axis (in world-space coordinates)
Vector3 rotationAxisWorld;
/// Hinge rotation axis of body 1 (in local-space coordinates)
Vector3 rotationAxisBody1Local;
/// Hinge rotation axis of body 2 (in local-space coordinates)
Vector3 rotationAxisBody2Local;
/// True if the hinge joint limits are enabled
bool isLimitEnabled;
@ -70,7 +85,7 @@ struct HingeJointInfo : public JointInfo {
/// to desired motor speed
decimal maxMotorTorque;
/// Constructor without limits and without motor
/// Constructor without limits and without motor with world-space anchor
/**
* @param rigidBody1 The first body of the joint
* @param rigidBody2 The second body of the joint
@ -83,12 +98,13 @@ struct HingeJointInfo : public JointInfo {
const Vector3& initAnchorPointWorldSpace,
const Vector3& initRotationAxisWorld)
: JointInfo(rigidBody1, rigidBody2, JointType::HINGEJOINT),
isUsingLocalSpaceAnchors(false),
anchorPointWorldSpace(initAnchorPointWorldSpace),
rotationAxisWorld(initRotationAxisWorld), isLimitEnabled(false),
isMotorEnabled(false), minAngleLimit(-1), maxAngleLimit(1),
motorSpeed(0), maxMotorTorque(0) {}
/// Constructor with limits but without motor
/// Constructor with limits but without motor with world-space anchor
/**
* @param rigidBody1 The first body of the joint
* @param rigidBody2 The second body of the joint
@ -102,13 +118,14 @@ struct HingeJointInfo : public JointInfo {
const Vector3& initRotationAxisWorld,
decimal initMinAngleLimit, decimal initMaxAngleLimit)
: JointInfo(rigidBody1, rigidBody2, JointType::HINGEJOINT),
isUsingLocalSpaceAnchors(false),
anchorPointWorldSpace(initAnchorPointWorldSpace),
rotationAxisWorld(initRotationAxisWorld), isLimitEnabled(true),
isMotorEnabled(false), minAngleLimit(initMinAngleLimit),
maxAngleLimit(initMaxAngleLimit), motorSpeed(0),
maxMotorTorque(0) {}
/// Constructor with limits and motor
/// Constructor with limits and motor with world-space anchor
/**
* @param rigidBody1 The first body of the joint
* @param rigidBody2 The second body of the joint
@ -125,11 +142,95 @@ struct HingeJointInfo : public JointInfo {
decimal initMinAngleLimit, decimal initMaxAngleLimit,
decimal initMotorSpeed, decimal initMaxMotorTorque)
: JointInfo(rigidBody1, rigidBody2, JointType::HINGEJOINT),
isUsingLocalSpaceAnchors(false),
anchorPointWorldSpace(initAnchorPointWorldSpace),
rotationAxisWorld(initRotationAxisWorld), isLimitEnabled(true),
isMotorEnabled(false), minAngleLimit(initMinAngleLimit),
maxAngleLimit(initMaxAngleLimit), motorSpeed(initMotorSpeed),
maxMotorTorque(initMaxMotorTorque) {}
/// Constructor without limits and without motor with local-space anchors
/**
* @param rigidBody1 The first body of the joint
* @param rigidBody2 The second body of the joint
* @param anchorPointBody1Local The initial anchor point on body 1 in local-space
* @param anchorPointBody2Local The initial anchor point on body 2 in local-space
* @param rotationBody1AxisLocal The initial rotation axis on body 1 in local-space
* @param rotationBody2AxisLocal The initial rotation axis on body 2 in local-space
*/
HingeJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
const Vector3& anchorPointBody1Local,
const Vector3& anchorPointBody2Local,
const Vector3& rotationBody1AxisLocal,
const Vector3& rotationBody2AxisLocal)
: JointInfo(rigidBody1, rigidBody2, JointType::HINGEJOINT),
isUsingLocalSpaceAnchors(true),
anchorPointBody1LocalSpace(anchorPointBody1Local),
anchorPointBody2LocalSpace(anchorPointBody2Local),
rotationAxisBody1Local(rotationBody1AxisLocal),
rotationAxisBody2Local(rotationBody2AxisLocal),
isLimitEnabled(false),
isMotorEnabled(false), minAngleLimit(-1), maxAngleLimit(1),
motorSpeed(0), maxMotorTorque(0) {}
/// Constructor with limits but without motor with local-space anchors
/**
* @param rigidBody1 The first body of the joint
* @param rigidBody2 The second body of the joint
* @param anchorPointBody1Local The initial anchor point on body 1 in local-space
* @param anchorPointBody2Local The initial anchor point on body 2 in local-space
* @param rotationBody1AxisLocal The initial rotation axis on body 1 in local-space
* @param rotationBody2AxisLocal The initial rotation axis on body 2 in local-space
* @param initMinAngleLimit The initial minimum limit angle (in radian)
* @param initMaxAngleLimit The initial maximum limit angle (in radian)
*/
HingeJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
const Vector3& anchorPointBody1Local,
const Vector3& anchorPointBody2Local,
const Vector3& rotationBody1AxisLocal,
const Vector3& rotationBody2AxisLocal,
decimal initMinAngleLimit, decimal initMaxAngleLimit)
: JointInfo(rigidBody1, rigidBody2, JointType::HINGEJOINT),
isUsingLocalSpaceAnchors(true),
anchorPointBody1LocalSpace(anchorPointBody1Local),
anchorPointBody2LocalSpace(anchorPointBody2Local),
rotationAxisBody1Local(rotationBody1AxisLocal),
rotationAxisBody2Local(rotationBody2AxisLocal),
isLimitEnabled(true),
isMotorEnabled(false), minAngleLimit(initMinAngleLimit),
maxAngleLimit(initMaxAngleLimit), motorSpeed(0),
maxMotorTorque(0) {}
/// Constructor with limits and motor with local-space anchors
/**
* @param rigidBody1 The first body of the joint
* @param rigidBody2 The second body of the joint
* @param anchorPointBody1Local The initial anchor point on body 1 in local-space
* @param anchorPointBody2Local The initial anchor point on body 2 in local-space
* @param rotationBody1AxisLocal The initial rotation axis on body 1 in local-space
* @param rotationBody2AxisLocal The initial rotation axis on body 2 in local-space
* @param initMinAngleLimit The initial minimum limit angle (in radian)
* @param initMaxAngleLimit The initial maximum limit angle (in radian)
* @param initMotorSpeed The initial motor speed of the joint (in radian per second)
* @param initMaxMotorTorque The initial maximum motor torque (in Newtons)
*/
HingeJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
const Vector3& anchorPointBody1Local,
const Vector3& anchorPointBody2Local,
const Vector3& rotationBody1AxisLocal,
const Vector3& rotationBody2AxisLocal,
decimal initMinAngleLimit, decimal initMaxAngleLimit,
decimal initMotorSpeed, decimal initMaxMotorTorque)
: JointInfo(rigidBody1, rigidBody2, JointType::HINGEJOINT),
isUsingLocalSpaceAnchors(true),
anchorPointBody1LocalSpace(anchorPointBody1Local),
anchorPointBody2LocalSpace(anchorPointBody2Local),
rotationAxisBody1Local(rotationBody1AxisLocal),
rotationAxisBody2Local(rotationBody2AxisLocal),
isLimitEnabled(true),
isMotorEnabled(false), minAngleLimit(initMinAngleLimit),
maxAngleLimit(initMaxAngleLimit), motorSpeed(initMotorSpeed),
maxMotorTorque(initMaxMotorTorque) {}
};
// Class HingeJoint
@ -210,9 +311,15 @@ class HingeJoint : public Joint {
/// Return the intensity of the current torque applied for the joint motor
decimal getMotorTorque(decimal timeStep) const;
/// Return the current hinge angle
/// Return the current hinge angle (in radians)
decimal getAngle() const;
/// Return the force (in Newtons) on body 2 required to satisfy the joint constraint in world-space
virtual Vector3 getReactionForce(decimal timeStep) const override;
/// Return the torque (in Newtons * meters) on body 2 required to satisfy the joint constraint in world-space
virtual Vector3 getReactionTorque(decimal timeStep) const override;
/// Return a string representation
virtual std::string to_string() const override;
};

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -62,7 +62,7 @@ struct JointInfo {
JointType type;
/// Position correction technique used for the constraint (used for joints).
/// By default, the BAUMGARTE technique is used
/// By default, the NON_LINEAR_GAUSS_SEIDEL technique is used
JointsPositionCorrectionTechnique positionCorrectionTechnique;
/// True if the two bodies of the joint are allowed to collide with each other
@ -137,6 +137,12 @@ class Joint {
/// Return the type of the constraint
JointType getType() const;
/// Return the force (in Newtons) on body 2 required to satisfy the joint constraint
virtual Vector3 getReactionForce(decimal timeStep) const=0;
/// Return the torque (in Newtons * meters) on body 2 required to satisfy the joint constraint
virtual Vector3 getReactionTorque(decimal timeStep) const=0;
/// Return true if the collision between the two bodies of the joint is enabled
bool isCollisionEnabled() const;
@ -157,7 +163,7 @@ class Joint {
/**
* @return The entity of the joint
*/
inline Entity Joint::getEntity() const {
RP3D_FORCE_INLINE Entity Joint::getEntity() const {
return mEntity;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -47,12 +47,24 @@ struct SliderJointInfo : public JointInfo {
// -------------------- Attributes -------------------- //
/// True if this object has been constructed using local-space anchors
bool isUsingLocalSpaceAnchors;
/// Anchor point (in world-space coordinates)
Vector3 anchorPointWorldSpace;
/// Anchor point on body 1 (in local-space coordinates)
Vector3 anchorPointBody1LocalSpace;
/// Anchor point on body 2 (in local-space coordinates)
Vector3 anchorPointBody2LocalSpace;
/// Slider axis (in world-space coordinates)
Vector3 sliderAxisWorldSpace;
/// Hinge slider axis of body 1 (in local-space coordinates)
Vector3 sliderAxisBody1Local;
/// True if the slider limits are enabled
bool isLimitEnabled;
@ -71,7 +83,7 @@ struct SliderJointInfo : public JointInfo {
/// Maximum motor force (in Newtons) that can be applied to reach to desired motor speed
decimal maxMotorForce;
/// Constructor without limits and without motor
/// Constructor without limits and without motor with world-space anchor
/**
* @param rigidBody1 The first body of the joint
* @param rigidBody2 The second body of the joint
@ -82,12 +94,13 @@ struct SliderJointInfo : public JointInfo {
const Vector3& initAnchorPointWorldSpace,
const Vector3& initSliderAxisWorldSpace)
: JointInfo(rigidBody1, rigidBody2, JointType::SLIDERJOINT),
isUsingLocalSpaceAnchors(false),
anchorPointWorldSpace(initAnchorPointWorldSpace),
sliderAxisWorldSpace(initSliderAxisWorldSpace),
isLimitEnabled(false), isMotorEnabled(false), minTranslationLimit(-1.0),
maxTranslationLimit(1.0), motorSpeed(0), maxMotorForce(0) {}
/// Constructor with limits and no motor
/// Constructor with limits and no motor with world-space anchor
/**
* @param rigidBody1 The first body of the joint
* @param rigidBody2 The second body of the joint
@ -101,6 +114,7 @@ struct SliderJointInfo : public JointInfo {
const Vector3& initSliderAxisWorldSpace,
decimal initMinTranslationLimit, decimal initMaxTranslationLimit)
: JointInfo(rigidBody1, rigidBody2, JointType::SLIDERJOINT),
isUsingLocalSpaceAnchors(false),
anchorPointWorldSpace(initAnchorPointWorldSpace),
sliderAxisWorldSpace(initSliderAxisWorldSpace),
isLimitEnabled(true), isMotorEnabled(false),
@ -108,7 +122,7 @@ struct SliderJointInfo : public JointInfo {
maxTranslationLimit(initMaxTranslationLimit), motorSpeed(0),
maxMotorForce(0) {}
/// Constructor with limits and motor
/// Constructor with limits and motor with world-space anchor
/**
* @param rigidBody1 The first body of the joint
* @param rigidBody2 The second body of the joint
@ -125,12 +139,86 @@ struct SliderJointInfo : public JointInfo {
decimal initMinTranslationLimit, decimal initMaxTranslationLimit,
decimal initMotorSpeed, decimal initMaxMotorForce)
: JointInfo(rigidBody1, rigidBody2, JointType::SLIDERJOINT),
isUsingLocalSpaceAnchors(false),
anchorPointWorldSpace(initAnchorPointWorldSpace),
sliderAxisWorldSpace(initSliderAxisWorldSpace),
isLimitEnabled(true), isMotorEnabled(true),
minTranslationLimit(initMinTranslationLimit),
maxTranslationLimit(initMaxTranslationLimit), motorSpeed(initMotorSpeed),
maxMotorForce(initMaxMotorForce) {}
/// Constructor without limits and without motor with local-space anchor
/**
* @param rigidBody1 The first body of the joint
* @param rigidBody2 The second body of the joint
* @param anchorPointBody1Local The initial anchor point on body 1 in local-space
* @param anchorPointBody2Local The initial anchor point on body 2 in local-space
* @param sliderAxisBody1Local The initial slider axis in body 1 local-space
*/
SliderJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
const Vector3& anchorPointBody1Local,
const Vector3& anchorPointBody2Local,
const Vector3& sliderAxisBody1Local)
: JointInfo(rigidBody1, rigidBody2, JointType::SLIDERJOINT),
isUsingLocalSpaceAnchors(true),
anchorPointBody1LocalSpace(anchorPointBody1Local),
anchorPointBody2LocalSpace(anchorPointBody2Local),
sliderAxisBody1Local(sliderAxisBody1Local),
isLimitEnabled(false), isMotorEnabled(false), minTranslationLimit(-1.0),
maxTranslationLimit(1.0), motorSpeed(0), maxMotorForce(0) {}
/// Constructor with limits and no motor with local-space anchor
/**
* @param rigidBody1 The first body of the joint
* @param rigidBody2 The second body of the joint
* @param anchorPointBody1Local The initial anchor point on body 1 in local-space
* @param anchorPointBody2Local The initial anchor point on body 2 in local-space
* @param sliderAxisBody1Local The initial slider axis in body 1 local-space
* @param initMinTranslationLimit The initial minimum translation limit (in meters)
* @param initMaxTranslationLimit The initial maximum translation limit (in meters)
*/
SliderJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
const Vector3& anchorPointBody1Local,
const Vector3& anchorPointBody2Local,
const Vector3& sliderAxisBody1Local,
decimal initMinTranslationLimit, decimal initMaxTranslationLimit)
: JointInfo(rigidBody1, rigidBody2, JointType::SLIDERJOINT),
isUsingLocalSpaceAnchors(true),
anchorPointBody1LocalSpace(anchorPointBody1Local),
anchorPointBody2LocalSpace(anchorPointBody2Local),
sliderAxisBody1Local(sliderAxisBody1Local),
isLimitEnabled(true), isMotorEnabled(false),
minTranslationLimit(initMinTranslationLimit),
maxTranslationLimit(initMaxTranslationLimit), motorSpeed(0),
maxMotorForce(0) {}
/// Constructor with limits and motor with local-space anchor
/**
* @param rigidBody1 The first body of the joint
* @param rigidBody2 The second body of the joint
* @param anchorPointBody1Local The initial anchor point on body 1 in local-space
* @param anchorPointBody2Local The initial anchor point on body 2 in local-space
* @param sliderAxisBody1Local The initial slider axis in body 1 local-space
* @param initMinTranslationLimit The initial minimum translation limit (in meters)
* @param initMaxTranslationLimit The initial maximum translation limit (in meters)
* @param initMotorSpeed The initial speed of the joint motor (in meters per second)
* @param initMaxMotorForce The initial maximum motor force of the joint (in Newtons x meters)
*/
SliderJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
const Vector3& anchorPointBody1Local,
const Vector3& anchorPointBody2Local,
const Vector3& sliderAxisBody1Local,
decimal initMinTranslationLimit, decimal initMaxTranslationLimit,
decimal initMotorSpeed, decimal initMaxMotorForce)
: JointInfo(rigidBody1, rigidBody2, JointType::SLIDERJOINT),
isUsingLocalSpaceAnchors(true),
anchorPointBody1LocalSpace(anchorPointBody1Local),
anchorPointBody2LocalSpace(anchorPointBody2Local),
sliderAxisBody1Local(sliderAxisBody1Local),
isLimitEnabled(true), isMotorEnabled(true),
minTranslationLimit(initMinTranslationLimit),
maxTranslationLimit(initMaxTranslationLimit), motorSpeed(initMotorSpeed),
maxMotorForce(initMaxMotorForce) {}
};
// Class SliderJoint
@ -216,12 +304,18 @@ class SliderJoint : public Joint {
/// Return the intensity of the current force applied for the joint motor
decimal getMotorForce(decimal timeStep) const;
/// Return the force (in Newtons) on body 2 required to satisfy the joint constraint in world-space
virtual Vector3 getReactionForce(decimal timeStep) const override;
/// Return the torque (in Newtons * meters) on body 2 required to satisfy the joint constraint in world-space
virtual Vector3 getReactionTorque(decimal timeStep) const override;
/// Return a string representation
virtual std::string to_string() const override;
};
// Return the number of bytes used by the joint
inline size_t SliderJoint::getSizeInBytes() const {
RP3D_FORCE_INLINE size_t SliderJoint::getSizeInBytes() const {
return sizeof(SliderJoint);
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -23,8 +23,8 @@
* *
********************************************************************************/
#ifndef REACTPHYSICS3D_LIST_H
#define REACTPHYSICS3D_LIST_H
#ifndef REACTPHYSICS3D_ARRAY_H
#define REACTPHYSICS3D_ARRAY_H
// Libraries
#include <reactphysics3d/configuration.h>
@ -36,25 +36,25 @@
namespace reactphysics3d {
// Class List
// Class Array
/**
* This class represents a simple generic list with custom memory allocator.
* This class represents a simple dynamic array with custom memory allocator.
*/
template<typename T>
class List {
class Array {
private:
// -------------------- Attributes -------------------- //
/// Buffer for the list elements
void* mBuffer;
/// Buffer for the array elements
T* mBuffer;
/// Number of elements in the list
size_t mSize;
/// Number of elements in the array
uint64 mSize;
/// Number of allocated elements in the list
size_t mCapacity;
/// Number of allocated elements in the array
uint64 mCapacity;
/// Memory allocator
MemoryAllocator& mAllocator;
@ -63,15 +63,15 @@ class List {
/// Class Iterator
/**
* This class represents an iterator for the List
* This class represents an iterator for the array
*/
class Iterator {
private:
size_t mCurrentIndex;
uint64 mCurrentIndex;
T* mBuffer;
size_t mSize;
uint64 mSize;
public:
@ -88,17 +88,11 @@ class List {
Iterator() = default;
/// Constructor
Iterator(void* buffer, size_t index, size_t size)
Iterator(void* buffer, uint64 index, uint64 size)
:mCurrentIndex(index), mBuffer(static_cast<T*>(buffer)), mSize(size) {
}
/// Copy constructor
Iterator(const Iterator& it)
:mCurrentIndex(it.mCurrentIndex), mBuffer(it.mBuffer), mSize(it.mSize) {
}
/// Deferencable
reference operator*() {
assert(mCurrentIndex >= 0 && mCurrentIndex < mSize);
@ -117,30 +111,30 @@ class List {
return &(mBuffer[mCurrentIndex]);
}
/// Post increment (it++)
/// Pre increment (++it)
Iterator& operator++() {
assert(mCurrentIndex < mSize);
mCurrentIndex++;
return *this;
}
/// Pre increment (++it)
Iterator operator++(int number) {
/// Post increment (it++)
Iterator operator++(int) {
assert(mCurrentIndex < mSize);
Iterator tmp = *this;
mCurrentIndex++;
return tmp;
}
/// Post decrement (it--)
/// Pre decrement (--it)
Iterator& operator--() {
assert(mCurrentIndex > 0);
mCurrentIndex--;
return *this;
}
/// Pre decrement (--it)
Iterator operator--(int number) {
/// Post decrement (it--)
Iterator operator--(int) {
assert(mCurrentIndex > 0);
Iterator tmp = *this;
mCurrentIndex--;
@ -198,7 +192,7 @@ class List {
bool operator==(const Iterator& iterator) const {
assert(mCurrentIndex >= 0 && mCurrentIndex <= mSize);
// If both iterators points to the end of the list
// If both iterators points to the end of the array
if (mCurrentIndex == mSize && iterator.mCurrentIndex == iterator.mSize) {
return true;
}
@ -212,14 +206,14 @@ class List {
}
/// Frienship
friend class List;
friend class Array;
};
// -------------------- Methods -------------------- //
/// Constructor
List(MemoryAllocator& allocator, size_t capacity = 0)
Array(MemoryAllocator& allocator, uint64 capacity = 0)
: mBuffer(nullptr), mSize(0), mCapacity(0), mAllocator(allocator) {
if (capacity > 0) {
@ -230,43 +224,47 @@ class List {
}
/// Copy constructor
List(const List<T>& list) : mBuffer(nullptr), mSize(0), mCapacity(0), mAllocator(list.mAllocator) {
Array(const Array<T>& array) : mBuffer(nullptr), mSize(0), mCapacity(0), mAllocator(array.mAllocator) {
// All all the elements of the list to the current one
addRange(list);
// If we need to allocate more memory
if (array.mCapacity > 0) {
reserve(array.mCapacity);
}
// All all the elements of the array to the current one
addRange(array);
}
/// Destructor
~List() {
~Array() {
// If elements have been allocated
if (mCapacity > 0) {
// Clear the list
// Clear the array
clear(true);
}
}
/// Allocate memory for a given number of elements
void reserve(size_t capacity) {
void reserve(uint64 capacity) {
if (capacity <= mCapacity) return;
// Allocate memory for the new array
void* newMemory = mAllocator.allocate(capacity * sizeof(T));
T* destination = static_cast<T*>(newMemory);
if (mBuffer != nullptr) {
if (mSize > 0) {
// Copy the elements to the new allocated memory location
T* destination = static_cast<T*>(newMemory);
T* items = static_cast<T*>(mBuffer);
std::uninitialized_copy(items, items + mSize, destination);
std::uninitialized_copy(mBuffer, mBuffer + mSize, destination);
// Destruct the previous items
for (size_t i=0; i<mSize; i++) {
items[i].~T();
for (uint64 i=0; i<mSize; i++) {
mBuffer[i].~T();
}
}
@ -274,13 +272,13 @@ class List {
mAllocator.release(mBuffer, mCapacity * sizeof(T));
}
mBuffer = newMemory;
mBuffer = destination;
assert(mBuffer != nullptr);
mCapacity = capacity;
}
/// Add an element into the list
/// Add an element into the array
void add(const T& element) {
// If we need to allocate more memory
@ -288,30 +286,45 @@ class List {
reserve(mCapacity == 0 ? 1 : mCapacity * 2);
}
// Use the copy-constructor to construct the element
new (static_cast<char*>(mBuffer) + mSize * sizeof(T)) T(element);
// Use the constructor to construct the element
new (reinterpret_cast<void*>(mBuffer + mSize)) T(element);
mSize++;
}
/// Add a given numbers of elements at the end of the list but do not init them
void addWithoutInit(uint nbElements) {
/// Add an element into the array by constructing it directly into the array (in order to avoid a copy)
template<typename...Ts>
void emplace(Ts&&... args) {
// If we need to allocate more memory
if (mSize == mCapacity) {
reserve(mCapacity == 0 ? 1 : mCapacity * 2);
}
// Construct the element directly at its location in the array
new (reinterpret_cast<void*>(mBuffer + mSize)) T(std::forward<Ts>(args)...);
mSize++;
}
/// Add a given numbers of elements at the end of the array but do not init them
void addWithoutInit(uint64 nbElements) {
// If we need to allocate more memory
if ((mSize + nbElements) > mCapacity) {
reserve(mCapacity == 0 ? nbElements : (mCapacity + nbElements) * 2);
}
mSize += nbElements;
}
/// Try to find a given item of the list and return an iterator
/// pointing to that element if it exists in the list. Otherwise,
/// Try to find a given item of the array and return an iterator
/// pointing to that element if it exists in the array. Otherwise,
/// this method returns the end() iterator
Iterator find(const T& element) {
for (uint i=0; i<mSize; i++) {
if (element == static_cast<T*>(mBuffer)[i]) {
for (uint64 i=0; i<mSize; i++) {
if (element == mBuffer[i]) {
return Iterator(mBuffer, i, mSize);
}
}
@ -319,64 +332,80 @@ class List {
return end();
}
/// Look for an element in the list and remove it
/// Look for an element in the array and remove it
Iterator remove(const T& element) {
return remove(find(element));
}
/// Remove an element from the list and return a iterator
/// Remove an element from the array and return a iterator
/// pointing to the element after the removed one (or end() if none)
Iterator remove(const Iterator& it) {
assert(it.mBuffer == mBuffer);
return removeAt(it.mCurrentIndex);
}
/// Remove an element from the list at a given index (all the following items will be moved)
Iterator removeAt(uint index) {
/// Remove an element from the array at a given index (all the following items will be moved)
Iterator removeAt(uint64 index) {
assert(index >= 0 && index < mSize);
assert(index < mSize);
// Call the destructor
(static_cast<T*>(mBuffer)[index]).~T();
mBuffer[index].~T();
mSize--;
if (index != mSize) {
// Move the elements to fill in the empty slot
char* dest = static_cast<char*>(mBuffer) + index * sizeof(T);
char* src = dest + sizeof(T);
std::memmove(static_cast<void*>(dest), static_cast<void*>(src), (mSize - index) * sizeof(T));
void* dest = reinterpret_cast<void*>(mBuffer + index);
std::uintptr_t src = reinterpret_cast<std::uintptr_t>(dest) + sizeof(T);
std::memmove(dest, reinterpret_cast<const void*>(src), (mSize - index) * sizeof(T));
}
// Return an iterator pointing to the element after the removed one
return Iterator(mBuffer, index, mSize);
}
/// Append another list at the end of the current one
void addRange(const List<T>& list) {
/// Remove an element from the list at a given index and replace it by the last one of the list (if any)
void removeAtAndReplaceByLast(uint64 index) {
assert(index < mSize);
mBuffer[index] = mBuffer[mSize - 1];
// Call the destructor of the last element
mBuffer[mSize - 1].~T();
mSize--;
}
/// Remove an element from the array at a given index and replace it by the last one of the array (if any)
/// Append another array at the end of the current one
void addRange(const Array<T>& array, uint64 startIndex = 0) {
assert(startIndex <= array.size());
// If we need to allocate more memory
if (mSize + list.size() > mCapacity) {
if (mSize + (array.size() - startIndex) > mCapacity) {
// Allocate memory
reserve(mSize + list.size());
reserve(mSize + array.size() - startIndex);
}
// Add the elements of the list to the current one
for(uint i=0; i<list.size(); i++) {
// Add the elements of the array to the current one
for(uint64 i=startIndex; i<array.size(); i++) {
new (static_cast<char*>(mBuffer) + mSize * sizeof(T)) T(list[i]);
new (reinterpret_cast<void*>(mBuffer + mSize)) T(array[i]);
mSize++;
}
}
/// Clear the list
/// Clear the array
void clear(bool releaseMemory = false) {
// Call the destructor of each element
for (uint i=0; i < mSize; i++) {
(static_cast<T*>(mBuffer)[i]).~T();
for (uint64 i=0; i < mSize; i++) {
mBuffer[i].~T();
}
mSize = 0;
@ -392,36 +421,35 @@ class List {
}
}
/// Return the number of elements in the list
size_t size() const {
/// Return the number of elements in the array
uint64 size() const {
return mSize;
}
/// Return the capacity of the list
size_t capacity() const {
/// Return the capacity of the array
uint64 capacity() const {
return mCapacity;
}
/// Overloaded index operator
T& operator[](const uint index) {
T& operator[](const uint64 index) {
assert(index >= 0 && index < mSize);
return (static_cast<T*>(mBuffer)[index]);
return mBuffer[index];
}
/// Overloaded const index operator
const T& operator[](const uint index) const {
const T& operator[](const uint64 index) const {
assert(index >= 0 && index < mSize);
return (static_cast<T*>(mBuffer)[index]);
return mBuffer[index];
}
/// Overloaded equality operator
bool operator==(const List<T>& list) const {
bool operator==(const Array<T>& array) const {
if (mSize != list.mSize) return false;
if (mSize != array.mSize) return false;
T* items = static_cast<T*>(mBuffer);
for (size_t i=0; i < mSize; i++) {
if (items[i] != list[i]) {
for (uint64 i=0; i < mSize; i++) {
if (mBuffer[i] != array[i]) {
return false;
}
}
@ -430,21 +458,21 @@ class List {
}
/// Overloaded not equal operator
bool operator!=(const List<T>& list) const {
bool operator!=(const Array<T>& array) const {
return !((*this) == list);
return !((*this) == array);
}
/// Overloaded assignment operator
List<T>& operator=(const List<T>& list) {
Array<T>& operator=(const Array<T>& array) {
if (this != &list) {
if (this != &array) {
// Clear all the elements
clear();
// Add all the elements of the list to the current one
addRange(list);
// Add all the elements of the array to the current one
addRange(array);
}
return *this;

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -55,10 +55,10 @@ class Deque {
// -------------------- Constants -------------------- //
/// Number of items in a chunk
const uint CHUNK_NB_ITEMS = 17;
const uint8 CHUNK_NB_ITEMS = 17;
/// First item index in a chunk
const uint CHUNK_FIRST_ITEM_INDEX = CHUNK_NB_ITEMS / 2;
const uint8 CHUNK_FIRST_ITEM_INDEX = CHUNK_NB_ITEMS / 2;
// -------------------- Attributes -------------------- //
@ -66,16 +66,16 @@ class Deque {
T** mChunks;
/// Number of current elements in the deque
size_t mSize;
uint64 mSize;
/// Number of chunks
size_t mNbChunks;
uint64 mNbChunks;
/// Index of the chunk with the first element of the deque
size_t mFirstChunkIndex;
uint64 mFirstChunkIndex;
/// Index of the chunk with the last element of the deque
size_t mLastChunkIndex;
uint64 mLastChunkIndex;
/// Index of the first element in the first chunk
uint8 mFirstItemIndex;
@ -89,15 +89,15 @@ class Deque {
// -------------------- Methods -------------------- //
/// Return a reference to an item at the given virtual index in range [0; mSize-1]
T& getItem(size_t virtualIndex) const {
T& getItem(uint64 virtualIndex) const {
// If the virtual index is valid
if (virtualIndex < mSize) {
size_t chunkIndex = mFirstChunkIndex;
size_t itemIndex = mFirstItemIndex;
uint64 chunkIndex = mFirstChunkIndex;
uint64 itemIndex = mFirstItemIndex;
const size_t nbItemsFirstChunk = CHUNK_NB_ITEMS - mFirstItemIndex;
const uint64 nbItemsFirstChunk = CHUNK_NB_ITEMS - mFirstItemIndex;
if (virtualIndex < nbItemsFirstChunk) {
itemIndex += virtualIndex;
}
@ -118,18 +118,18 @@ class Deque {
}
/// Add more chunks
void expandChunks(size_t atLeastNbChunks = 0) {
void expandChunks(uint64 atLeastNbChunks = 0) {
// If it is not necessary to expand the chunks
if (atLeastNbChunks > 0 && atLeastNbChunks <= mNbChunks) {
return;
}
size_t newNbChunks = mNbChunks == 0 ? 3 : 2 * mNbChunks - 1;
uint64 newNbChunks = mNbChunks == 0 ? 3 : 2 * mNbChunks - 1;
if (atLeastNbChunks > 0 && newNbChunks < atLeastNbChunks) {
newNbChunks = size_t(atLeastNbChunks / 2) * 2 + 1;
newNbChunks = uint64(atLeastNbChunks / 2) * 2 + 1;
}
const size_t halfNbChunksToAdd = mNbChunks == 0 ? 1 : (mNbChunks - 1) / 2;
const uint64 halfNbChunksToAdd = mNbChunks == 0 ? 1 : (mNbChunks - 1) / 2;
// Allocate memory for the new array of pointers to chunk
void* newMemory = mAllocator.allocate(newNbChunks * sizeof(T*));
@ -157,7 +157,7 @@ class Deque {
mNbChunks = newNbChunks;
// Allocate memory for each new chunk
for (size_t i=0; i < halfNbChunksToAdd; i++) {
for (uint64 i=0; i < halfNbChunksToAdd; i++) {
// Allocate memory for the new chunk
mChunks[i] = static_cast<T*>(mAllocator.allocate(sizeof(T) * CHUNK_NB_ITEMS));
@ -182,7 +182,7 @@ class Deque {
private:
size_t mVirtualIndex;
uint64 mVirtualIndex;
const Deque<T>* mDeque;
public:
@ -197,15 +197,7 @@ class Deque {
using iterator_category = std::random_access_iterator_tag;
/// Constructor
Iterator() = default;
/// Constructor
Iterator(const Deque<T>* deque, size_t virtualIndex) : mVirtualIndex(virtualIndex), mDeque(deque) {
}
/// Copy constructor
Iterator(const Iterator& it) : mVirtualIndex(it.mVirtualIndex), mDeque(it.mDeque) {
Iterator(const Deque<T>* deque, uint64 virtualIndex) : mVirtualIndex(virtualIndex), mDeque(deque) {
}
@ -227,29 +219,29 @@ class Deque {
return &(mDeque->getItem(mVirtualIndex));
}
/// Post increment (it++)
/// Pre increment (++it)
Iterator& operator++() {
assert(mVirtualIndex < mDeque->mSize);
mVirtualIndex++;
return *this;
}
/// Pre increment (++it)
Iterator operator++(int number) {
/// Post increment (it++)
Iterator operator++(int /*number*/) {
assert(mVirtualIndex < mDeque->mSize);
Iterator tmp = *this;
mVirtualIndex++;
return tmp;
}
/// Post decrement (it--)
/// Pre decrement (--it)
Iterator& operator--() {
mVirtualIndex--;
return *this;
}
/// Pre decrement (--it)
Iterator operator--(int number) {
/// Post decrement (it--)
Iterator operator--(int /*number*/) {
Iterator tmp = *this;
mVirtualIndex--;
return tmp;
@ -345,14 +337,14 @@ class Deque {
if (deque.mSize > 0) {
const size_t dequeHalfSize1 = std::ceil(deque.mSize / 2.0f);
const size_t dequeHalfSize2 = deque.mSize - dequeHalfSize1;
const uint64 dequeHalfSize1 = std::ceil(deque.mSize / 2.0f);
const uint64 dequeHalfSize2 = deque.mSize - dequeHalfSize1;
// Add the items into the deque
for(size_t i=0; i < dequeHalfSize1; i++) {
for(uint64 i=0; i < dequeHalfSize1; i++) {
addFront(deque[dequeHalfSize1 - 1 - i]);
}
for(size_t i=0; i < dequeHalfSize2; i++) {
for(uint64 i=0; i < dequeHalfSize2; i++) {
addBack(deque[dequeHalfSize1 + i]);
}
}
@ -364,7 +356,7 @@ class Deque {
clear();
// Release each chunk
for (size_t i=0; i < mNbChunks; i++) {
for (uint64 i=0; i < mNbChunks; i++) {
mAllocator.release(mChunks[i], sizeof(T) * CHUNK_NB_ITEMS);
}
@ -499,18 +491,14 @@ class Deque {
/// Return a reference to the first item of the deque
const T& getFront() const {
if (mSize > 0) {
return mChunks[mFirstChunkIndex][mFirstItemIndex];
}
assert(false);
assert(mSize > 0);
return mChunks[mFirstChunkIndex][mFirstItemIndex];
}
/// Return a reference to the last item of the deque
const T& getBack() const {
if (mSize > 0) {
return mChunks[mLastChunkIndex][mLastItemIndex];
}
assert(false);
assert(mSize > 0);
return mChunks[mLastChunkIndex][mLastItemIndex];
}
/// Clear the elements of the deque
@ -519,7 +507,7 @@ class Deque {
if (mSize > 0) {
// Call the destructor of every items
for (size_t i=0; i < mSize; i++) {
for (uint64 i=0; i < mSize; i++) {
getItem(i).~T();
}
@ -533,18 +521,18 @@ class Deque {
}
/// Return the number of elements in the deque
size_t size() const {
uint64 size() const {
return mSize;
}
/// Overloaded index operator
T& operator[](const uint index) {
T& operator[](const uint64 index) {
assert(index < mSize);
return getItem(index);
}
/// Overloaded const index operator
const T& operator[](const uint index) const {
const T& operator[](const uint64 index) const {
assert(index < mSize);
return getItem(index);
}
@ -554,7 +542,7 @@ class Deque {
if (mSize != deque.mSize) return false;
for (size_t i=0; i < mSize; i++) {
for (uint64 i=0; i < mSize; i++) {
if (getItem(i) != deque.getItem(i)) {
return false;
}
@ -580,19 +568,19 @@ class Deque {
if (deque.mSize > 0) {
// Number of used chunks
const size_t nbUsedChunks = deque.mLastChunkIndex - deque.mFirstChunkIndex + 1;
const uint64 nbUsedChunks = deque.mLastChunkIndex - deque.mFirstChunkIndex + 1;
// Expand the chunk if necessary
expandChunks(nbUsedChunks);
const size_t dequeHalfSize1 = std::ceil(deque.mSize / 2.0f);
const size_t dequeHalfSize2 = deque.mSize - dequeHalfSize1;
const uint64 dequeHalfSize1 = std::ceil(deque.mSize / 2.0f);
const uint64 dequeHalfSize2 = deque.mSize - dequeHalfSize1;
// Add the items into the deque
for(size_t i=0; i < dequeHalfSize1; i++) {
for(uint64 i=0; i < dequeHalfSize1; i++) {
addFront(deque[dequeHalfSize1 - 1 - i]);
}
for(size_t i=0; i < dequeHalfSize2; i++) {
for(uint64 i=0; i < dequeHalfSize2; i++) {
addBack(deque[dequeHalfSize1 + i]);
}
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -93,20 +93,20 @@ class LinkedList {
// Return the first element of the list
template<typename T>
inline typename LinkedList<T>::ListElement* LinkedList<T>::getListHead() const {
RP3D_FORCE_INLINE typename LinkedList<T>::ListElement* LinkedList<T>::getListHead() const {
return mListHead;
}
// Insert an element at the beginning of the linked list
template<typename T>
inline void LinkedList<T>::insert(const T& data) {
RP3D_FORCE_INLINE void LinkedList<T>::insert(const T& data) {
ListElement* element = new (mAllocator.allocate(sizeof(ListElement))) ListElement(data, mListHead);
mListHead = element;
}
// Remove all the elements of the list
template<typename T>
inline void LinkedList<T>::reset() {
RP3D_FORCE_INLINE void LinkedList<T>::reset() {
// Release all the list elements
ListElement* element = mListHead;

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -59,14 +59,6 @@ class Pair {
}
/// Copy constructor
Pair(const Pair<T1, T2>& pair) : first(pair.first), second(pair.second) {
}
/// Destructor
~Pair() = default;
/// Overloaded equality operator
bool operator==(const Pair<T1, T2>& pair) const {
return first == pair.first && second == pair.second;
@ -76,13 +68,6 @@ class Pair {
bool operator!=(const Pair<T1, T2>& pair) const {
return !((*this) == pair);
}
/// Overloaded assignment operator
Pair<T1, T2>& operator=(const Pair<T1, T2>& pair) {
first = pair.first;
second = pair.second;
return *this;
}
};
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -34,7 +34,6 @@
#include <functional>
#include <limits>
namespace reactphysics3d {
// Class Set
@ -47,197 +46,60 @@ class Set {
private:
/// An entry of the set
struct Entry {
size_t hashCode; // Hash code of the entry
int next; // Index of the next entry
V* value; // Pointer to the value stored in the entry
/// Constructor
Entry() {
next = -1;
value = nullptr;
}
/// Constructor
Entry(size_t hashcode, int nextEntry) {
hashCode = hashcode;
next = nextEntry;
value = nullptr;
}
/// Copy-constructor
Entry(const Entry& entry) {
hashCode = entry.hashCode;
next = entry.next;
value = entry.value;
}
/// Destructor
~Entry() {
}
};
// -------------------- Constants -------------------- //
/// Number of prime numbers in array
static constexpr int NB_PRIMES = 70;
/// Default load factor
static constexpr float DEFAULT_LOAD_FACTOR = 0.75;
/// Array of prime numbers for the size of the set
static const int PRIMES[NB_PRIMES];
/// Largest prime number
static int LARGEST_PRIME;
/// Invalid index in the array
static constexpr uint64 INVALID_INDEX = -1;
// -------------------- Attributes -------------------- //
/// Current number of used entries in the set
int mNbUsedEntries;
/// Total number of allocated entries
uint64 mNbAllocatedEntries;
/// Number of free entries among the used ones
int mNbFreeEntries;
/// Number of items in the set
uint64 mNbEntries;
/// Current capacity of the set
int mCapacity;
/// Number of buckets and size of the hash table (nbEntries = loadFactor * mHashSize)
uint64 mHashSize ;
/// Array with all the buckets
int* mBuckets;
uint64* mBuckets;
/// Array with all the entries
Entry* mEntries;
/// Array with all the entries (nbEntries = loadFactor * mHashSize)
V* mEntries;
/// For each entry, index of the next entry at the same bucket
uint64* mNextEntries;
/// Memory allocator
MemoryAllocator& mAllocator;
/// Index to the fist free entry
int mFreeIndex;
uint64 mFreeIndex;
// -------------------- Methods -------------------- //
/// Initialize the set
void initialize(int capacity) {
// Compute the next larger prime size
mCapacity = getPrimeSize(capacity);
// Allocate memory for the buckets
mBuckets = static_cast<int*>(mAllocator.allocate(mCapacity * sizeof(int)));
// Allocate memory for the entries
mEntries = static_cast<Entry*>(mAllocator.allocate(mCapacity * sizeof(Entry)));
// Initialize the buckets and entries
for (int i=0; i<mCapacity; i++) {
mBuckets[i] = -1;
// Construct the entry
new (&mEntries[i]) Entry();
}
mNbUsedEntries = 0;
mNbFreeEntries = 0;
mFreeIndex = -1;
}
/// Expand the capacity of the set
void expand(int newCapacity) {
assert(newCapacity > mCapacity);
assert(isPrimeNumber(newCapacity));
// Allocate memory for the buckets
int* newBuckets = static_cast<int*>(mAllocator.allocate(newCapacity * sizeof(int)));
// Allocate memory for the entries
Entry* newEntries = static_cast<Entry*>(mAllocator.allocate(newCapacity * sizeof(Entry)));
// Initialize the new buckets
for (int i=0; i<newCapacity; i++) {
newBuckets[i] = -1;
}
if (mNbUsedEntries > 0) {
// Copy the old entries to the new allocated memory location
std::uninitialized_copy(mEntries, mEntries + mNbUsedEntries, newEntries);
// Destruct the old entries at previous location
for (int i=0; i<mNbUsedEntries; i++) {
mEntries[i].~Entry();
}
}
// Construct the new entries
for (int i=mNbUsedEntries; i<newCapacity; i++) {
// Construct the entry
new (static_cast<void*>(&newEntries[i])) Entry();
}
// For each used entry
for (int i=0; i<mNbUsedEntries; i++) {
// If the entry is not free
if (newEntries[i].value != nullptr) {
// Get the corresponding bucket
int bucket = newEntries[i].hashCode % newCapacity;
newEntries[i].next = newBuckets[bucket];
newBuckets[bucket] = i;
}
}
// Release previously allocated memory
mAllocator.release(mBuckets, mCapacity * sizeof(int));
mAllocator.release(mEntries, mCapacity * sizeof(Entry));
mCapacity = newCapacity;
mBuckets = newBuckets;
mEntries = newEntries;
}
/// Return the index of the entry with a given value or -1 if there is no entry with this value
int findEntry(const V& value) const {
uint64 findEntry(const V& value) const {
if (mCapacity > 0) {
if (mHashSize > 0) {
size_t hashCode = Hash()(value);
int bucket = hashCode % mCapacity;
auto keyEqual = KeyEqual();
const size_t hashCode = Hash()(value);
const size_t divider = mHashSize - 1;
const uint64 bucket = static_cast<uint64>(hashCode & divider);
auto keyEqual = KeyEqual();
for (int i = mBuckets[bucket]; i >= 0; i = mEntries[i].next) {
if (mEntries[i].hashCode == hashCode && keyEqual(*mEntries[i].value, value)) {
for (uint64 i = mBuckets[bucket]; i != INVALID_INDEX; i = mNextEntries[i]) {
if (Hash()(mEntries[i]) == hashCode && keyEqual(mEntries[i], value)) {
return i;
}
}
}
return -1;
}
/// Return the prime number that is larger or equal to the number in parameter
/// for the size of the set
static int getPrimeSize(int number) {
// Check if the next larger prime number is in the precomputed array of primes
for (int i = 0; i < NB_PRIMES; i++) {
if (PRIMES[i] >= number) return PRIMES[i];
}
// Manually compute the next larger prime number
for (int i = (number | 1); i < std::numeric_limits<int>::max(); i+=2) {
if (isPrimeNumber(i)) {
return i;
}
}
return number;
return INVALID_INDEX;
}
public:
@ -250,36 +112,36 @@ class Set {
private:
/// Array of entries
const Entry* mEntries;
/// Pointer to the set
const Set* mSet;
/// Capacity of the map
int mCapacity;
/// Number of used entries in the map
int mNbUsedEntries;
/// Index of the current bucket
uint64 mCurrentBucketIndex;
/// Index of the current entry
int mCurrentEntry;
uint64 mCurrentEntryIndex;
/// Advance the iterator
void advance() {
// If we are trying to move past the end
assert(mCurrentEntry < mNbUsedEntries);
assert(mCurrentBucketIndex < mSet->mHashSize);
assert(mCurrentEntryIndex < mSet->mNbAllocatedEntries);
for (mCurrentEntry += 1; mCurrentEntry < mNbUsedEntries; mCurrentEntry++) {
// If the entry is not empty
if (mEntries[mCurrentEntry].value != nullptr) {
// We have found the next non empty entry
return;
}
// Try the next entry
if (mSet->mNextEntries[mCurrentEntryIndex] != INVALID_INDEX) {
mCurrentEntryIndex = mSet->mNextEntries[mCurrentEntryIndex];
return;
}
// We have not find a non empty entry, we return an iterator to the end
mCurrentEntry = mCapacity;
// Try to move to the next bucket
mCurrentEntryIndex = 0;
mCurrentBucketIndex++;
while(mCurrentBucketIndex < mSet->mHashSize && mSet->mBuckets[mCurrentBucketIndex] == INVALID_INDEX) {
mCurrentBucketIndex++;
}
if (mCurrentBucketIndex < mSet->mHashSize) {
mCurrentEntryIndex = mSet->mBuckets[mCurrentBucketIndex];
}
}
public:
@ -295,38 +157,32 @@ class Set {
Iterator() = default;
/// Constructor
Iterator(const Entry* entries, int capacity, int nbUsedEntries, int currentEntry)
:mEntries(entries), mCapacity(capacity), mNbUsedEntries(nbUsedEntries), mCurrentEntry(currentEntry) {
}
/// Copy constructor
Iterator(const Iterator& it)
:mEntries(it.mEntries), mCapacity(it.mCapacity), mNbUsedEntries(it.mNbUsedEntries), mCurrentEntry(it.mCurrentEntry) {
Iterator(const Set* set, uint64 bucketIndex, uint64 entryIndex)
:mSet(set), mCurrentBucketIndex(bucketIndex), mCurrentEntryIndex(entryIndex) {
}
/// Deferencable
reference operator*() const {
assert(mCurrentEntry >= 0 && mCurrentEntry < mNbUsedEntries);
assert(mEntries[mCurrentEntry].value != nullptr);
return *(mEntries[mCurrentEntry].value);
assert(mCurrentEntryIndex < mSet->mNbAllocatedEntries);
assert(mCurrentEntryIndex != INVALID_INDEX);
return mSet->mEntries[mCurrentEntryIndex];
}
/// Deferencable
pointer operator->() const {
assert(mCurrentEntry >= 0 && mCurrentEntry < mNbUsedEntries);
assert(mEntries[mCurrentEntry].value != nullptr);
return mEntries[mCurrentEntry].value;
assert(mCurrentEntryIndex < mSet->mNbAllocatedEntries);
assert(mCurrentEntryIndex != INVALID_INDEX);
return &(mSet->mEntries[mCurrentEntryIndex]);
}
/// Post increment (it++)
/// Pre increment (++it)
Iterator& operator++() {
advance();
return *this;
}
/// Pre increment (++it)
/// Post increment (it++)
Iterator operator++(int) {
Iterator tmp = *this;
advance();
@ -335,7 +191,7 @@ class Set {
/// Equality operator (it == end())
bool operator==(const Iterator& iterator) const {
return mCurrentEntry == iterator.mCurrentEntry && mEntries == iterator.mEntries;
return mCurrentBucketIndex == iterator.mCurrentBucketIndex && mCurrentEntryIndex == iterator.mCurrentEntryIndex && mSet == iterator.mSet;
}
/// Inequality operator (it != end())
@ -348,47 +204,46 @@ class Set {
// -------------------- Methods -------------------- //
/// Constructor
Set(MemoryAllocator& allocator, size_t capacity = 0)
: mNbUsedEntries(0), mNbFreeEntries(0), mCapacity(0), mBuckets(nullptr),
mEntries(nullptr), mAllocator(allocator), mFreeIndex(-1) {
// If the largest prime has not been computed yet
if (LARGEST_PRIME == -1) {
// Compute the largest prime number (largest map capacity)
LARGEST_PRIME = getPrimeSize(PRIMES[NB_PRIMES - 1] + 2);
}
Set(MemoryAllocator& allocator, uint64 capacity = 0)
: mNbAllocatedEntries(0), mNbEntries(0), mHashSize(0), mBuckets(nullptr),
mEntries(nullptr), mNextEntries(nullptr), mAllocator(allocator), mFreeIndex(INVALID_INDEX) {
if (capacity > 0) {
initialize(capacity);
reserve(capacity);
}
}
/// Copy constructor
Set(const Set<V, Hash, KeyEqual>& set)
:mNbUsedEntries(set.mNbUsedEntries), mNbFreeEntries(set.mNbFreeEntries), mCapacity(set.mCapacity),
mBuckets(nullptr), mEntries(nullptr), mAllocator(set.mAllocator), mFreeIndex(set.mFreeIndex) {
:mNbAllocatedEntries(set.mNbAllocatedEntries), mNbEntries(set.mNbEntries), mHashSize(set.mHashSize),
mBuckets(nullptr), mEntries(nullptr), mNextEntries(nullptr), mAllocator(set.mAllocator), mFreeIndex(set.mFreeIndex) {
if (mCapacity > 0) {
if (mHashSize > 0) {
// Allocate memory for the buckets
mBuckets = static_cast<int*>(mAllocator.allocate(mCapacity * sizeof(int)));
mBuckets = static_cast<uint64*>(mAllocator.allocate(mHashSize * sizeof(uint64)));
// Allocate memory for the entries
mEntries = static_cast<Entry*>(mAllocator.allocate(mCapacity * sizeof(Entry)));
mEntries = static_cast<V*>(mAllocator.allocate(mNbAllocatedEntries * sizeof(V)));
mNextEntries = static_cast<uint64*>(mAllocator.allocate(mNbAllocatedEntries * sizeof(uint64)));
// Copy the buckets
std::uninitialized_copy(set.mBuckets, set.mBuckets + mCapacity, mBuckets);
// Copy the buckets array
std::memcpy(mBuckets, set.mBuckets, mHashSize * sizeof(uint64));
// Copy the next entries indices
std::memcpy(mNextEntries, set.mNextEntries, mNbAllocatedEntries * sizeof(uint64));
// Copy the entries
for (int i=0; i < mCapacity; i++) {
for (uint64 i=0; i<mHashSize; i++) {
new (&mEntries[i]) Entry(set.mEntries[i].hashCode, set.mEntries[i].next);
uint64 entryIndex = mBuckets[i];
while(entryIndex != INVALID_INDEX) {
if (set.mEntries[i].value != nullptr) {
mEntries[i].value = static_cast<V*>(mAllocator.allocate(sizeof(V)));
new (mEntries[i].value) V(*(set.mEntries[i].value));
// Copy the entry to the new location and destroy the previous one
new (mEntries + entryIndex) V(set.mEntries[entryIndex]);
entryIndex = mNextEntries[entryIndex];
}
}
}
@ -401,82 +256,151 @@ class Set {
}
/// Allocate memory for a given number of elements
void reserve(int capacity) {
void reserve(uint64 capacity) {
if (capacity <= mCapacity) return;
if (capacity <= mHashSize) return;
if (capacity > LARGEST_PRIME && LARGEST_PRIME > mCapacity) {
capacity = LARGEST_PRIME;
}
else {
capacity = getPrimeSize(capacity);
}
if (capacity < 16) capacity = 16;
expand(capacity);
// Make sure we have a power of two size
if (!isPowerOfTwo(capacity)) {
capacity = nextPowerOfTwo64Bits(capacity);
}
assert(capacity < INVALID_INDEX);
assert(capacity > mHashSize);
// Allocate memory for the buckets
uint64* newBuckets = static_cast<uint64*>(mAllocator.allocate(capacity * sizeof(uint64)));
// Allocate memory for the entries
const uint64 nbAllocatedEntries = static_cast<uint64>(capacity * double(DEFAULT_LOAD_FACTOR));
assert(nbAllocatedEntries > 0);
V* newEntries = static_cast<V*>(mAllocator.allocate(nbAllocatedEntries * sizeof(V)));
uint64* newNextEntries = static_cast<uint64*>(mAllocator.allocate(nbAllocatedEntries * sizeof(uint64)));
assert(newEntries != nullptr);
assert(newNextEntries != nullptr);
// Initialize the new buckets
for (uint64 i=0; i<capacity; i++) {
newBuckets[i] = INVALID_INDEX;
}
if (mNbAllocatedEntries > 0) {
assert(mNextEntries != nullptr);
// Copy the free nodes indices in the nextEntries array
std::memcpy(newNextEntries, mNextEntries, mNbAllocatedEntries * sizeof(uint64));
}
// Recompute the buckets (hash) with the new hash size
for (uint64 i=0; i<mHashSize; i++) {
uint64 entryIndex = mBuckets[i];
while(entryIndex != INVALID_INDEX) {
// Get the corresponding bucket
const size_t hashCode = Hash()(mEntries[entryIndex]);
const size_t divider = capacity - 1;
const uint64 bucketIndex = static_cast<uint64>(hashCode & divider);
newNextEntries[entryIndex] = newBuckets[bucketIndex];
newBuckets[bucketIndex] = entryIndex;
// Copy the entry to the new location and destroy the previous one
new (newEntries + entryIndex) V(mEntries[entryIndex]);
mEntries[entryIndex].~V();
entryIndex = mNextEntries[entryIndex];
}
}
if (mNbAllocatedEntries > 0) {
// Release previously allocated memory
mAllocator.release(mBuckets, mHashSize * sizeof(uint64));
mAllocator.release(mEntries, mNbAllocatedEntries * sizeof(V));
mAllocator.release(mNextEntries, mNbAllocatedEntries * sizeof(uint64));
}
// Add the new entries to the free list
for (uint64 i=mNbAllocatedEntries; i < nbAllocatedEntries-1; i++) {
newNextEntries[i] = i + 1;
}
newNextEntries[nbAllocatedEntries - 1] = mFreeIndex;
mFreeIndex = mNbAllocatedEntries;
mHashSize = capacity;
mNbAllocatedEntries = nbAllocatedEntries;
mBuckets = newBuckets;
mEntries = newEntries;
mNextEntries = newNextEntries;
assert(mFreeIndex != INVALID_INDEX);
}
/// Return true if the set contains a given value
bool contains(const V& value) const {
return findEntry(value) != -1;
return findEntry(value) != INVALID_INDEX;
}
/// Add a value into the set.
/// Returns true if the item has been inserted and false otherwise.
bool add(const V& value) {
if (mCapacity == 0) {
initialize(0);
}
uint64 bucket = INVALID_INDEX;
// Compute the hash code of the value
size_t hashCode = Hash()(value);
const size_t hashCode = Hash()(value);
// Compute the corresponding bucket index
int bucket = hashCode % mCapacity;
if (mHashSize > 0) {
auto keyEqual = KeyEqual();
// Compute the corresponding bucket index
const size_t divider = mHashSize - 1;
bucket = static_cast<uint64>(hashCode & divider);
// Check if the item is already in the set
for (int i = mBuckets[bucket]; i >= 0; i = mEntries[i].next) {
auto keyEqual = KeyEqual();
// If there is already an item with the same value in the set
if (mEntries[i].hashCode == hashCode && keyEqual(*mEntries[i].value, value)) {
// Check if the item is already in the set
for (uint64 i = mBuckets[bucket]; i != INVALID_INDEX; i = mNextEntries[i]) {
return false;
// If there is already an item with the same value in the set
if (Hash()(mEntries[i]) == hashCode && keyEqual(mEntries[i], value)) {
return false;
}
}
}
size_t entryIndex;
uint64 entryIndex;
// If there are free entries to use
if (mNbFreeEntries > 0) {
assert(mFreeIndex >= 0);
entryIndex = mFreeIndex;
mFreeIndex = mEntries[entryIndex].next;
mNbFreeEntries--;
}
else {
// If there are no more free entries to use
if (mFreeIndex == INVALID_INDEX) {
// If we need to allocator more entries
if (mNbUsedEntries == mCapacity) {
// Allocate more memory
reserve(mHashSize == 0 ? 16 : mHashSize * 2);
// Allocate more memory
reserve(mCapacity * 2);
// Recompute the bucket index
bucket = hashCode % mCapacity;
}
entryIndex = mNbUsedEntries;
mNbUsedEntries++;
// Recompute the bucket index
const size_t divider = mHashSize - 1;
bucket = static_cast<uint64>(hashCode & divider);
}
assert(mEntries[entryIndex].value == nullptr);
mEntries[entryIndex].hashCode = hashCode;
mEntries[entryIndex].next = mBuckets[bucket];
mEntries[entryIndex].value = static_cast<V*>(mAllocator.allocate(sizeof(V)));
assert(mEntries[entryIndex].value != nullptr);
new (mEntries[entryIndex].value) V(value);
assert(mNbEntries < mNbAllocatedEntries);
assert(mFreeIndex != INVALID_INDEX);
// Get the next free entry
entryIndex = mFreeIndex;
mFreeIndex = mNextEntries[entryIndex];
mNbEntries++;
assert(bucket != INVALID_INDEX);
mNextEntries[entryIndex] = mBuckets[bucket];
new (mEntries + entryIndex) V(value);
mBuckets[bucket] = entryIndex;
return true;
@ -495,46 +419,47 @@ class Set {
/// element after the one that has been removed
Iterator remove(const V& value) {
if (mCapacity > 0) {
if (mHashSize > 0) {
size_t hashcode = Hash()(value);
auto keyEqual = KeyEqual();
int bucket = hashcode % mCapacity;
int last = -1;
for (int i = mBuckets[bucket]; i >= 0; last = i, i = mEntries[i].next) {
const size_t hashcode = Hash()(value);
auto keyEqual = KeyEqual();
const size_t divider = mHashSize - 1;
const size_t bucket = hashcode & divider;
uint64 last = INVALID_INDEX;
for (uint64 i = mBuckets[bucket]; i != INVALID_INDEX; last = i, i = mNextEntries[i]) {
if (mEntries[i].hashCode == hashcode && keyEqual(*mEntries[i].value, value)) {
// If we have found the item
if (Hash()(mEntries[i]) == hashcode && keyEqual(mEntries[i], value)) {
if (last < 0 ) {
mBuckets[bucket] = mEntries[i].next;
if (last == INVALID_INDEX) {
mBuckets[bucket] = mNextEntries[i];
}
else {
mEntries[last].next = mEntries[i].next;
mNextEntries[last] = mNextEntries[i];
}
// Release memory for the value if any
if (mEntries[i].value != nullptr) {
mEntries[i].value->~V();
mAllocator.release(mEntries[i].value, sizeof(V));
mEntries[i].value = nullptr;
}
assert(mEntries[i].value == nullptr);
mEntries[i].next = mFreeIndex;
uint64 nextEntryIndex = mNextEntries[i];
uint64 nextBucketIndex = bucket;
mEntries[i].~V();
mNextEntries[i] = mFreeIndex;
mFreeIndex = i;
mNbFreeEntries++;
mNbEntries--;
// Find the next valid entry to return an iterator
for (i += 1; i < mNbUsedEntries; i++) {
// If the entry is not empty
if (mEntries[i].value != nullptr) {
// We have found the next non empty entry
return Iterator(mEntries, mCapacity, mNbUsedEntries, i);
// Find the next entry to return an iterator
if (nextEntryIndex == INVALID_INDEX) {
nextEntryIndex = 0;
nextBucketIndex++;
while(nextBucketIndex < mHashSize && mBuckets[nextBucketIndex] == INVALID_INDEX) {
nextBucketIndex++;
}
if (nextBucketIndex < mHashSize) {
nextEntryIndex = mBuckets[nextBucketIndex];
}
}
return end();
// We have found the next non empty entry
return Iterator(this, nextBucketIndex, nextEntryIndex);
}
}
}
@ -542,67 +467,67 @@ class Set {
return end();
}
/// Return a list with all the values of the set
List<V> toList(MemoryAllocator& listAllocator) const {
/// Return an array with all the values of the set
Array<V> toArray(MemoryAllocator& arrayAllocator) const {
List<V> list(listAllocator);
Array<V> array(arrayAllocator);
for (int i=0; i < mCapacity; i++) {
if (mEntries[i].value != nullptr) {
list.add(*(mEntries[i].value));
}
for (auto it = begin(); it != end(); ++it) {
array.add(*it);
}
return list;
return array;
}
/// Clear the set
void clear(bool releaseMemory = false) {
if (mNbUsedEntries > 0) {
for (uint64 i=0; i<mHashSize; i++) {
for (int i=0; i < mCapacity; i++) {
mBuckets[i] = -1;
mEntries[i].next = -1;
if (mEntries[i].value != nullptr) {
mEntries[i].value->~V();
mAllocator.release(mEntries[i].value, sizeof(V));
mEntries[i].value = nullptr;
}
uint64 entryIndex = mBuckets[i];
while(entryIndex != INVALID_INDEX) {
// Destroy the entry
mEntries[entryIndex].~V();
uint64 nextEntryIndex = mNextEntries[entryIndex];
// Add entry to the free list
mNextEntries[entryIndex] = mFreeIndex;
mFreeIndex = entryIndex;
entryIndex = nextEntryIndex;
}
mFreeIndex = -1;
mNbUsedEntries = 0;
mNbFreeEntries = 0;
mBuckets[i] = INVALID_INDEX;
}
// If elements have been allocated
if (releaseMemory && mCapacity > 0) {
if (releaseMemory && mNbAllocatedEntries > 0) {
// Destroy the entries
for (int i=0; i < mCapacity; i++) {
mEntries[i].~Entry();
}
// Release previously allocated memory
mAllocator.release(mBuckets, mHashSize * sizeof(uint64));
mAllocator.release(mEntries, mNbAllocatedEntries * sizeof(V));
mAllocator.release(mNextEntries, mNbAllocatedEntries * sizeof(uint64));
mAllocator.release(mBuckets, mCapacity * sizeof(int));
mAllocator.release(mEntries, mCapacity * sizeof(Entry));
mCapacity = 0;
mBuckets = nullptr;
mEntries = nullptr;
mNextEntries = nullptr;
mNbAllocatedEntries = 0;
mHashSize = 0;
}
assert(size() == 0);
mNbEntries = 0;
}
/// Return the number of elements in the set
int size() const {
return mNbUsedEntries - mNbFreeEntries;
uint64 size() const {
return mNbEntries;
}
/// Return the capacity of the set
int capacity() const {
return mCapacity;
uint64 capacity() const {
return mHashSize;
}
/// Try to find an item of the set given a key.
@ -610,30 +535,29 @@ class Set {
/// an iterator pointing to the end if not found
Iterator find(const V& value) const {
int bucket;
int entry = -1;
uint64 bucket;
uint64 entry = INVALID_INDEX;
if (mCapacity > 0) {
if (mHashSize > 0) {
size_t hashCode = Hash()(value);
bucket = hashCode % mCapacity;
auto keyEqual = KeyEqual();
const size_t hashCode = Hash()(value);
const size_t divider = mHashSize - 1;
bucket = static_cast<uint64>(hashCode & divider);
auto keyEqual = KeyEqual();
for (int i = mBuckets[bucket]; i >= 0; i = mEntries[i].next) {
if (mEntries[i].hashCode == hashCode && keyEqual(*(mEntries[i].value), value)) {
for (uint64 i = mBuckets[bucket]; i != INVALID_INDEX; i = mNextEntries[i]) {
if (Hash()(mEntries[i]) == hashCode && keyEqual(mEntries[i], value)) {
entry = i;
break;
}
}
}
if (entry == -1) {
if (entry == INVALID_INDEX) {
return end();
}
assert(mEntries[entry].value != nullptr);
return Iterator(mEntries, mCapacity, mNbUsedEntries, entry);
return Iterator(this, bucket, entry);
}
/// Overloaded equality operator
@ -665,34 +589,38 @@ class Set {
// Clear the set
clear(true);
if (set.mCapacity > 0) {
mNbAllocatedEntries = set.mNbAllocatedEntries;
mNbEntries = set.mNbEntries;
mHashSize = set.mHashSize;
mFreeIndex = set.mFreeIndex;
// Compute the next larger prime size
mCapacity = getPrimeSize(set.mCapacity);
if (mHashSize > 0) {
// Allocate memory for the buckets
mBuckets = static_cast<int*>(mAllocator.allocate(mCapacity * sizeof(int)));
mBuckets = static_cast<uint64*>(mAllocator.allocate(mHashSize * sizeof(uint64)));
// Allocate memory for the entries
mEntries = static_cast<Entry*>(mAllocator.allocate(mCapacity * sizeof(Entry)));
mEntries = static_cast<V*>(mAllocator.allocate(mNbAllocatedEntries * sizeof(V)));
mNextEntries = static_cast<uint64*>(mAllocator.allocate(mNbAllocatedEntries * sizeof(uint64)));
// Copy the buckets
std::uninitialized_copy(set.mBuckets, set.mBuckets + mCapacity, mBuckets);
// Copy the buckets array
std::memcpy(mBuckets, set.mBuckets, mHashSize * sizeof(uint64));
// Copy the next entries indices
std::memcpy(mNextEntries, set.mNextEntries, mNbAllocatedEntries * sizeof(uint64));
// Copy the entries
for (int i=0; i < mCapacity; i++) {
for (uint64 i=0; i<mHashSize; i++) {
new (&mEntries[i]) Entry(set.mEntries[i].hashCode, set.mEntries[i].next);
uint64 entryIndex = mBuckets[i];
while(entryIndex != INVALID_INDEX) {
if (set.mEntries[i].value != nullptr) {
mEntries[i].value = static_cast<V*>(mAllocator.allocate(sizeof(V)));
new (mEntries[i].value) V(*(set.mEntries[i].value));
// Copy the entry to the new location and destroy the previous one
new (mEntries + entryIndex) V(set.mEntries[entryIndex]);
entryIndex = mNextEntries[entryIndex];
}
}
mNbUsedEntries = set.mNbUsedEntries;
mNbFreeEntries = set.mNbFreeEntries;
mFreeIndex = set.mFreeIndex;
}
}
@ -702,7 +630,7 @@ class Set {
/// Return a begin iterator
Iterator begin() const {
// If the map is empty
// If the set is empty
if (size() == 0) {
// Return an iterator to the end
@ -710,33 +638,29 @@ class Set {
}
// Find the first used entry
int entry;
for (entry=0; entry < mNbUsedEntries; entry++) {
if (mEntries[entry].value != nullptr) {
return Iterator(mEntries, mCapacity, mNbUsedEntries, entry);
}
uint64 bucketIndex = 0;
while (mBuckets[bucketIndex] == INVALID_INDEX) {
bucketIndex++;
}
assert(false);
return end();
assert(bucketIndex < mHashSize);
assert(mBuckets[bucketIndex] != INVALID_INDEX);
return Iterator(this, bucketIndex, mBuckets[bucketIndex]);
}
/// Return a end iterator
Iterator end() const {
return Iterator(mEntries, mCapacity, mNbUsedEntries, mCapacity);
return Iterator(this, mHashSize, 0);
}
// ---------- Friendship ---------- //
friend class Iterator;
};
template<typename V, class Hash, class KeyEqual>
const int Set<V, Hash, KeyEqual>::PRIMES[NB_PRIMES] = {3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559};
template<typename V, class Hash, class KeyEqual>
int Set<V, Hash, KeyEqual>::LARGEST_PRIME = -1;
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -51,15 +51,15 @@ class Stack {
T* mArray;
/// Number of elements in the stack
uint mNbElements;
uint64 mNbElements;
/// Number of allocated elements in the stack
uint mCapacity;
uint64 mCapacity;
// -------------------- Methods -------------------- //
/// Allocate more memory
void allocate(size_t capacity) {
void allocate(uint64 capacity) {
T* newArray = static_cast<T*>(mAllocator.allocate(capacity * sizeof(T)));
assert(newArray != nullptr);
@ -87,7 +87,7 @@ class Stack {
// -------------------- Methods -------------------- //
/// Constructor
Stack(MemoryAllocator& allocator, size_t capacity = 0)
Stack(MemoryAllocator& allocator, uint64 capacity = 0)
:mAllocator(allocator), mArray(nullptr), mNbElements(0), mCapacity(0) {
if (capacity > 0) {
@ -130,7 +130,7 @@ class Stack {
void clear() {
// Destruct the items
for (size_t i = 0; i < mNbElements; i++) {
for (uint64 i = 0; i < mNbElements; i++) {
mArray[i].~T();
}
@ -169,12 +169,12 @@ class Stack {
}
/// Return the number of items in the stack
size_t size() const {
uint64 size() const {
return mNbElements;
}
/// Return the capacity of the stack
size_t capacity() const {
uint64 capacity() const {
return mCapacity;
}
};

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -29,6 +29,7 @@
// Libraries
#include <cstddef>
#include <functional>
#include <reactphysics3d/configuration.h>
namespace reactphysics3d {

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -91,9 +91,6 @@ struct Entity {
/// Return the generation number of the entity
uint32 getGeneration() const;
/// Assignment operator
Entity& operator=(const Entity& entity);
/// Equality operator
bool operator==(const Entity& entity) const;
@ -103,27 +100,26 @@ struct Entity {
// -------------------- Friendship -------------------- //
friend class EntityManager;
};
// Return the lookup index of the entity in a array
inline uint32 Entity::getIndex() const {
RP3D_FORCE_INLINE uint32 Entity::getIndex() const {
return id & ENTITY_INDEX_MASK;
}
// Return the generation number of the entity
inline uint32 Entity::getGeneration() const {
RP3D_FORCE_INLINE uint32 Entity::getGeneration() const {
return (id >> ENTITY_INDEX_BITS) & ENTITY_GENERATION_MASK;
}
// Equality operator
inline bool Entity::operator==(const Entity& entity) const {
RP3D_FORCE_INLINE bool Entity::operator==(const Entity& entity) const {
return entity.id == id;
}
// Inequality operator
inline bool Entity::operator!=(const Entity& entity) const {
RP3D_FORCE_INLINE bool Entity::operator!=(const Entity& entity) const {
return entity.id != id;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -28,7 +28,7 @@
// Libraries
#include <reactphysics3d/configuration.h>
#include <reactphysics3d/containers/List.h>
#include <reactphysics3d/containers/Array.h>
#include <reactphysics3d/containers/Deque.h>
#include <reactphysics3d/engine/Entity.h>
@ -45,8 +45,8 @@ class EntityManager {
// -------------------- Attributes -------------------- //
/// List storing the generations of the created entities
List<uint8> mGenerations;
/// Array storing the generations of the created entities
Array<uint8> mGenerations;
/// Deque with the indices of destroyed entities that can be reused
Deque<uint32> mFreeIndices;
@ -71,7 +71,7 @@ class EntityManager {
};
// Return true if the entity is still valid (not destroyed)
inline bool EntityManager::isValid(Entity entity) const {
RP3D_FORCE_INLINE bool EntityManager::isValid(Entity entity) const {
return mGenerations[entity.getIndex()] == entity.getGeneration();
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -55,13 +55,13 @@ class EventListener : public CollisionCallback {
/**
* @param callbackData Contains information about all the contacts
*/
virtual void onContact(const CollisionCallback::CallbackData& callbackData) override {}
virtual void onContact(const CollisionCallback::CallbackData& /*callbackData*/) override {}
/// Called when some trigger events occur
/**
* @param callbackData Contains information about all the triggers that are colliding
*/
virtual void onTrigger(const OverlapCallback::CallbackData& callbackData) {}
virtual void onTrigger(const OverlapCallback::CallbackData& /*callbackData*/) {}
};
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -54,17 +54,17 @@ class Island {
ContactManifold** mContactManifolds;
/// Current number of bodies in the island
uint mNbBodies;
uint32 mNbBodies;
/// Current number of contact manifold in the island
uint mNbContactManifolds;
uint32 mNbContactManifolds;
public:
// -------------------- Methods -------------------- //
/// Constructor
Island(uint nbMaxBodies, uint nbMaxContactManifolds, MemoryManager& memoryManager);
Island(uint32 nbMaxBodies, uint32 nbMaxContactManifolds, MemoryManager& memoryManager);
/// Destructor
~Island();
@ -85,13 +85,13 @@ class Island {
void addJoint(Joint* joint);
/// Return the number of bodies in the island
uint getNbBodies() const;
uint32 getNbBodies() const;
/// Return the number of contact manifolds in the island
uint getNbContactManifolds() const;
uint32 getNbContactManifolds() const;
/// Return the number of joints in the island
uint getNbJoints() const;
uint32 getNbJoints() const;
/// Return a pointer to the array of bodies
RigidBody** getBodies();
@ -105,35 +105,35 @@ class Island {
};
// Add a body into the island
inline void Island::addBody(RigidBody* body) {
RP3D_FORCE_INLINE void Island::addBody(RigidBody* body) {
assert(!body->isSleeping());
mBodies[mNbBodies] = body;
mNbBodies++;
}
// Add a contact manifold into the island
inline void Island::addContactManifold(ContactManifold* contactManifold) {
RP3D_FORCE_INLINE void Island::addContactManifold(ContactManifold* contactManifold) {
mContactManifolds[mNbContactManifolds] = contactManifold;
mNbContactManifolds++;
}
// Return the number of bodies in the island
inline uint Island::getNbBodies() const {
RP3D_FORCE_INLINE uint32 Island::getNbBodies() const {
return mNbBodies;
}
// Return the number of contact manifolds in the island
inline uint Island::getNbContactManifolds() const {
RP3D_FORCE_INLINE uint32 Island::getNbContactManifolds() const {
return mNbContactManifolds;
}
// Return a pointer to the array of bodies
inline RigidBody** Island::getBodies() {
RP3D_FORCE_INLINE RigidBody** Island::getBodies() {
return mBodies;
}
// Return a pointer to the array of contact manifolds
inline ContactManifold** Island::getContactManifolds() {
RP3D_FORCE_INLINE ContactManifold** Island::getContactManifolds() {
return mContactManifolds;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -28,7 +28,7 @@
// Libraries
#include <reactphysics3d/configuration.h>
#include <reactphysics3d/containers/List.h>
#include <reactphysics3d/containers/Array.h>
#include <reactphysics3d/engine/Entity.h>
#include <reactphysics3d/constraint/Joint.h>
@ -46,10 +46,17 @@ struct Islands {
private:
// -------------------- Attributes -------------------- //
/// Number of islands in the previous frame
uint32 mNbIslandsPreviousFrame;
/// Reference to the memory allocator
MemoryAllocator& memoryAllocator;
/// Number of items in the bodyEntities array in the previous frame
uint32 mNbBodyEntitiesPreviousFrame;
/// Maximum number of bodies in a single island in the previous frame
uint32 mNbMaxBodiesInIslandPreviousFrame;
/// Maximum number of bodies in a single island in the current frame
uint32 mNbMaxBodiesInIslandCurrentFrame;
public:
@ -57,20 +64,27 @@ struct Islands {
/// For each island, index of the first contact manifold of the island in the array of contact manifolds
List<uint> contactManifoldsIndices;
Array<uint> contactManifoldsIndices;
/// For each island, number of contact manifolds in the island
List<uint> nbContactManifolds;
Array<uint> nbContactManifolds;
/// For each island, list of all the entities of the bodies in the island
List<List<Entity>> bodyEntities;
/// Array of all the entities of the bodies in the islands (stored sequentially)
Array<Entity> bodyEntities;
/// For each island we store the starting index of the bodies of that island in the "bodyEntities" array
Array<uint32> startBodyEntitiesIndex;
/// For each island, total number of bodies in the island
Array<uint32> nbBodiesInIsland;
// -------------------- Methods -------------------- //
/// Constructor
Islands(MemoryAllocator& allocator)
:memoryAllocator(allocator), contactManifoldsIndices(allocator), nbContactManifolds(allocator),
bodyEntities(allocator) {
:mNbIslandsPreviousFrame(16), mNbBodyEntitiesPreviousFrame(32), mNbMaxBodiesInIslandPreviousFrame(0), mNbMaxBodiesInIslandCurrentFrame(0),
contactManifoldsIndices(allocator), nbContactManifolds(allocator),
bodyEntities(allocator), startBodyEntitiesIndex(allocator), nbBodiesInIsland(allocator) {
}
@ -78,7 +92,7 @@ struct Islands {
~Islands() = default;
/// Assignment operator
Islands& operator=(const Islands& island) = default;
Islands& operator=(const Islands& island) = delete;
/// Copy-constructor
Islands(const Islands& island) = default;
@ -91,21 +105,63 @@ struct Islands {
/// Add an island and return its index
uint32 addIsland(uint32 contactManifoldStartIndex) {
uint32 islandIndex = contactManifoldsIndices.size();
const uint32 islandIndex = static_cast<uint32>(contactManifoldsIndices.size());
contactManifoldsIndices.add(contactManifoldStartIndex);
nbContactManifolds.add(0);
bodyEntities.add(List<Entity>(memoryAllocator));
startBodyEntitiesIndex.add(static_cast<uint32>(bodyEntities.size()));
nbBodiesInIsland.add(0);
if (islandIndex > 0 && nbBodiesInIsland[islandIndex-1] > mNbMaxBodiesInIslandCurrentFrame) {
mNbMaxBodiesInIslandCurrentFrame = nbBodiesInIsland[islandIndex-1];
}
return islandIndex;
}
void addBodyToIsland(Entity bodyEntity) {
const uint32 islandIndex = static_cast<uint32>(contactManifoldsIndices.size());
assert(islandIndex > 0);
bodyEntities.add(bodyEntity);
nbBodiesInIsland[islandIndex - 1]++;
}
/// Reserve memory for the current frame
void reserveMemory() {
contactManifoldsIndices.reserve(mNbIslandsPreviousFrame);
nbContactManifolds.reserve(mNbIslandsPreviousFrame);
startBodyEntitiesIndex.reserve(mNbIslandsPreviousFrame);
nbBodiesInIsland.reserve(mNbIslandsPreviousFrame);
bodyEntities.reserve(mNbBodyEntitiesPreviousFrame);
}
/// Clear all the islands
void clear() {
const uint32 nbIslands = static_cast<uint32>(nbContactManifolds.size());
if (nbIslands > 0 && nbBodiesInIsland[nbIslands-1] > mNbMaxBodiesInIslandCurrentFrame) {
mNbMaxBodiesInIslandCurrentFrame = nbBodiesInIsland[nbIslands-1];
}
mNbMaxBodiesInIslandPreviousFrame = mNbMaxBodiesInIslandCurrentFrame;
mNbIslandsPreviousFrame = nbIslands;
mNbMaxBodiesInIslandCurrentFrame = 0;
mNbBodyEntitiesPreviousFrame = static_cast<uint32>(bodyEntities.size());
contactManifoldsIndices.clear(true);
nbContactManifolds.clear(true);
bodyEntities.clear(true);
startBodyEntitiesIndex.clear(true);
nbBodiesInIsland.clear(true);
}
uint32 getNbMaxBodiesInIslandPreviousFrame() const {
return mNbMaxBodiesInIslandPreviousFrame;
}
};

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -28,6 +28,7 @@
// Libraries
#include <cassert>
#include <cmath>
#include <reactphysics3d/configuration.h>
namespace reactphysics3d {
@ -44,11 +45,8 @@ class Material {
// -------------------- Attributes -------------------- //
/// Friction coefficient (positive value)
decimal mFrictionCoefficient;
/// Rolling resistance factor (positive value)
decimal mRollingResistance;
/// Square root of the friction coefficient
decimal mFrictionCoefficientSqrt;
/// Bounciness during collisions (between 0 and 1) where 1 is for a very bouncy body
decimal mBounciness;
@ -59,14 +57,7 @@ class Material {
// -------------------- Methods -------------------- //
/// Constructor
Material(decimal frictionCoefficient, decimal rollingResistance, decimal bounciness,
decimal massDensity = decimal(1.0));
/// Copy-constructor
Material(const Material& material);
/// Destructor
~Material() = default;
Material(decimal frictionCoefficient, decimal bounciness, decimal massDensity = decimal(1.0));
public :
@ -84,11 +75,8 @@ class Material {
/// Set the friction coefficient.
void setFrictionCoefficient(decimal frictionCoefficient);
/// Return the rolling resistance factor
decimal getRollingResistance() const;
/// Set the rolling resistance factor
void setRollingResistance(decimal rollingResistance);
/// Return the square root friction coefficient
decimal getFrictionCoefficientSqrt() const;
/// Return the mass density of the collider
decimal getMassDensity() const;
@ -99,19 +87,18 @@ class Material {
/// Return a string representation for the material
std::string to_string() const;
/// Overloaded assignment operator
Material& operator=(const Material& material);
// ---------- Friendship ---------- //
friend class Collider;
friend class CollisionBody;
friend class RigidBody;
};
// Return the bounciness
/**
* @return Bounciness factor (between 0 and 1) where 1 is very bouncy
*/
inline decimal Material::getBounciness() const {
RP3D_FORCE_INLINE decimal Material::getBounciness() const {
return mBounciness;
}
@ -121,7 +108,7 @@ inline decimal Material::getBounciness() const {
/**
* @param bounciness Bounciness factor (between 0 and 1) where 1 is very bouncy
*/
inline void Material::setBounciness(decimal bounciness) {
RP3D_FORCE_INLINE void Material::setBounciness(decimal bounciness) {
assert(bounciness >= decimal(0.0) && bounciness <= decimal(1.0));
mBounciness = bounciness;
}
@ -130,8 +117,8 @@ inline void Material::setBounciness(decimal bounciness) {
/**
* @return Friction coefficient (positive value)
*/
inline decimal Material::getFrictionCoefficient() const {
return mFrictionCoefficient;
RP3D_FORCE_INLINE decimal Material::getFrictionCoefficient() const {
return mFrictionCoefficientSqrt * mFrictionCoefficientSqrt;
}
// Set the friction coefficient.
@ -140,34 +127,18 @@ inline decimal Material::getFrictionCoefficient() const {
/**
* @param frictionCoefficient Friction coefficient (positive value)
*/
inline void Material::setFrictionCoefficient(decimal frictionCoefficient) {
RP3D_FORCE_INLINE void Material::setFrictionCoefficient(decimal frictionCoefficient) {
assert(frictionCoefficient >= decimal(0.0));
mFrictionCoefficient = frictionCoefficient;
mFrictionCoefficientSqrt = std::sqrt(frictionCoefficient);
}
// Return the rolling resistance factor. If this value is larger than zero,
// it will be used to slow down the body when it is rolling
// against another body.
/**
* @return The rolling resistance factor (positive value)
*/
inline decimal Material::getRollingResistance() const {
return mRollingResistance;
}
// Set the rolling resistance factor. If this value is larger than zero,
// it will be used to slow down the body when it is rolling
// against another body.
/**
* @param rollingResistance The rolling resistance factor
*/
inline void Material::setRollingResistance(decimal rollingResistance) {
assert(rollingResistance >= 0);
mRollingResistance = rollingResistance;
// Return the square root friction coefficient
RP3D_FORCE_INLINE decimal Material::getFrictionCoefficientSqrt() const {
return mFrictionCoefficientSqrt;
}
// Return the mass density of the collider
inline decimal Material::getMassDensity() const {
RP3D_FORCE_INLINE decimal Material::getMassDensity() const {
return mMassDensity;
}
@ -175,36 +146,21 @@ inline decimal Material::getMassDensity() const {
/**
* @param massDensity The mass density of the collider
*/
inline void Material::setMassDensity(decimal massDensity) {
RP3D_FORCE_INLINE void Material::setMassDensity(decimal massDensity) {
mMassDensity = massDensity;
}
// Return a string representation for the material
inline std::string Material::to_string() const {
RP3D_FORCE_INLINE std::string Material::to_string() const {
std::stringstream ss;
ss << "frictionCoefficient=" << mFrictionCoefficient << std::endl;
ss << "rollingResistance=" << mRollingResistance << std::endl;
ss << "frictionCoefficient=" << (mFrictionCoefficientSqrt * mFrictionCoefficientSqrt) << std::endl;
ss << "bounciness=" << mBounciness << std::endl;
return ss.str();
}
// Overloaded assignment operator
inline Material& Material::operator=(const Material& material) {
// Check for self-assignment
if (this != &material) {
mFrictionCoefficient = material.mFrictionCoefficient;
mBounciness = material.mBounciness;
mRollingResistance = material.mRollingResistance;
}
// Return this material
return *this;
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -54,6 +54,8 @@ class CollisionDispatch;
*/
struct LastFrameCollisionInfo {
// TODO OPTI : Use bit flags instead of bools here
/// True if we have information about the previous frame
bool isValid;
@ -77,20 +79,16 @@ struct LastFrameCollisionInfo {
// SAT Algorithm
bool satIsAxisFacePolyhedron1;
bool satIsAxisFacePolyhedron2;
uint satMinAxisFaceIndex;
uint satMinEdge1Index;
uint satMinEdge2Index;
uint8 satMinAxisFaceIndex;
uint8 satMinEdge1Index;
uint8 satMinEdge2Index;
/// Constructor
LastFrameCollisionInfo() {
LastFrameCollisionInfo()
:isValid(false), isObsolete(false), wasColliding(false), wasUsingGJK(false), gjkSeparatingAxis(Vector3(0, 1, 0)),
satIsAxisFacePolyhedron1(false), satIsAxisFacePolyhedron2(false), satMinAxisFaceIndex(0),
satMinEdge1Index(0), satMinEdge2Index(0) {
isValid = false;
isObsolete = false;
wasColliding = false;
wasUsingSAT = false;
wasUsingGJK = false;
gjkSeparatingAxis = Vector3(0, 1, 0);
}
};
@ -104,80 +102,194 @@ struct LastFrameCollisionInfo {
*/
class OverlappingPairs {
public:
struct OverlappingPair {
/// Ids of the convex vs convex pairs
uint64 pairID;
/// Broad-phase Id of the first shape
// TODO OPTI : Is this used ?
int32 broadPhaseId1;
/// Broad-phase Id of the second shape
// TODO OPTI : Is this used ?
int32 broadPhaseId2;
/// Entity of the first collider of the convex vs convex pairs
Entity collider1;
/// Entity of the second collider of the convex vs convex pairs
Entity collider2;
/// True if we need to test if the convex vs convex overlapping pairs of shapes still overlap
bool needToTestOverlap;
/// Pointer to the narrow-phase algorithm
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType;
/// True if the colliders of the overlapping pair were colliding in the previous frame
bool collidingInPreviousFrame;
/// True if the colliders of the overlapping pair are colliding in the current frame
bool collidingInCurrentFrame;
/// Constructor
OverlappingPair(uint64 pairId, int32 broadPhaseId1, int32 broadPhaseId2, Entity collider1, Entity collider2,
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType)
: pairID(pairId), broadPhaseId1(broadPhaseId1), broadPhaseId2(broadPhaseId2), collider1(collider1) , collider2(collider2),
needToTestOverlap(false), narrowPhaseAlgorithmType(narrowPhaseAlgorithmType), collidingInPreviousFrame(false),
collidingInCurrentFrame(false) {
}
/// Destructor
virtual ~OverlappingPair() = default;
};
// Overlapping pair between two convex colliders
struct ConvexOverlappingPair : public OverlappingPair {
/// Temporal coherence collision data for each overlapping collision shapes of this pair.
/// Temporal coherence data store collision information about the last frame.
/// If two convex shapes overlap, we have a single collision data but if one shape is concave,
/// we might have collision data for several overlapping triangles.
LastFrameCollisionInfo lastFrameCollisionInfo;
/// Constructor
ConvexOverlappingPair(uint64 pairId, int32 broadPhaseId1, int32 broadPhaseId2, Entity collider1, Entity collider2,
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType)
: OverlappingPair(pairId, broadPhaseId1, broadPhaseId2, collider1, collider2, narrowPhaseAlgorithmType) {
}
};
// Overlapping pair between two a convex collider and a concave collider
struct ConcaveOverlappingPair : public OverlappingPair {
private:
MemoryAllocator* mPoolAllocator;
public:
/// True if the first shape of the pair is convex
bool isShape1Convex;
/// Temporal coherence collision data for each overlapping collision shapes of this pair.
/// Temporal coherence data store collision information about the last frame.
/// If two convex shapes overlap, we have a single collision data but if one shape is concave,
/// we might have collision data for several overlapping triangles. The key in the map is the
/// shape Ids of the two collision shapes.
Map<uint64, LastFrameCollisionInfo*> lastFrameCollisionInfos;
/// Constructor
ConcaveOverlappingPair(uint64 pairId, int32 broadPhaseId1, int32 broadPhaseId2, Entity collider1, Entity collider2,
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType,
bool isShape1Convex, MemoryAllocator& poolAllocator, MemoryAllocator& heapAllocator)
: OverlappingPair(pairId, broadPhaseId1, broadPhaseId2, collider1, collider2, narrowPhaseAlgorithmType), mPoolAllocator(&poolAllocator),
isShape1Convex(isShape1Convex), lastFrameCollisionInfos(heapAllocator, 16) {
}
// Destroy all the LastFrameCollisionInfo objects
void destroyLastFrameCollisionInfos() {
for (auto it = lastFrameCollisionInfos.begin(); it != lastFrameCollisionInfos.end(); ++it) {
// Call the destructor
it->second->LastFrameCollisionInfo::~LastFrameCollisionInfo();
// Release memory
mPoolAllocator->release(it->second, sizeof(LastFrameCollisionInfo));
}
lastFrameCollisionInfos.clear();
}
// Add a new last frame collision info if it does not exist for the given shapes already
LastFrameCollisionInfo* addLastFrameInfoIfNecessary(uint32 shapeId1, uint32 shapeId2) {
uint32 maxShapeId = shapeId1;
uint32 minShapeId = shapeId2;
if (shapeId1 < shapeId2) {
maxShapeId = shapeId2;
minShapeId = shapeId1;
}
// Try to get the corresponding last frame collision info
const uint64 shapesId = pairNumbers(maxShapeId, minShapeId);
// If there is no collision info for those two shapes already
auto it = lastFrameCollisionInfos.find(shapesId);
if (it == lastFrameCollisionInfos.end()) {
LastFrameCollisionInfo* lastFrameInfo = new (mPoolAllocator->allocate(sizeof(LastFrameCollisionInfo))) LastFrameCollisionInfo();
// Add it into the map of collision infos
lastFrameCollisionInfos.add(Pair<uint64, LastFrameCollisionInfo*>(shapesId, lastFrameInfo));
return lastFrameInfo;
}
else {
// The existing collision info is not obsolete
it->second->isObsolete = false;
return it->second;
}
}
/// Clear the obsolete LastFrameCollisionInfo objects
void clearObsoleteLastFrameInfos() {
// For each last frame collision info
for (auto it = lastFrameCollisionInfos.begin(); it != lastFrameCollisionInfos.end(); ) {
// If the collision info is obsolete
if (it->second->isObsolete) {
// Call the destructor
it->second->LastFrameCollisionInfo::~LastFrameCollisionInfo();
// Release memory
mPoolAllocator->release(it->second, sizeof(LastFrameCollisionInfo));
it = lastFrameCollisionInfos.remove(it);
}
else { // If the collision info is not obsolete
// Do not delete it but mark it as obsolete
it->second->isObsolete = true;
++it;
}
}
}
};
private:
// -------------------- Constants -------------------- //
/// Number of pairs to allocated at the beginning
const uint32 INIT_NB_ALLOCATED_PAIRS = 10;
// -------------------- Attributes -------------------- //
/// Persistent memory allocator
MemoryAllocator& mPersistentAllocator;
/// Pool memory allocator
MemoryAllocator& mPoolAllocator;
/// Memory allocator used to allocated memory for the ContactManifoldInfo and ContactPointInfo
// TODO : Do we need to keep this ?
MemoryAllocator& mTempMemoryAllocator;
/// Heap memory allocator
MemoryAllocator& mHeapAllocator;
/// Current number of components
uint64 mNbPairs;
/// Array of convex vs convex overlapping pairs
Array<ConvexOverlappingPair> mConvexPairs;
/// Index in the array of the first convex vs concave pair
uint64 mConcavePairsStartIndex;
/// Size (in bytes) of a single pair
size_t mPairDataSize;
/// Number of allocated pairs
uint64 mNbAllocatedPairs;
/// Allocated memory for all the data of the pairs
void* mBuffer;
/// Array of convex vs concave overlapping pairs
Array<ConcaveOverlappingPair> mConcavePairs;
/// Map a pair id to the internal array index
Map<uint64, uint64> mMapPairIdToPairIndex;
Map<uint64, uint64> mMapConvexPairIdToPairIndex;
/// Ids of the convex vs convex pairs
uint64* mPairIds;
/// Array with the broad-phase Ids of the first shape
int32* mPairBroadPhaseId1;
/// Array with the broad-phase Ids of the second shape
int32* mPairBroadPhaseId2;
/// Array of Entity of the first collider of the convex vs convex pairs
Entity* mColliders1;
/// Array of Entity of the second collider of the convex vs convex pairs
Entity* mColliders2;
/// Temporal coherence collision data for each overlapping collision shapes of this pair.
/// Temporal coherence data store collision information about the last frame.
/// If two convex shapes overlap, we have a single collision data but if one shape is concave,
/// we might have collision data for several overlapping triangles. The key in the map is the
/// shape Ids of the two collision shapes.
Map<uint64, LastFrameCollisionInfo*>* mLastFrameCollisionInfos;
/// True if we need to test if the convex vs convex overlapping pairs of shapes still overlap
bool* mNeedToTestOverlap;
/// True if the overlapping pair is active (at least one body of the pair is active and not static)
bool* mIsActive;
/// Array with the pointer to the narrow-phase algorithm for each overlapping pair
NarrowPhaseAlgorithmType* mNarrowPhaseAlgorithmType;
/// True if the first shape of the pair is convex
bool* mIsShape1Convex;
/// True if the colliders of the overlapping pair were colliding in the previous frame
bool* mCollidingInPreviousFrame;
/// True if the colliders of the overlapping pair are colliding in the current frame
bool* mCollidingInCurrentFrame;
/// Map a pair id to the internal array index
Map<uint64, uint64> mMapConcavePairIdToPairIndex;
/// Reference to the colliders components
ColliderComponents& mColliderComponents;
@ -203,15 +315,6 @@ class OverlappingPairs {
// -------------------- Methods -------------------- //
/// Allocate memory for a given number of pairs
void allocate(uint64 nbPairsToAllocate);
/// Compute the index where we need to insert the new pair
uint64 prepareAddPair(bool isConvexVsConvex);
/// Destroy a pair at a given index
void destroyPair(uint64 index);
// Move a pair from a source to a destination index in the pairs array
void movePairToIndex(uint64 srcIndex, uint64 destIndex);
@ -223,8 +326,8 @@ class OverlappingPairs {
// -------------------- Methods -------------------- //
/// Constructor
OverlappingPairs(MemoryAllocator& persistentMemoryAllocator, MemoryAllocator& temporaryMemoryAllocator,
ColliderComponents& colliderComponents, CollisionBodyComponents& collisionBodyComponents,
OverlappingPairs(MemoryManager& memoryManager, ColliderComponents& colliderComponents,
CollisionBodyComponents& collisionBodyComponents,
RigidBodyComponents& rigidBodyComponents, Set<bodypair>& noCollisionPairs,
CollisionDispatch& collisionDispatch);
@ -238,46 +341,13 @@ class OverlappingPairs {
OverlappingPairs& operator=(const OverlappingPairs& pair) = delete;
/// Add an overlapping pair
uint64 addPair(Collider* shape1, Collider* shape2);
uint64 addPair(uint32 collider1Index, uint32 collider2Index, bool isConvexVsConvex);
/// Remove a component at a given index
void removePair(uint64 pairId);
/// Return the number of pairs
uint64 getNbPairs() const;
/// Return the number of convex vs convex pairs
uint64 getNbConvexVsConvexPairs() const;
/// Return the number of convex vs concave pairs
uint64 getNbConvexVsConcavePairs() const;
/// Return the starting index of the convex vs concave pairs
uint64 getConvexVsConcavePairsStartIndex() const;
/// Return the entity of the first collider
Entity getCollider1(uint64 pairId) const;
/// Return the entity of the second collider
Entity getCollider2(uint64 pairId) const;
/// Notify if a given pair is active or not
void setIsPairActive(uint64 pairId, bool isActive);
/// Return the index of a given overlapping pair in the internal array
uint64 getPairIndex(uint64 pairId) const;
/// Return the last frame collision info
LastFrameCollisionInfo* getLastFrameCollisionInfo(uint64, uint64 shapesId);
/// Return a reference to the temporary memory allocator
MemoryAllocator& getTemporaryAllocator();
/// Add a new last frame collision info if it does not exist for the given shapes already
LastFrameCollisionInfo* addLastFrameInfoIfNecessary(uint64 pairIndex, uint32 shapeId1, uint32 shapeId2);
/// Update whether a given overlapping pair is active or not
void updateOverlappingPairIsActive(uint64 pairId);
/// Remove a pair
void removePair(uint64 pairIndex, bool isConvexVsConvex);
/// Delete all the obsolete last frame collision info
void clearObsoleteLastFrameCollisionInfos();
@ -291,11 +361,8 @@ class OverlappingPairs {
/// Set if we need to test a given pair for overlap
void setNeedToTestOverlap(uint64 pairId, bool needToTestOverlap);
/// Return true if the two colliders of the pair were already colliding the previous frame
bool getCollidingInPreviousFrame(uint64 pairId) const;
/// Set to true if the two colliders of the pair were already colliding the previous frame
void setCollidingInPreviousFrame(uint64 pairId, bool wereCollidingInPreviousFrame);
/// Return a reference to an overlapping pair
OverlappingPair* getOverlappingPair(uint64 pairId);
#ifdef IS_RP3D_PROFILING_ENABLED
@ -310,51 +377,8 @@ class OverlappingPairs {
friend class CollisionDetectionSystem;
};
// Return the entity of the first collider
inline Entity OverlappingPairs::getCollider1(uint64 pairId) const {
assert(mMapPairIdToPairIndex.containsKey(pairId));
assert(mMapPairIdToPairIndex[pairId] < mNbPairs);
return mColliders1[mMapPairIdToPairIndex[pairId]];
}
// Return the entity of the second collider
inline Entity OverlappingPairs::getCollider2(uint64 pairId) const {
assert(mMapPairIdToPairIndex.containsKey(pairId));
assert(mMapPairIdToPairIndex[pairId] < mNbPairs);
return mColliders2[mMapPairIdToPairIndex[pairId]];
}
// Notify if a given pair is active or not
inline void OverlappingPairs::setIsPairActive(uint64 pairId, bool isActive) {
assert(mMapPairIdToPairIndex.containsKey(pairId));
assert(mMapPairIdToPairIndex[pairId] < mNbPairs);
mIsActive[mMapPairIdToPairIndex[pairId]] = isActive;
}
// Return the index of a given overlapping pair in the internal array
inline uint64 OverlappingPairs::getPairIndex(uint64 pairId) const {
assert(mMapPairIdToPairIndex.containsKey(pairId));
return mMapPairIdToPairIndex[pairId];
}
// Return the last frame collision info for a given shape id or nullptr if none is found
inline LastFrameCollisionInfo* OverlappingPairs::getLastFrameCollisionInfo(uint64 pairId, uint64 shapesId) {
assert(mMapPairIdToPairIndex.containsKey(pairId));
const uint64 index = mMapPairIdToPairIndex[pairId];
assert(index < mNbPairs);
Map<uint64, LastFrameCollisionInfo*>::Iterator it = mLastFrameCollisionInfos[index].find(shapesId);
if (it != mLastFrameCollisionInfos[index].end()) {
return it->second;
}
return nullptr;
}
// Return the pair of bodies index
inline bodypair OverlappingPairs::computeBodiesIndexPair(Entity body1Entity, Entity body2Entity) {
RP3D_FORCE_INLINE bodypair OverlappingPairs::computeBodiesIndexPair(Entity body1Entity, Entity body2Entity) {
// Construct the pair of body index
bodypair indexPair = body1Entity.id < body2Entity.id ?
@ -364,53 +388,39 @@ inline bodypair OverlappingPairs::computeBodiesIndexPair(Entity body1Entity, Ent
return indexPair;
}
// Return the number of pairs
inline uint64 OverlappingPairs::getNbPairs() const {
return mNbPairs;
}
// Return the number of convex vs convex pairs
inline uint64 OverlappingPairs::getNbConvexVsConvexPairs() const {
return mConcavePairsStartIndex;
}
// Return the number of convex vs concave pairs
inline uint64 OverlappingPairs::getNbConvexVsConcavePairs() const {
return mNbPairs - mConcavePairsStartIndex;
}
// Return the starting index of the convex vs concave pairs
inline uint64 OverlappingPairs::getConvexVsConcavePairsStartIndex() const {
return mConcavePairsStartIndex;
}
// Return a reference to the temporary memory allocator
inline MemoryAllocator& OverlappingPairs::getTemporaryAllocator() {
return mTempMemoryAllocator;
}
// Set if we need to test a given pair for overlap
inline void OverlappingPairs::setNeedToTestOverlap(uint64 pairId, bool needToTestOverlap) {
assert(mMapPairIdToPairIndex.containsKey(pairId));
mNeedToTestOverlap[mMapPairIdToPairIndex[pairId]] = needToTestOverlap;
RP3D_FORCE_INLINE void OverlappingPairs::setNeedToTestOverlap(uint64 pairId, bool needToTestOverlap) {
assert(mMapConvexPairIdToPairIndex.containsKey(pairId) || mMapConcavePairIdToPairIndex.containsKey(pairId));
auto it = mMapConvexPairIdToPairIndex.find(pairId);
if (it != mMapConvexPairIdToPairIndex.end()) {
mConvexPairs[static_cast<uint32>(it->second)].needToTestOverlap = needToTestOverlap;
}
else {
mConcavePairs[static_cast<uint32>(mMapConcavePairIdToPairIndex[pairId])].needToTestOverlap = needToTestOverlap;
}
}
// Return true if the two colliders of the pair were already colliding the previous frame
inline bool OverlappingPairs::getCollidingInPreviousFrame(uint64 pairId) const {
assert(mMapPairIdToPairIndex.containsKey(pairId));
return mCollidingInPreviousFrame[mMapPairIdToPairIndex[pairId]];
}
// Return a reference to an overlapping pair
RP3D_FORCE_INLINE OverlappingPairs::OverlappingPair* OverlappingPairs::getOverlappingPair(uint64 pairId) {
// Set to true if the two colliders of the pair were already colliding the previous frame
inline void OverlappingPairs::setCollidingInPreviousFrame(uint64 pairId, bool wereCollidingInPreviousFrame) {
assert(mMapPairIdToPairIndex.containsKey(pairId));
mCollidingInPreviousFrame[mMapPairIdToPairIndex[pairId]] = wereCollidingInPreviousFrame;
auto it = mMapConvexPairIdToPairIndex.find(pairId);
if (it != mMapConvexPairIdToPairIndex.end()) {
return &(mConvexPairs[static_cast<uint32>(it->second)]);
}
it = mMapConcavePairIdToPairIndex.find(pairId);
if (it != mMapConcavePairIdToPairIndex.end()) {
return &(mConcavePairs[static_cast<uint32>(it->second)]);
}
return nullptr;
}
#ifdef IS_RP3D_PROFILING_ENABLED
// Set the profiler
inline void OverlappingPairs::setProfiler(Profiler* profiler) {
RP3D_FORCE_INLINE void OverlappingPairs::setProfiler(Profiler* profiler) {
mProfiler = profiler;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -92,11 +92,56 @@ class PhysicsCommon {
/// Set of default loggers
Set<DefaultLogger*> mDefaultLoggers;
/// Half-edge structure of a box polyhedron
HalfEdgeStructure mBoxShapeHalfEdgeStructure;
/// Half-edge structure of a triangle shape
HalfEdgeStructure mTriangleShapeHalfEdgeStructure;
// -------------------- Methods -------------------- //
/// Initialization
void init();
/// Destroy and release everything that has been allocated
void release();
/// Delete an instance of PhysicsWorld
void deletePhysicsWorld(PhysicsWorld* world);
/// Delete a sphere collision shape
void deleteSphereShape(SphereShape* sphereShape);
/// Delete a box collision shape
void deleteBoxShape(BoxShape* boxShape);
/// Delete a capsule collision shape
void deleteCapsuleShape(CapsuleShape* capsuleShape);
/// Delete a convex mesh shape
void deleteConvexMeshShape(ConvexMeshShape* convexMeshShape);
/// Delete a height-field shape
void deleteHeightFieldShape(HeightFieldShape* heightFieldShape);
/// Delete a concave mesh shape
void deleteConcaveMeshShape(ConcaveMeshShape* concaveMeshShape);
/// Delete a polyhedron mesh
void deletePolyhedronMesh(PolyhedronMesh* polyhedronMesh);
/// Delete a triangle mesh
void deleteTriangleMesh(TriangleMesh* triangleMesh);
/// Delete a default logger
void deleteDefaultLogger(DefaultLogger* logger);
/// Initialize the half-edge structure of a BoxShape
void initBoxShapeHalfEdgeStructure();
/// Initialize the static half-edge structure of a TriangleShape
void initTriangleShapeHalfEdgeStructure();
// If profiling is enabled
#ifdef IS_RP3D_PROFILING_ENABLED
@ -106,6 +151,9 @@ class PhysicsCommon {
/// Destroy a profiler
void destroyProfiler(Profiler* profiler);
/// Delete a profiler
void deleteProfiler(Profiler* profiler);
#endif
public :
@ -187,13 +235,19 @@ class PhysicsCommon {
/// Set the logger
static void setLogger(Logger* logger);
// ---------- Friendship ---------- //
friend class BoxShape;
friend class TriangleShape;
friend class PhysicsWorld;
};
// Return the current logger
/**
* @return A pointer to the current logger
*/
inline Logger* PhysicsCommon::getLogger() {
RP3D_FORCE_INLINE Logger* PhysicsCommon::getLogger() {
return mLogger;
}
@ -201,7 +255,7 @@ inline Logger* PhysicsCommon::getLogger() {
/**
* @param logger A pointer to the logger to use
*/
inline void PhysicsCommon::setLogger(Logger* logger) {
RP3D_FORCE_INLINE void PhysicsCommon::setLogger(Logger* logger) {
mLogger = logger;
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -28,7 +28,7 @@
// Libraries
#include <reactphysics3d/mathematics/mathematics.h>
#include <reactphysics3d/containers/List.h>
#include <reactphysics3d/containers/Array.h>
#include <reactphysics3d/constraint/Joint.h>
#include <reactphysics3d/memory/MemoryManager.h>
#include <reactphysics3d/engine/EntityManager.h>
@ -59,6 +59,7 @@ namespace reactphysics3d {
// Declarations
class Island;
class RigidBody;
class PhysicsCommon;
struct JointInfo;
// Class PhysicsWorld
@ -93,17 +94,14 @@ class PhysicsWorld {
/// Velocity threshold for contact velocity restitution
decimal restitutionVelocityThreshold;
/// Default rolling resistance
decimal defaultRollingRestistance;
/// True if the sleeping technique is enabled
bool isSleepingEnabled;
/// Number of iterations when solving the velocity constraints of the Sequential Impulse technique
uint defaultVelocitySolverNbIterations;
uint16 defaultVelocitySolverNbIterations;
/// Number of iterations when solving the position constraints of the Sequential Impulse technique
uint defaultPositionSolverNbIterations;
uint16 defaultPositionSolverNbIterations;
/// Time (in seconds) that a body must stay still to be considered sleeping
float defaultTimeBeforeSleep;
@ -116,9 +114,6 @@ class PhysicsWorld {
/// might enter sleeping mode
decimal defaultSleepAngularVelocity;
/// Maximum number of contact manifolds in an overlapping pair
uint nbMaxContactManifolds;
/// This is used to test if two contact manifold are similar (same contact normal) in order to
/// merge them. If the cosine of the angle between the normals of the two manifold are larger
/// than the value bellow, the manifold are considered to be similar.
@ -132,16 +127,13 @@ class PhysicsWorld {
defaultFrictionCoefficient = decimal(0.3);
defaultBounciness = decimal(0.5);
restitutionVelocityThreshold = decimal(0.5);
defaultRollingRestistance = decimal(0.0);
isSleepingEnabled = true;
defaultVelocitySolverNbIterations = 10;
defaultPositionSolverNbIterations = 5;
defaultVelocitySolverNbIterations = 6;
defaultPositionSolverNbIterations = 3;
defaultTimeBeforeSleep = 1.0f;
defaultSleepLinearVelocity = decimal(0.02);
defaultSleepAngularVelocity = decimal(3.0) * (PI / decimal(180.0));
nbMaxContactManifolds = 3;
defaultSleepAngularVelocity = decimal(3.0) * (PI_RP3D / decimal(180.0));
cosAngleSimilarContactManifold = decimal(0.95);
}
~WorldSettings() = default;
@ -157,14 +149,12 @@ class PhysicsWorld {
ss << "defaultFrictionCoefficient=" << defaultFrictionCoefficient << std::endl;
ss << "defaultBounciness=" << defaultBounciness << std::endl;
ss << "restitutionVelocityThreshold=" << restitutionVelocityThreshold << std::endl;
ss << "defaultRollingRestistance=" << defaultRollingRestistance << std::endl;
ss << "isSleepingEnabled=" << isSleepingEnabled << std::endl;
ss << "defaultVelocitySolverNbIterations=" << defaultVelocitySolverNbIterations << std::endl;
ss << "defaultPositionSolverNbIterations=" << defaultPositionSolverNbIterations << std::endl;
ss << "defaultTimeBeforeSleep=" << defaultTimeBeforeSleep << std::endl;
ss << "defaultSleepLinearVelocity=" << defaultSleepLinearVelocity << std::endl;
ss << "defaultSleepAngularVelocity=" << defaultSleepAngularVelocity << std::endl;
ss << "nbMaxContactManifolds=" << nbMaxContactManifolds << std::endl;
ss << "cosAngleSimilarContactManifold=" << cosAngleSimilarContactManifold << std::endl;
return ss.str();
@ -221,7 +211,7 @@ class PhysicsWorld {
CollisionDetectionSystem mCollisionDetection;
/// All the collision bodies of the world
List<CollisionBody*> mCollisionBodies;
Array<CollisionBody*> mCollisionBodies;
/// Pointer to an event listener object
EventListener* mEventListener;
@ -236,7 +226,7 @@ class PhysicsWorld {
#endif
/// Total number of worlds
static uint mNbWorlds;
static uint32 mNbWorlds;
/// All the islands of bodies of the current frame
Islands mIslands;
@ -244,7 +234,7 @@ class PhysicsWorld {
/// Order in which to process the ContactPairs for contact creation such that
/// all the contact manifolds and contact points of a given island are packed together
/// This array contains the indices of the ContactPairs.
List<uint32> mProcessContactPairsOrderIslands;
Array<uint32> mProcessContactPairsOrderIslands;
/// Contact solver system
ContactSolverSystem mContactSolverSystem;
@ -256,16 +246,16 @@ class PhysicsWorld {
DynamicsSystem mDynamicsSystem;
/// Number of iterations for the velocity solver of the Sequential Impulses technique
uint mNbVelocitySolverIterations;
uint16 mNbVelocitySolverIterations;
/// Number of iterations for the position solver of the Sequential Impulses technique
uint mNbPositionSolverIterations;
uint16 mNbPositionSolverIterations;
/// True if the spleeping technique for inactive bodies is enabled
bool mIsSleepingEnabled;
/// All the rigid bodies of the physics world
List<RigidBody*> mRigidBodies;
Array<RigidBody*> mRigidBodies;
/// True if the gravity force is on
bool mIsGravityEnabled;
@ -280,13 +270,10 @@ class PhysicsWorld {
/// becomes smaller than the sleep velocity.
decimal mTimeBeforeSleep;
/// Current joint id
uint mCurrentJointId;
// -------------------- Methods -------------------- //
/// Constructor
PhysicsWorld(MemoryManager& memoryManager, const WorldSettings& worldSettings = WorldSettings(), Profiler* profiler = nullptr);
PhysicsWorld(MemoryManager& memoryManager, PhysicsCommon& physicsCommon, const WorldSettings& worldSettings = WorldSettings(), Profiler* profiler = nullptr);
/// Notify the world if a body is disabled (slepping or inactive) or not
void setBodyDisabled(Entity entity, bool isDisabled);
@ -309,9 +296,12 @@ class PhysicsWorld {
/// Put bodies to sleep if needed.
void updateSleepingBodies(decimal timeStep);
/// Add the joint to the list of joints of the two bodies involved in the joint
/// Add the joint to the array of joints of the two bodies involved in the joint
void addJointToBodies(Entity body1, Entity body2, Entity joint);
/// Update the world inverse inertia tensors of rigid bodies
void updateBodiesInverseWorldInertiaTensors();
/// Destructor
~PhysicsWorld();
@ -368,28 +358,25 @@ class PhysicsWorld {
void update(decimal timeStep);
/// Get the number of iterations for the velocity constraint solver
uint getNbIterationsVelocitySolver() const;
uint16 getNbIterationsVelocitySolver() const;
/// Set the number of iterations for the velocity constraint solver
void setNbIterationsVelocitySolver(uint nbIterations);
void setNbIterationsVelocitySolver(uint16 nbIterations);
/// Get the number of iterations for the position constraint solver
uint getNbIterationsPositionSolver() const;
uint16 getNbIterationsPositionSolver() const;
/// Set the number of iterations for the position constraint solver
void setNbIterationsPositionSolver(uint nbIterations);
void setNbIterationsPositionSolver(uint32 nbIterations);
/// Set the position correction technique used for contacts
void setContactsPositionCorrectionTechnique(ContactsPositionCorrectionTechnique technique);
/// Set the position correction technique used for joints
void setJointsPositionCorrectionTechnique(JointsPositionCorrectionTechnique technique);
/// Create a rigid body into the physics world.
RigidBody* createRigidBody(const Transform& transform);
/// Disable the joints for pair of sleeping bodies
void disableJointsOfSleepingBodies();
void enableDisableJoints();
/// Destroy a rigid body and all the joints which it belongs
void destroyRigidBody(RigidBody* rigidBody);
@ -440,22 +427,22 @@ class PhysicsWorld {
void setEventListener(EventListener* eventListener);
/// Return the number of CollisionBody in the physics world
uint getNbCollisionBodies() const;
uint32 getNbCollisionBodies() const;
/// Return a constant pointer to a given CollisionBody of the world
const CollisionBody* getCollisionBody(uint index) const;
const CollisionBody* getCollisionBody(uint32 index) const;
/// Return a pointer to a given CollisionBody of the world
CollisionBody* getCollisionBody(uint index) ;
CollisionBody* getCollisionBody(uint32 index) ;
/// Return the number of RigidBody in the physics world
uint getNbRigidBodies() const;
uint32 getNbRigidBodies() const;
/// Return a constant pointer to a given RigidBody of the world
const RigidBody* getRigidBody(uint index) const;
const RigidBody* getRigidBody(uint32 index) const;
/// Return a pointer to a given RigidBody of the world
RigidBody* getRigidBody(uint index) ;
RigidBody* getRigidBody(uint32 index) ;
/// Return true if the debug rendering is enabled
bool getIsDebugRenderingEnabled() const;
@ -500,7 +487,7 @@ class PhysicsWorld {
* @param CollisionDispatch Pointer to a collision dispatch object describing
* which collision detection algorithm to use for two given collision shapes
*/
inline CollisionDispatch& PhysicsWorld::getCollisionDispatch() {
RP3D_FORCE_INLINE CollisionDispatch& PhysicsWorld::getCollisionDispatch() {
return mCollisionDetection.getCollisionDispatch();
}
@ -511,7 +498,7 @@ inline CollisionDispatch& PhysicsWorld::getCollisionDispatch() {
* @param raycastWithCategoryMaskBits Bits mask corresponding to the category of
* bodies to be raycasted
*/
inline void PhysicsWorld::raycast(const Ray& ray,
RP3D_FORCE_INLINE void PhysicsWorld::raycast(const Ray& ray,
RaycastCallback* raycastCallback,
unsigned short raycastWithCategoryMaskBits) const {
mCollisionDetection.raycast(raycastCallback, ray, raycastWithCategoryMaskBits);
@ -527,7 +514,7 @@ inline void PhysicsWorld::raycast(const Ray& ray,
* @param body2 Pointer to the second body to test
* @param callback Pointer to the object with the callback method
*/
inline void PhysicsWorld::testCollision(CollisionBody* body1, CollisionBody* body2, CollisionCallback& callback) {
RP3D_FORCE_INLINE void PhysicsWorld::testCollision(CollisionBody* body1, CollisionBody* body2, CollisionCallback& callback) {
mCollisionDetection.testCollision(body1, body2, callback);
}
@ -540,7 +527,7 @@ inline void PhysicsWorld::testCollision(CollisionBody* body1, CollisionBody* bod
* @param body Pointer to the body against which we need to test collision
* @param callback Pointer to the object with the callback method to report contacts
*/
inline void PhysicsWorld::testCollision(CollisionBody* body, CollisionCallback& callback) {
RP3D_FORCE_INLINE void PhysicsWorld::testCollision(CollisionBody* body, CollisionCallback& callback) {
mCollisionDetection.testCollision(body, callback);
}
@ -552,7 +539,7 @@ inline void PhysicsWorld::testCollision(CollisionBody* body, CollisionCallback&
/**
* @param callback Pointer to the object with the callback method to report contacts
*/
inline void PhysicsWorld::testCollision(CollisionCallback& callback) {
RP3D_FORCE_INLINE void PhysicsWorld::testCollision(CollisionCallback& callback) {
mCollisionDetection.testCollision(callback);
}
@ -564,7 +551,7 @@ inline void PhysicsWorld::testCollision(CollisionCallback& callback) {
* @param body Pointer to the collision body to test overlap with
* @param overlapCallback Pointer to the callback class to report overlap
*/
inline void PhysicsWorld::testOverlap(CollisionBody* body, OverlapCallback& overlapCallback) {
RP3D_FORCE_INLINE void PhysicsWorld::testOverlap(CollisionBody* body, OverlapCallback& overlapCallback) {
mCollisionDetection.testOverlap(body, overlapCallback);
}
@ -575,12 +562,12 @@ inline void PhysicsWorld::testOverlap(CollisionBody* body, OverlapCallback& over
/**
* @param overlapCallback Pointer to the callback class to report overlap
*/
inline void PhysicsWorld::testOverlap(OverlapCallback& overlapCallback) {
RP3D_FORCE_INLINE void PhysicsWorld::testOverlap(OverlapCallback& overlapCallback) {
mCollisionDetection.testOverlap(overlapCallback);
}
// Return a reference to the memory manager of the world
inline MemoryManager& PhysicsWorld::getMemoryManager() {
RP3D_FORCE_INLINE MemoryManager& PhysicsWorld::getMemoryManager() {
return mMemoryManager;
}
@ -588,7 +575,7 @@ inline MemoryManager& PhysicsWorld::getMemoryManager() {
/**
* @return Name of the world
*/
inline const std::string& PhysicsWorld::getName() const {
RP3D_FORCE_INLINE const std::string& PhysicsWorld::getName() const {
return mName;
}
@ -598,7 +585,7 @@ inline const std::string& PhysicsWorld::getName() const {
/**
* @return A pointer to the profiler
*/
inline Profiler* PhysicsWorld::getProfiler() {
RP3D_FORCE_INLINE Profiler* PhysicsWorld::getProfiler() {
return mProfiler;
}
@ -608,7 +595,7 @@ inline Profiler* PhysicsWorld::getProfiler() {
/**
* @return The number of iterations of the velocity constraint solver
*/
inline uint PhysicsWorld::getNbIterationsVelocitySolver() const {
RP3D_FORCE_INLINE uint16 PhysicsWorld::getNbIterationsVelocitySolver() const {
return mNbVelocitySolverIterations;
}
@ -616,7 +603,7 @@ inline uint PhysicsWorld::getNbIterationsVelocitySolver() const {
/**
* @return The number of iterations of the position constraint solver
*/
inline uint PhysicsWorld::getNbIterationsPositionSolver() const {
RP3D_FORCE_INLINE uint16 PhysicsWorld::getNbIterationsPositionSolver() const {
return mNbPositionSolverIterations;
}
@ -624,7 +611,7 @@ inline uint PhysicsWorld::getNbIterationsPositionSolver() const {
/**
* @param technique Technique used for the position correction (Baumgarte or Split Impulses)
*/
inline void PhysicsWorld::setContactsPositionCorrectionTechnique(
RP3D_FORCE_INLINE void PhysicsWorld::setContactsPositionCorrectionTechnique(
ContactsPositionCorrectionTechnique technique) {
if (technique == ContactsPositionCorrectionTechnique::BAUMGARTE_CONTACTS) {
mContactSolverSystem.setIsSplitImpulseActive(false);
@ -634,25 +621,11 @@ inline void PhysicsWorld::setContactsPositionCorrectionTechnique(
}
}
// Set the position correction technique used for joints
/**
* @param technique Technique used for the joins position correction (Baumgarte or Non Linear Gauss Seidel)
*/
inline void PhysicsWorld::setJointsPositionCorrectionTechnique(
JointsPositionCorrectionTechnique technique) {
if (technique == JointsPositionCorrectionTechnique::BAUMGARTE_JOINTS) {
mConstraintSolverSystem.setIsNonLinearGaussSeidelPositionCorrectionActive(false);
}
else {
mConstraintSolverSystem.setIsNonLinearGaussSeidelPositionCorrectionActive(true);
}
}
// Return the gravity vector of the world
/**
* @return The current gravity vector (in meter per seconds squared)
*/
inline Vector3 PhysicsWorld::getGravity() const {
RP3D_FORCE_INLINE Vector3 PhysicsWorld::getGravity() const {
return mConfig.gravity;
}
@ -660,7 +633,7 @@ inline Vector3 PhysicsWorld::getGravity() const {
/**
* @return True if the gravity is enabled in the world
*/
inline bool PhysicsWorld::isGravityEnabled() const {
RP3D_FORCE_INLINE bool PhysicsWorld::isGravityEnabled() const {
return mIsGravityEnabled;
}
@ -668,7 +641,7 @@ inline bool PhysicsWorld::isGravityEnabled() const {
/**
* @return True if the sleeping technique is enabled and false otherwise
*/
inline bool PhysicsWorld::isSleepingEnabled() const {
RP3D_FORCE_INLINE bool PhysicsWorld::isSleepingEnabled() const {
return mIsSleepingEnabled;
}
@ -676,7 +649,7 @@ inline bool PhysicsWorld::isSleepingEnabled() const {
/**
* @return The sleep linear velocity (in meters per second)
*/
inline decimal PhysicsWorld::getSleepLinearVelocity() const {
RP3D_FORCE_INLINE decimal PhysicsWorld::getSleepLinearVelocity() const {
return mSleepLinearVelocity;
}
@ -684,7 +657,7 @@ inline decimal PhysicsWorld::getSleepLinearVelocity() const {
/**
* @return The sleep angular velocity (in radian per second)
*/
inline decimal PhysicsWorld::getSleepAngularVelocity() const {
RP3D_FORCE_INLINE decimal PhysicsWorld::getSleepAngularVelocity() const {
return mSleepAngularVelocity;
}
@ -692,7 +665,7 @@ inline decimal PhysicsWorld::getSleepAngularVelocity() const {
/**
* @return Time a body is required to stay still before sleeping (in seconds)
*/
inline decimal PhysicsWorld::getTimeBeforeSleep() const {
RP3D_FORCE_INLINE decimal PhysicsWorld::getTimeBeforeSleep() const {
return mTimeBeforeSleep;
}
@ -702,7 +675,7 @@ inline decimal PhysicsWorld::getTimeBeforeSleep() const {
* @param eventListener Pointer to the event listener object that will receive
* event callbacks during the simulation
*/
inline void PhysicsWorld::setEventListener(EventListener* eventListener) {
RP3D_FORCE_INLINE void PhysicsWorld::setEventListener(EventListener* eventListener) {
mEventListener = eventListener;
}
@ -711,23 +684,23 @@ inline void PhysicsWorld::setEventListener(EventListener* eventListener) {
/**
* @return The number of collision bodies in the physics world
*/
inline uint PhysicsWorld::getNbCollisionBodies() const {
return mCollisionBodies.size();
RP3D_FORCE_INLINE uint32 PhysicsWorld::getNbCollisionBodies() const {
return static_cast<uint32>(mCollisionBodies.size());
}
// Return the number of RigidBody in the physics world
/**
* @return The number of rigid bodies in the physics world
*/
inline uint PhysicsWorld::getNbRigidBodies() const {
return mRigidBodies.size();
RP3D_FORCE_INLINE uint32 PhysicsWorld::getNbRigidBodies() const {
return static_cast<uint32>(mRigidBodies.size());
}
// Return true if the debug rendering is enabled
/**
* @return True if the debug rendering is enabled and false otherwise
*/
inline bool PhysicsWorld::getIsDebugRenderingEnabled() const {
RP3D_FORCE_INLINE bool PhysicsWorld::getIsDebugRenderingEnabled() const {
return mIsDebugRenderingEnabled;
}
@ -735,7 +708,7 @@ inline bool PhysicsWorld::getIsDebugRenderingEnabled() const {
/**
* @param isEnabled True if you want to enable the debug rendering and false otherwise
*/
inline void PhysicsWorld::setIsDebugRenderingEnabled(bool isEnabled) {
RP3D_FORCE_INLINE void PhysicsWorld::setIsDebugRenderingEnabled(bool isEnabled) {
mIsDebugRenderingEnabled = isEnabled;
}
@ -743,7 +716,7 @@ inline void PhysicsWorld::setIsDebugRenderingEnabled(bool isEnabled) {
/**
* @return A reference to the DebugRenderer object of the world
*/
inline DebugRenderer& PhysicsWorld::getDebugRenderer() {
RP3D_FORCE_INLINE DebugRenderer& PhysicsWorld::getDebugRenderer() {
return mDebugRenderer;
}

View File

@ -1,196 +0,0 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
*********************************************************************************
* *
* 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 REACTPHYSICS3D_TIMER_H
#define REACTPHYSICS3D_TIMER_H
// Libraries
#include <ctime>
#include <cassert>
#include <reactphysics3d/configuration.h>
#if defined(WINDOWS_OS) // For Windows platform
#define NOMINMAX // This is used to avoid definition of max() and min() macros
#include <windows.h>
#else // For Mac OS or Linux platform
#include <sys/time.h>
#endif
/// Namespace ReactPhysics3D
namespace reactphysics3d {
// Class Timer
/**
* This class will take care of the time in the physics engine. It
* uses functions that depend on the current platform to get the
* current time.
*/
class Timer {
private :
// -------------------- Attributes -------------------- //
/// Timestep dt of the physics engine (timestep > 0.0)
double mTimeStep;
/// Last time the timer has been updated
long double mLastUpdateTime;
/// Time difference between the two last timer update() calls
long double mDeltaTime;
/// Used to fix the time step and avoid strange time effects
double mAccumulator;
/// True if the timer is running
bool mIsRunning;
public :
// -------------------- Methods -------------------- //
/// Constructor
Timer(double timeStep);
/// Destructor
~Timer() = default;
/// Deleted copy-constructor
Timer(const Timer& timer) = delete;
/// Deleted assignment operator
Timer& operator=(const Timer& timer) = delete;
/// Return the timestep of the physics engine
double getTimeStep() const;
/// Set the timestep of the physics engine
void setTimeStep(double timeStep);
/// Return the current time of the physics engine
long double getPhysicsTime() const;
/// Start the timer
void start();
/// Stop the timer
void stop();
/// Return true if the timer is running
bool getIsRunning() const;
/// True if it's possible to take a new step
bool isPossibleToTakeStep() const;
/// Compute the time since the last update() call and add it to the accumulator
void update();
/// Take a new step => update the timer by adding the timeStep value to the current time
void nextStep();
/// Compute the interpolation factor
decimal computeInterpolationFactor();
/// Return the current time of the system in seconds
static long double getCurrentSystemTime();
};
// Return the timestep of the physics engine
inline double Timer::getTimeStep() const {
return mTimeStep;
}
// Set the timestep of the physics engine
inline void Timer::setTimeStep(double timeStep) {
assert(timeStep > 0.0f);
mTimeStep = timeStep;
}
// Return the current time
inline long double Timer::getPhysicsTime() const {
return mLastUpdateTime;
}
// Return if the timer is running
inline bool Timer::getIsRunning() const {
return mIsRunning;
}
// Start the timer
inline void Timer::start() {
if (!mIsRunning) {
// Get the current system time
mLastUpdateTime = getCurrentSystemTime();
mAccumulator = 0.0;
mIsRunning = true;
}
}
// Stop the timer
inline void Timer::stop() {
mIsRunning = false;
}
// True if it's possible to take a new step
inline bool Timer::isPossibleToTakeStep() const {
return (mAccumulator >= mTimeStep);
}
// Take a new step => update the timer by adding the timeStep value to the current time
inline void Timer::nextStep() {
assert(mIsRunning);
// Update the accumulator value
mAccumulator -= mTimeStep;
}
// Compute the interpolation factor
inline decimal Timer::computeInterpolationFactor() {
return (decimal(mAccumulator / mTimeStep));
}
// Compute the time since the last update() call and add it to the accumulator
inline void Timer::update() {
// Get the current system time
long double currentTime = getCurrentSystemTime();
// Compute the delta display time between two display frames
mDeltaTime = currentTime - mLastUpdateTime;
// Update the current display time
mLastUpdateTime = currentTime;
// Update the accumulator value
mAccumulator += mDeltaTime;
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -59,15 +59,6 @@ class Matrix2x2 {
/// Constructor
Matrix2x2(decimal a1, decimal a2, decimal b1, decimal b2);
/// Destructor
~Matrix2x2() = default;
/// Copy-constructor
Matrix2x2(const Matrix2x2& matrix);
/// Assignment operator
Matrix2x2& operator=(const Matrix2x2& matrix);
/// Set all the values in the matrix
void setAllValues(decimal a1, decimal a2, decimal b1, decimal b2);
@ -92,6 +83,9 @@ class Matrix2x2 {
/// Return the inverse matrix
Matrix2x2 getInverse() const;
/// Return the inverse matrix
Matrix2x2 getInverse(decimal determinant) const;
/// Return the matrix with absolute values
Matrix2x2 getAbsoluteMatrix() const;
@ -151,57 +145,51 @@ class Matrix2x2 {
};
// Constructor of the class Matrix2x2
inline Matrix2x2::Matrix2x2() {
RP3D_FORCE_INLINE Matrix2x2::Matrix2x2() {
// Initialize all values in the matrix to zero
setAllValues(0.0, 0.0, 0.0, 0.0);
}
// Constructor
inline Matrix2x2::Matrix2x2(decimal value) {
RP3D_FORCE_INLINE Matrix2x2::Matrix2x2(decimal value) {
setAllValues(value, value, value, value);
}
// Constructor with arguments
inline Matrix2x2::Matrix2x2(decimal a1, decimal a2, decimal b1, decimal b2) {
RP3D_FORCE_INLINE Matrix2x2::Matrix2x2(decimal a1, decimal a2, decimal b1, decimal b2) {
// Initialize the matrix with the values
setAllValues(a1, a2, b1, b2);
}
// Copy-constructor
inline Matrix2x2::Matrix2x2(const Matrix2x2& matrix) {
setAllValues(matrix.mRows[0][0], matrix.mRows[0][1],
matrix.mRows[1][0], matrix.mRows[1][1]);
}
// Method to set all the values in the matrix
inline void Matrix2x2::setAllValues(decimal a1, decimal a2,
RP3D_FORCE_INLINE void Matrix2x2::setAllValues(decimal a1, decimal a2,
decimal b1, decimal b2) {
mRows[0][0] = a1; mRows[0][1] = a2;
mRows[1][0] = b1; mRows[1][1] = b2;
}
// Set the matrix to zero
inline void Matrix2x2::setToZero() {
RP3D_FORCE_INLINE void Matrix2x2::setToZero() {
mRows[0].setToZero();
mRows[1].setToZero();
}
// Return a column
inline Vector2 Matrix2x2::getColumn(int i) const {
RP3D_FORCE_INLINE Vector2 Matrix2x2::getColumn(int i) const {
assert(i>= 0 && i<2);
return Vector2(mRows[0][i], mRows[1][i]);
}
// Return a row
inline Vector2 Matrix2x2::getRow(int i) const {
RP3D_FORCE_INLINE Vector2 Matrix2x2::getRow(int i) const {
assert(i>= 0 && i<2);
return mRows[i];
}
// Return the transpose matrix
inline Matrix2x2 Matrix2x2::getTranspose() const {
RP3D_FORCE_INLINE Matrix2x2 Matrix2x2::getTranspose() const {
// Return the transpose matrix
return Matrix2x2(mRows[0][0], mRows[1][0],
@ -209,45 +197,51 @@ inline Matrix2x2 Matrix2x2::getTranspose() const {
}
// Return the determinant of the matrix
inline decimal Matrix2x2::getDeterminant() const {
RP3D_FORCE_INLINE decimal Matrix2x2::getDeterminant() const {
// Compute and return the determinant of the matrix
return mRows[0][0] * mRows[1][1] - mRows[1][0] * mRows[0][1];
}
// Return the trace of the matrix
inline decimal Matrix2x2::getTrace() const {
RP3D_FORCE_INLINE decimal Matrix2x2::getTrace() const {
// Compute and return the trace
return (mRows[0][0] + mRows[1][1]);
}
// Set the matrix to the identity matrix
inline void Matrix2x2::setToIdentity() {
RP3D_FORCE_INLINE void Matrix2x2::setToIdentity() {
mRows[0][0] = 1.0; mRows[0][1] = 0.0;
mRows[1][0] = 0.0; mRows[1][1] = 1.0;
}
// Return the 2x2 identity matrix
inline Matrix2x2 Matrix2x2::identity() {
RP3D_FORCE_INLINE Matrix2x2 Matrix2x2::identity() {
// Return the isdentity matrix
return Matrix2x2(1.0, 0.0, 0.0, 1.0);
}
// Return the 2x2 zero matrix
inline Matrix2x2 Matrix2x2::zero() {
RP3D_FORCE_INLINE Matrix2x2 Matrix2x2::zero() {
return Matrix2x2(0.0, 0.0, 0.0, 0.0);
}
// Return the inverse matrix
RP3D_FORCE_INLINE Matrix2x2 Matrix2x2::getInverse() const {
return getInverse(getDeterminant());
}
// Return the matrix with absolute values
inline Matrix2x2 Matrix2x2::getAbsoluteMatrix() const {
return Matrix2x2(fabs(mRows[0][0]), fabs(mRows[0][1]),
fabs(mRows[1][0]), fabs(mRows[1][1]));
RP3D_FORCE_INLINE Matrix2x2 Matrix2x2::getAbsoluteMatrix() const {
return Matrix2x2(std::abs(mRows[0][0]), std::abs(mRows[0][1]),
std::abs(mRows[1][0]), std::abs(mRows[1][1]));
}
// Overloaded operator for addition
inline Matrix2x2 operator+(const Matrix2x2& matrix1, const Matrix2x2& matrix2) {
RP3D_FORCE_INLINE Matrix2x2 operator+(const Matrix2x2& matrix1, const Matrix2x2& matrix2) {
return Matrix2x2(matrix1.mRows[0][0] + matrix2.mRows[0][0],
matrix1.mRows[0][1] + matrix2.mRows[0][1],
matrix1.mRows[1][0] + matrix2.mRows[1][0],
@ -255,7 +249,7 @@ inline Matrix2x2 operator+(const Matrix2x2& matrix1, const Matrix2x2& matrix2) {
}
// Overloaded operator for substraction
inline Matrix2x2 operator-(const Matrix2x2& matrix1, const Matrix2x2& matrix2) {
RP3D_FORCE_INLINE Matrix2x2 operator-(const Matrix2x2& matrix1, const Matrix2x2& matrix2) {
return Matrix2x2(matrix1.mRows[0][0] - matrix2.mRows[0][0],
matrix1.mRows[0][1] - matrix2.mRows[0][1],
matrix1.mRows[1][0] - matrix2.mRows[1][0],
@ -263,24 +257,24 @@ inline Matrix2x2 operator-(const Matrix2x2& matrix1, const Matrix2x2& matrix2) {
}
// Overloaded operator for the negative of the matrix
inline Matrix2x2 operator-(const Matrix2x2& matrix) {
RP3D_FORCE_INLINE Matrix2x2 operator-(const Matrix2x2& matrix) {
return Matrix2x2(-matrix.mRows[0][0], -matrix.mRows[0][1],
-matrix.mRows[1][0], -matrix.mRows[1][1]);
}
// Overloaded operator for multiplication with a number
inline Matrix2x2 operator*(decimal nb, const Matrix2x2& matrix) {
RP3D_FORCE_INLINE Matrix2x2 operator*(decimal nb, const Matrix2x2& matrix) {
return Matrix2x2(matrix.mRows[0][0] * nb, matrix.mRows[0][1] * nb,
matrix.mRows[1][0] * nb, matrix.mRows[1][1] * nb);
}
// Overloaded operator for multiplication with a matrix
inline Matrix2x2 operator*(const Matrix2x2& matrix, decimal nb) {
RP3D_FORCE_INLINE Matrix2x2 operator*(const Matrix2x2& matrix, decimal nb) {
return nb * matrix;
}
// Overloaded operator for matrix multiplication
inline Matrix2x2 operator*(const Matrix2x2& matrix1, const Matrix2x2& matrix2) {
RP3D_FORCE_INLINE Matrix2x2 operator*(const Matrix2x2& matrix1, const Matrix2x2& matrix2) {
return Matrix2x2(matrix1.mRows[0][0] * matrix2.mRows[0][0] + matrix1.mRows[0][1] *
matrix2.mRows[1][0],
matrix1.mRows[0][0] * matrix2.mRows[0][1] + matrix1.mRows[0][1] *
@ -292,38 +286,38 @@ inline Matrix2x2 operator*(const Matrix2x2& matrix1, const Matrix2x2& matrix2) {
}
// Overloaded operator for multiplication with a vector
inline Vector2 operator*(const Matrix2x2& matrix, const Vector2& vector) {
RP3D_FORCE_INLINE Vector2 operator*(const Matrix2x2& matrix, const Vector2& vector) {
return Vector2(matrix.mRows[0][0]*vector.x + matrix.mRows[0][1]*vector.y,
matrix.mRows[1][0]*vector.x + matrix.mRows[1][1]*vector.y);
}
// Overloaded operator for equality condition
inline bool Matrix2x2::operator==(const Matrix2x2& matrix) const {
RP3D_FORCE_INLINE bool Matrix2x2::operator==(const Matrix2x2& matrix) const {
return (mRows[0][0] == matrix.mRows[0][0] && mRows[0][1] == matrix.mRows[0][1] &&
mRows[1][0] == matrix.mRows[1][0] && mRows[1][1] == matrix.mRows[1][1]);
}
// Overloaded operator for the is different condition
inline bool Matrix2x2::operator!= (const Matrix2x2& matrix) const {
RP3D_FORCE_INLINE bool Matrix2x2::operator!= (const Matrix2x2& matrix) const {
return !(*this == matrix);
}
// Overloaded operator for addition with assignment
inline Matrix2x2& Matrix2x2::operator+=(const Matrix2x2& matrix) {
RP3D_FORCE_INLINE Matrix2x2& Matrix2x2::operator+=(const Matrix2x2& matrix) {
mRows[0][0] += matrix.mRows[0][0]; mRows[0][1] += matrix.mRows[0][1];
mRows[1][0] += matrix.mRows[1][0]; mRows[1][1] += matrix.mRows[1][1];
return *this;
}
// Overloaded operator for substraction with assignment
inline Matrix2x2& Matrix2x2::operator-=(const Matrix2x2& matrix) {
RP3D_FORCE_INLINE Matrix2x2& Matrix2x2::operator-=(const Matrix2x2& matrix) {
mRows[0][0] -= matrix.mRows[0][0]; mRows[0][1] -= matrix.mRows[0][1];
mRows[1][0] -= matrix.mRows[1][0]; mRows[1][1] -= matrix.mRows[1][1];
return *this;
}
// Overloaded operator for multiplication with a number with assignment
inline Matrix2x2& Matrix2x2::operator*=(decimal nb) {
RP3D_FORCE_INLINE Matrix2x2& Matrix2x2::operator*=(decimal nb) {
mRows[0][0] *= nb; mRows[0][1] *= nb;
mRows[1][0] *= nb; mRows[1][1] *= nb;
return *this;
@ -332,19 +326,19 @@ inline Matrix2x2& Matrix2x2::operator*=(decimal nb) {
// Overloaded operator to return a row of the matrix.
/// This operator is also used to access a matrix value using the syntax
/// matrix[row][col].
inline const Vector2& Matrix2x2::operator[](int row) const {
RP3D_FORCE_INLINE const Vector2& Matrix2x2::operator[](int row) const {
return mRows[row];
}
// Overloaded operator to return a row of the matrix.
/// This operator is also used to access a matrix value using the syntax
/// matrix[row][col].
inline Vector2& Matrix2x2::operator[](int row) {
RP3D_FORCE_INLINE Vector2& Matrix2x2::operator[](int row) {
return mRows[row];
}
// Get the string representation
inline std::string Matrix2x2::to_string() const {
RP3D_FORCE_INLINE std::string Matrix2x2::to_string() const {
return "Matrix2x2(" + std::to_string(mRows[0][0]) + "," + std::to_string(mRows[0][1]) + "," +
std::to_string(mRows[1][0]) + "," + std::to_string(mRows[1][1]) + ")";
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -61,15 +61,6 @@ class Matrix3x3 {
Matrix3x3(decimal a1, decimal a2, decimal a3, decimal b1, decimal b2, decimal b3,
decimal c1, decimal c2, decimal c3);
/// Destructor
~Matrix3x3() = default;
/// Copy-constructor
Matrix3x3(const Matrix3x3& matrix);
/// Assignment operator
Matrix3x3& operator=(const Matrix3x3& matrix);
/// Set all the values in the matrix
void setAllValues(decimal a1, decimal a2, decimal a3, decimal b1, decimal b2, decimal b3,
decimal c1, decimal c2, decimal c3);
@ -95,6 +86,9 @@ class Matrix3x3 {
/// Return the inverse matrix
Matrix3x3 getInverse() const;
/// Return the inverse matrix
Matrix3x3 getInverse(decimal determinant) const;
/// Return the matrix with absolute values
Matrix3x3 getAbsoluteMatrix() const;
@ -158,33 +152,26 @@ class Matrix3x3 {
};
// Constructor of the class Matrix3x3
inline Matrix3x3::Matrix3x3() {
RP3D_FORCE_INLINE Matrix3x3::Matrix3x3() {
// Initialize all values in the matrix to zero
setAllValues(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
}
// Constructor
inline Matrix3x3::Matrix3x3(decimal value) {
RP3D_FORCE_INLINE Matrix3x3::Matrix3x3(decimal value) {
setAllValues(value, value, value, value, value, value, value, value, value);
}
// Constructor with arguments
inline Matrix3x3::Matrix3x3(decimal a1, decimal a2, decimal a3,
RP3D_FORCE_INLINE Matrix3x3::Matrix3x3(decimal a1, decimal a2, decimal a3,
decimal b1, decimal b2, decimal b3,
decimal c1, decimal c2, decimal c3) {
// Initialize the matrix with the values
setAllValues(a1, a2, a3, b1, b2, b3, c1, c2, c3);
}
// Copy-constructor
inline Matrix3x3::Matrix3x3(const Matrix3x3& matrix) {
setAllValues(matrix.mRows[0][0], matrix.mRows[0][1], matrix.mRows[0][2],
matrix.mRows[1][0], matrix.mRows[1][1], matrix.mRows[1][2],
matrix.mRows[2][0], matrix.mRows[2][1], matrix.mRows[2][2]);
}
// Method to set all the values in the matrix
inline void Matrix3x3::setAllValues(decimal a1, decimal a2, decimal a3,
RP3D_FORCE_INLINE void Matrix3x3::setAllValues(decimal a1, decimal a2, decimal a3,
decimal b1, decimal b2, decimal b3,
decimal c1, decimal c2, decimal c3) {
mRows[0][0] = a1; mRows[0][1] = a2; mRows[0][2] = a3;
@ -193,26 +180,26 @@ inline void Matrix3x3::setAllValues(decimal a1, decimal a2, decimal a3,
}
// Set the matrix to zero
inline void Matrix3x3::setToZero() {
RP3D_FORCE_INLINE void Matrix3x3::setToZero() {
mRows[0].setToZero();
mRows[1].setToZero();
mRows[2].setToZero();
}
// Return a column
inline Vector3 Matrix3x3::getColumn(int i) const {
RP3D_FORCE_INLINE Vector3 Matrix3x3::getColumn(int i) const {
assert(i>= 0 && i<3);
return Vector3(mRows[0][i], mRows[1][i], mRows[2][i]);
}
// Return a row
inline Vector3 Matrix3x3::getRow(int i) const {
RP3D_FORCE_INLINE Vector3 Matrix3x3::getRow(int i) const {
assert(i>= 0 && i<3);
return mRows[i];
}
// Return the transpose matrix
inline Matrix3x3 Matrix3x3::getTranspose() const {
RP3D_FORCE_INLINE Matrix3x3 Matrix3x3::getTranspose() const {
// Return the transpose matrix
return Matrix3x3(mRows[0][0], mRows[1][0], mRows[2][0],
@ -221,7 +208,7 @@ inline Matrix3x3 Matrix3x3::getTranspose() const {
}
// Return the determinant of the matrix
inline decimal Matrix3x3::getDeterminant() const {
RP3D_FORCE_INLINE decimal Matrix3x3::getDeterminant() const {
// Compute and return the determinant of the matrix
return (mRows[0][0]*(mRows[1][1]*mRows[2][2]-mRows[2][1]*mRows[1][2]) -
@ -230,44 +217,50 @@ inline decimal Matrix3x3::getDeterminant() const {
}
// Return the trace of the matrix
inline decimal Matrix3x3::getTrace() const {
RP3D_FORCE_INLINE decimal Matrix3x3::getTrace() const {
// Compute and return the trace
return (mRows[0][0] + mRows[1][1] + mRows[2][2]);
}
// Set the matrix to the identity matrix
inline void Matrix3x3::setToIdentity() {
RP3D_FORCE_INLINE void Matrix3x3::setToIdentity() {
mRows[0][0] = 1.0; mRows[0][1] = 0.0; mRows[0][2] = 0.0;
mRows[1][0] = 0.0; mRows[1][1] = 1.0; mRows[1][2] = 0.0;
mRows[2][0] = 0.0; mRows[2][1] = 0.0; mRows[2][2] = 1.0;
}
// Return the 3x3 identity matrix
inline Matrix3x3 Matrix3x3::identity() {
RP3D_FORCE_INLINE Matrix3x3 Matrix3x3::identity() {
return Matrix3x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);
}
// Return the 3x3 zero matrix
inline Matrix3x3 Matrix3x3::zero() {
RP3D_FORCE_INLINE Matrix3x3 Matrix3x3::zero() {
return Matrix3x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
}
// Return the inverse matrix
RP3D_FORCE_INLINE Matrix3x3 Matrix3x3::getInverse() const {
return getInverse(getDeterminant());
}
// Return a skew-symmetric matrix using a given vector that can be used
// to compute cross product with another vector using matrix multiplication
inline Matrix3x3 Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(const Vector3& vector) {
RP3D_FORCE_INLINE Matrix3x3 Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(const Vector3& vector) {
return Matrix3x3(0, -vector.z, vector.y, vector.z, 0, -vector.x, -vector.y, vector.x, 0);
}
// Return the matrix with absolute values
inline Matrix3x3 Matrix3x3::getAbsoluteMatrix() const {
return Matrix3x3(std::fabs(mRows[0][0]), std::fabs(mRows[0][1]), std::fabs(mRows[0][2]),
std::fabs(mRows[1][0]), std::fabs(mRows[1][1]), std::fabs(mRows[1][2]),
std::fabs(mRows[2][0]), std::fabs(mRows[2][1]), std::fabs(mRows[2][2]));
RP3D_FORCE_INLINE Matrix3x3 Matrix3x3::getAbsoluteMatrix() const {
return Matrix3x3(std::abs(mRows[0][0]), std::abs(mRows[0][1]), std::abs(mRows[0][2]),
std::abs(mRows[1][0]), std::abs(mRows[1][1]), std::abs(mRows[1][2]),
std::abs(mRows[2][0]), std::abs(mRows[2][1]), std::abs(mRows[2][2]));
}
// Overloaded operator for addition
inline Matrix3x3 operator+(const Matrix3x3& matrix1, const Matrix3x3& matrix2) {
RP3D_FORCE_INLINE Matrix3x3 operator+(const Matrix3x3& matrix1, const Matrix3x3& matrix2) {
return Matrix3x3(matrix1.mRows[0][0] + matrix2.mRows[0][0], matrix1.mRows[0][1] +
matrix2.mRows[0][1], matrix1.mRows[0][2] + matrix2.mRows[0][2],
matrix1.mRows[1][0] + matrix2.mRows[1][0], matrix1.mRows[1][1] +
@ -277,7 +270,7 @@ inline Matrix3x3 operator+(const Matrix3x3& matrix1, const Matrix3x3& matrix2) {
}
// Overloaded operator for substraction
inline Matrix3x3 operator-(const Matrix3x3& matrix1, const Matrix3x3& matrix2) {
RP3D_FORCE_INLINE Matrix3x3 operator-(const Matrix3x3& matrix1, const Matrix3x3& matrix2) {
return Matrix3x3(matrix1.mRows[0][0] - matrix2.mRows[0][0], matrix1.mRows[0][1] -
matrix2.mRows[0][1], matrix1.mRows[0][2] - matrix2.mRows[0][2],
matrix1.mRows[1][0] - matrix2.mRows[1][0], matrix1.mRows[1][1] -
@ -287,26 +280,26 @@ inline Matrix3x3 operator-(const Matrix3x3& matrix1, const Matrix3x3& matrix2) {
}
// Overloaded operator for the negative of the matrix
inline Matrix3x3 operator-(const Matrix3x3& matrix) {
RP3D_FORCE_INLINE Matrix3x3 operator-(const Matrix3x3& matrix) {
return Matrix3x3(-matrix.mRows[0][0], -matrix.mRows[0][1], -matrix.mRows[0][2],
-matrix.mRows[1][0], -matrix.mRows[1][1], -matrix.mRows[1][2],
-matrix.mRows[2][0], -matrix.mRows[2][1], -matrix.mRows[2][2]);
}
// Overloaded operator for multiplication with a number
inline Matrix3x3 operator*(decimal nb, const Matrix3x3& matrix) {
RP3D_FORCE_INLINE Matrix3x3 operator*(decimal nb, const Matrix3x3& matrix) {
return Matrix3x3(matrix.mRows[0][0] * nb, matrix.mRows[0][1] * nb, matrix.mRows[0][2] * nb,
matrix.mRows[1][0] * nb, matrix.mRows[1][1] * nb, matrix.mRows[1][2] * nb,
matrix.mRows[2][0] * nb, matrix.mRows[2][1] * nb, matrix.mRows[2][2] * nb);
}
// Overloaded operator for multiplication with a matrix
inline Matrix3x3 operator*(const Matrix3x3& matrix, decimal nb) {
RP3D_FORCE_INLINE Matrix3x3 operator*(const Matrix3x3& matrix, decimal nb) {
return nb * matrix;
}
// Overloaded operator for matrix multiplication
inline Matrix3x3 operator*(const Matrix3x3& matrix1, const Matrix3x3& matrix2) {
RP3D_FORCE_INLINE Matrix3x3 operator*(const Matrix3x3& matrix1, const Matrix3x3& matrix2) {
return Matrix3x3(matrix1.mRows[0][0]*matrix2.mRows[0][0] + matrix1.mRows[0][1] *
matrix2.mRows[1][0] + matrix1.mRows[0][2]*matrix2.mRows[2][0],
matrix1.mRows[0][0]*matrix2.mRows[0][1] + matrix1.mRows[0][1] *
@ -328,7 +321,7 @@ inline Matrix3x3 operator*(const Matrix3x3& matrix1, const Matrix3x3& matrix2) {
}
// Overloaded operator for multiplication with a vector
inline Vector3 operator*(const Matrix3x3& matrix, const Vector3& vector) {
RP3D_FORCE_INLINE Vector3 operator*(const Matrix3x3& matrix, const Vector3& vector) {
return Vector3(matrix.mRows[0][0]*vector.x + matrix.mRows[0][1]*vector.y +
matrix.mRows[0][2]*vector.z,
matrix.mRows[1][0]*vector.x + matrix.mRows[1][1]*vector.y +
@ -338,7 +331,7 @@ inline Vector3 operator*(const Matrix3x3& matrix, const Vector3& vector) {
}
// Overloaded operator for equality condition
inline bool Matrix3x3::operator==(const Matrix3x3& matrix) const {
RP3D_FORCE_INLINE bool Matrix3x3::operator==(const Matrix3x3& matrix) const {
return (mRows[0][0] == matrix.mRows[0][0] && mRows[0][1] == matrix.mRows[0][1] &&
mRows[0][2] == matrix.mRows[0][2] &&
mRows[1][0] == matrix.mRows[1][0] && mRows[1][1] == matrix.mRows[1][1] &&
@ -348,12 +341,12 @@ inline bool Matrix3x3::operator==(const Matrix3x3& matrix) const {
}
// Overloaded operator for the is different condition
inline bool Matrix3x3::operator!= (const Matrix3x3& matrix) const {
RP3D_FORCE_INLINE bool Matrix3x3::operator!= (const Matrix3x3& matrix) const {
return !(*this == matrix);
}
// Overloaded operator for addition with assignment
inline Matrix3x3& Matrix3x3::operator+=(const Matrix3x3& matrix) {
RP3D_FORCE_INLINE Matrix3x3& Matrix3x3::operator+=(const Matrix3x3& matrix) {
mRows[0][0] += matrix.mRows[0][0]; mRows[0][1] += matrix.mRows[0][1];
mRows[0][2] += matrix.mRows[0][2]; mRows[1][0] += matrix.mRows[1][0];
mRows[1][1] += matrix.mRows[1][1]; mRows[1][2] += matrix.mRows[1][2];
@ -363,7 +356,7 @@ inline Matrix3x3& Matrix3x3::operator+=(const Matrix3x3& matrix) {
}
// Overloaded operator for substraction with assignment
inline Matrix3x3& Matrix3x3::operator-=(const Matrix3x3& matrix) {
RP3D_FORCE_INLINE Matrix3x3& Matrix3x3::operator-=(const Matrix3x3& matrix) {
mRows[0][0] -= matrix.mRows[0][0]; mRows[0][1] -= matrix.mRows[0][1];
mRows[0][2] -= matrix.mRows[0][2]; mRows[1][0] -= matrix.mRows[1][0];
mRows[1][1] -= matrix.mRows[1][1]; mRows[1][2] -= matrix.mRows[1][2];
@ -373,7 +366,7 @@ inline Matrix3x3& Matrix3x3::operator-=(const Matrix3x3& matrix) {
}
// Overloaded operator for multiplication with a number with assignment
inline Matrix3x3& Matrix3x3::operator*=(decimal nb) {
RP3D_FORCE_INLINE Matrix3x3& Matrix3x3::operator*=(decimal nb) {
mRows[0][0] *= nb; mRows[0][1] *= nb; mRows[0][2] *= nb;
mRows[1][0] *= nb; mRows[1][1] *= nb; mRows[1][2] *= nb;
mRows[2][0] *= nb; mRows[2][1] *= nb; mRows[2][2] *= nb;
@ -383,19 +376,19 @@ inline Matrix3x3& Matrix3x3::operator*=(decimal nb) {
// Overloaded operator to return a row of the matrix.
/// This operator is also used to access a matrix value using the syntax
/// matrix[row][col].
inline const Vector3& Matrix3x3::operator[](int row) const {
RP3D_FORCE_INLINE const Vector3& Matrix3x3::operator[](int row) const {
return mRows[row];
}
// Overloaded operator to return a row of the matrix.
/// This operator is also used to access a matrix value using the syntax
/// matrix[row][col].
inline Vector3& Matrix3x3::operator[](int row) {
RP3D_FORCE_INLINE Vector3& Matrix3x3::operator[](int row) {
return mRows[row];
}
// Get the string representation
inline std::string Matrix3x3::to_string() const {
RP3D_FORCE_INLINE std::string Matrix3x3::to_string() const {
return "Matrix3x3(" + std::to_string(mRows[0][0]) + "," + std::to_string(mRows[0][1]) + "," + std::to_string(mRows[0][2]) + "," +
std::to_string(mRows[1][0]) + "," + std::to_string(mRows[1][1]) + "," + std::to_string(mRows[1][2]) + "," +
std::to_string(mRows[2][0]) + "," + std::to_string(mRows[2][1]) + "," + std::to_string(mRows[2][2]) + ")";

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -73,15 +73,9 @@ struct Quaternion {
/// Constructor with the component w and the vector v=(x y z)
Quaternion(const Vector3& v, decimal newW);
/// Copy-constructor
Quaternion(const Quaternion& quaternion);
/// Create a unit quaternion from a rotation matrix
Quaternion(const Matrix3x3& matrix);
/// Destructor
~Quaternion() = default;
/// Set all the values
void setAllValues(decimal newX, decimal newY, decimal newZ, decimal newW);
@ -166,9 +160,6 @@ struct Quaternion {
/// Overloaded operator for the multiplication with a vector
Vector3 operator*(const Vector3& point) const;
/// Overloaded operator for assignment
Quaternion& operator=(const Quaternion& quaternion);
/// Overloaded operator for equality condition
bool operator==(const Quaternion& quaternion) const;
@ -182,28 +173,28 @@ struct Quaternion {
};
// Constructor of the class
inline Quaternion::Quaternion() : x(0.0), y(0.0), z(0.0), w(0.0) {
RP3D_FORCE_INLINE Quaternion::Quaternion() : x(0.0), y(0.0), z(0.0), w(0.0) {
}
// Constructor with arguments
inline Quaternion::Quaternion(decimal newX, decimal newY, decimal newZ, decimal newW)
RP3D_FORCE_INLINE Quaternion::Quaternion(decimal newX, decimal newY, decimal newZ, decimal newW)
:x(newX), y(newY), z(newZ), w(newW) {
}
// Constructor with the component w and the vector v=(x y z)
inline Quaternion::Quaternion(decimal newW, const Vector3& v) : x(v.x), y(v.y), z(v.z), w(newW) {
RP3D_FORCE_INLINE Quaternion::Quaternion(decimal newW, const Vector3& v) : x(v.x), y(v.y), z(v.z), w(newW) {
}
// Constructor with the component w and the vector v=(x y z)
inline Quaternion::Quaternion(const Vector3& v, decimal newW) : x(v.x), y(v.y), z(v.z), w(newW) {
RP3D_FORCE_INLINE Quaternion::Quaternion(const Vector3& v, decimal newW) : x(v.x), y(v.y), z(v.z), w(newW) {
}
// Set all the values
inline void Quaternion::setAllValues(decimal newX, decimal newY, decimal newZ, decimal newW) {
RP3D_FORCE_INLINE void Quaternion::setAllValues(decimal newX, decimal newY, decimal newZ, decimal newW) {
x = newX;
y = newY;
z = newZ;
@ -211,7 +202,7 @@ inline void Quaternion::setAllValues(decimal newX, decimal newY, decimal newZ, d
}
// Set the quaternion to zero
inline void Quaternion::setToZero() {
RP3D_FORCE_INLINE void Quaternion::setToZero() {
x = 0;
y = 0;
z = 0;
@ -219,7 +210,7 @@ inline void Quaternion::setToZero() {
}
// Set to the identity quaternion
inline void Quaternion::setToIdentity() {
RP3D_FORCE_INLINE void Quaternion::setToIdentity() {
x = 0;
y = 0;
z = 0;
@ -227,24 +218,24 @@ inline void Quaternion::setToIdentity() {
}
// Return the vector v=(x y z) of the quaternion
inline Vector3 Quaternion::getVectorV() const {
RP3D_FORCE_INLINE Vector3 Quaternion::getVectorV() const {
// Return the vector v
return Vector3(x, y, z);
}
// Return the length of the quaternion (inline)
inline decimal Quaternion::length() const {
// Return the length of the quaternion (RP3D_FORCE_INLINE)
RP3D_FORCE_INLINE decimal Quaternion::length() const {
return std::sqrt(x*x + y*y + z*z + w*w);
}
// Return the square of the length of the quaternion
inline decimal Quaternion::lengthSquare() const {
RP3D_FORCE_INLINE decimal Quaternion::lengthSquare() const {
return x*x + y*y + z*z + w*w;
}
// Normalize the quaternion
inline void Quaternion::normalize() {
RP3D_FORCE_INLINE void Quaternion::normalize() {
decimal l = length();
@ -258,7 +249,7 @@ inline void Quaternion::normalize() {
}
// Inverse the quaternion
inline void Quaternion::inverse() {
RP3D_FORCE_INLINE void Quaternion::inverse() {
// Use the conjugate of the current quaternion
x = -x;
@ -267,7 +258,7 @@ inline void Quaternion::inverse() {
}
// Return the unit quaternion
inline Quaternion Quaternion::getUnit() const {
RP3D_FORCE_INLINE Quaternion Quaternion::getUnit() const {
decimal lengthQuaternion = length();
// Check if the length is not equal to zero
@ -279,60 +270,60 @@ inline Quaternion Quaternion::getUnit() const {
}
// Return the identity quaternion
inline Quaternion Quaternion::identity() {
RP3D_FORCE_INLINE Quaternion Quaternion::identity() {
return Quaternion(0.0, 0.0, 0.0, 1.0);
}
// Return the conjugate of the quaternion (inline)
inline Quaternion Quaternion::getConjugate() const {
// Return the conjugate of the quaternion (RP3D_FORCE_INLINE)
RP3D_FORCE_INLINE Quaternion Quaternion::getConjugate() const {
return Quaternion(-x, -y, -z, w);
}
// Return the inverse of the quaternion (inline)
inline Quaternion Quaternion::getInverse() const {
// Return the inverse of the quaternion (RP3D_FORCE_INLINE)
RP3D_FORCE_INLINE Quaternion Quaternion::getInverse() const {
// Return the conjugate quaternion
return Quaternion(-x, -y, -z, w);
}
// Scalar product between two quaternions
inline decimal Quaternion::dot(const Quaternion& quaternion) const {
RP3D_FORCE_INLINE decimal Quaternion::dot(const Quaternion& quaternion) const {
return (x*quaternion.x + y*quaternion.y + z*quaternion.z + w*quaternion.w);
}
// Return true if the values are not NAN OR INF
inline bool Quaternion::isFinite() const {
RP3D_FORCE_INLINE bool Quaternion::isFinite() const {
return std::isfinite(x) && std::isfinite(y) && std::isfinite(z) && std::isfinite(w);
}
// Return true if it is a unit quaternion
inline bool Quaternion::isUnit() const {
RP3D_FORCE_INLINE bool Quaternion::isUnit() const {
const decimal length = std::sqrt(x*x + y*y + z*z + w*w);
const decimal tolerance = 1e-5f;
return std::abs(length - decimal(1.0)) < tolerance;
}
// Return true if it is a valid quaternion
inline bool Quaternion::isValid() const {
RP3D_FORCE_INLINE bool Quaternion::isValid() const {
return isFinite() && isUnit();
}
// Overloaded operator for the addition of two quaternions
inline Quaternion Quaternion::operator+(const Quaternion& quaternion) const {
RP3D_FORCE_INLINE Quaternion Quaternion::operator+(const Quaternion& quaternion) const {
// Return the result quaternion
return Quaternion(x + quaternion.x, y + quaternion.y, z + quaternion.z, w + quaternion.w);
}
// Overloaded operator for the substraction of two quaternions
inline Quaternion Quaternion::operator-(const Quaternion& quaternion) const {
RP3D_FORCE_INLINE Quaternion Quaternion::operator-(const Quaternion& quaternion) const {
// Return the result of the substraction
return Quaternion(x - quaternion.x, y - quaternion.y, z - quaternion.z, w - quaternion.w);
}
// Overloaded operator for addition with assignment
inline Quaternion& Quaternion::operator+=(const Quaternion& quaternion) {
RP3D_FORCE_INLINE Quaternion& Quaternion::operator+=(const Quaternion& quaternion) {
x += quaternion.x;
y += quaternion.y;
z += quaternion.z;
@ -341,7 +332,7 @@ inline Quaternion& Quaternion::operator+=(const Quaternion& quaternion) {
}
// Overloaded operator for substraction with assignment
inline Quaternion& Quaternion::operator-=(const Quaternion& quaternion) {
RP3D_FORCE_INLINE Quaternion& Quaternion::operator-=(const Quaternion& quaternion) {
x -= quaternion.x;
y -= quaternion.y;
z -= quaternion.z;
@ -350,12 +341,12 @@ inline Quaternion& Quaternion::operator-=(const Quaternion& quaternion) {
}
// Overloaded operator for the multiplication with a constant
inline Quaternion Quaternion::operator*(decimal nb) const {
RP3D_FORCE_INLINE Quaternion Quaternion::operator*(decimal nb) const {
return Quaternion(nb * x, nb * y, nb * z, nb * w);
}
// Overloaded operator for the multiplication of two quaternions
inline Quaternion Quaternion::operator*(const Quaternion& quaternion) const {
RP3D_FORCE_INLINE Quaternion Quaternion::operator*(const Quaternion& quaternion) const {
/* The followin code is equivalent to this
return Quaternion(w * quaternion.w - getVectorV().dot(quaternion.getVectorV()),
@ -371,7 +362,7 @@ inline Quaternion Quaternion::operator*(const Quaternion& quaternion) const {
// Overloaded operator for the multiplication with a vector.
/// This methods rotates a point given the rotation of a quaternion.
inline Vector3 Quaternion::operator*(const Vector3& point) const {
RP3D_FORCE_INLINE Vector3 Quaternion::operator*(const Vector3& point) const {
/* The following code is equivalent to this
* Quaternion p(point.x, point.y, point.z, 0.0);
@ -387,29 +378,14 @@ inline Vector3 Quaternion::operator*(const Vector3& point) const {
w * prodZ - prodX * y + prodY * x - prodW * z);
}
// Overloaded operator for the assignment
inline Quaternion& Quaternion::operator=(const Quaternion& quaternion) {
// Check for self-assignment
if (this != &quaternion) {
x = quaternion.x;
y = quaternion.y;
z = quaternion.z;
w = quaternion.w;
}
// Return this quaternion
return *this;
}
// Overloaded operator for equality condition
inline bool Quaternion::operator==(const Quaternion& quaternion) const {
RP3D_FORCE_INLINE bool Quaternion::operator==(const Quaternion& quaternion) const {
return (x == quaternion.x && y == quaternion.y &&
z == quaternion.z && w == quaternion.w);
}
// Get the string representation
inline std::string Quaternion::to_string() const {
RP3D_FORCE_INLINE std::string Quaternion::to_string() const {
return "Quaternion(" + std::to_string(x) + "," + std::to_string(y) + "," + std::to_string(z) + "," +
std::to_string(w) + ")";
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -60,24 +60,6 @@ struct Ray {
: point1(p1), point2(p2), maxFraction(maxFrac) {
}
/// Copy-constructor
Ray(const Ray& ray) : point1(ray.point1), point2(ray.point2), maxFraction(ray.maxFraction) {
}
/// Destructor
~Ray() = default;
/// Overloaded assignment operator
Ray& operator=(const Ray& ray) {
if (&ray != this) {
point1 = ray.point1;
point2 = ray.point2;
maxFraction = ray.maxFraction;
}
return *this;
}
};
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -63,12 +63,6 @@ class Transform {
/// Constructor
Transform(const Vector3& position, const Quaternion& orientation);
/// Destructor
~Transform() = default;
/// Copy-constructor
Transform(const Transform& transform);
/// Return the origin of the transform
const Vector3& getPosition() const;
@ -116,71 +110,62 @@ class Transform {
/// Return true if the two transforms are different
bool operator!=(const Transform& transform2) const;
/// Assignment operator
Transform& operator=(const Transform& transform);
/// Return the string representation
std::string to_string() const;
};
// Constructor
inline Transform::Transform() : mPosition(Vector3(0.0, 0.0, 0.0)), mOrientation(Quaternion::identity()) {
RP3D_FORCE_INLINE Transform::Transform() : mPosition(Vector3(0.0, 0.0, 0.0)), mOrientation(Quaternion::identity()) {
}
// Constructor
inline Transform::Transform(const Vector3& position, const Matrix3x3& orientation)
RP3D_FORCE_INLINE Transform::Transform(const Vector3& position, const Matrix3x3& orientation)
: mPosition(position), mOrientation(Quaternion(orientation)) {
}
// Constructor
inline Transform::Transform(const Vector3& position, const Quaternion& orientation)
RP3D_FORCE_INLINE Transform::Transform(const Vector3& position, const Quaternion& orientation)
: mPosition(position), mOrientation(orientation) {
}
// Copy-constructor
inline Transform::Transform(const Transform& transform)
: mPosition(transform.mPosition), mOrientation(transform.mOrientation) {
}
// Return the position of the transform
inline const Vector3& Transform::getPosition() const {
RP3D_FORCE_INLINE const Vector3& Transform::getPosition() const {
return mPosition;
}
// Set the origin of the transform
inline void Transform::setPosition(const Vector3& position) {
RP3D_FORCE_INLINE void Transform::setPosition(const Vector3& position) {
mPosition = position;
}
// Return the rotation matrix
inline const Quaternion& Transform::getOrientation() const {
RP3D_FORCE_INLINE const Quaternion& Transform::getOrientation() const {
return mOrientation;
}
// Set the rotation matrix of the transform
inline void Transform::setOrientation(const Quaternion& orientation) {
RP3D_FORCE_INLINE void Transform::setOrientation(const Quaternion& orientation) {
mOrientation = orientation;
}
// Set the transform to the identity transform
inline void Transform::setToIdentity() {
RP3D_FORCE_INLINE void Transform::setToIdentity() {
mPosition = Vector3(0.0, 0.0, 0.0);
mOrientation = Quaternion::identity();
}
// Return the inverse of the transform
inline Transform Transform::getInverse() const {
RP3D_FORCE_INLINE Transform Transform::getInverse() const {
const Quaternion& invQuaternion = mOrientation.getInverse();
return Transform(invQuaternion * (-mPosition), invQuaternion);
}
// Return an interpolated transform
inline Transform Transform::interpolateTransforms(const Transform& oldTransform,
RP3D_FORCE_INLINE Transform Transform::interpolateTransforms(const Transform& oldTransform,
const Transform& newTransform,
decimal interpolationFactor) {
@ -195,22 +180,22 @@ inline Transform Transform::interpolateTransforms(const Transform& oldTransform,
}
// Return the identity transform
inline Transform Transform::identity() {
RP3D_FORCE_INLINE Transform Transform::identity() {
return Transform(Vector3(0, 0, 0), Quaternion::identity());
}
// Return true if it is a valid transform
inline bool Transform::isValid() const {
RP3D_FORCE_INLINE bool Transform::isValid() const {
return mPosition.isFinite() && mOrientation.isValid();
}
// Return the transformed vector
inline Vector3 Transform::operator*(const Vector3& vector) const {
RP3D_FORCE_INLINE Vector3 Transform::operator*(const Vector3& vector) const {
return (mOrientation * vector) + mPosition;
}
// Operator of multiplication of a transform with another one
inline Transform Transform::operator*(const Transform& transform2) const {
RP3D_FORCE_INLINE Transform Transform::operator*(const Transform& transform2) const {
// The following code is equivalent to this
//return Transform(mPosition + mOrientation * transform2.mPosition,
@ -239,26 +224,17 @@ inline Transform Transform::operator*(const Transform& transform2) const {
}
// Return true if the two transforms are equal
inline bool Transform::operator==(const Transform& transform2) const {
RP3D_FORCE_INLINE bool Transform::operator==(const Transform& transform2) const {
return (mPosition == transform2.mPosition) && (mOrientation == transform2.mOrientation);
}
// Return true if the two transforms are different
inline bool Transform::operator!=(const Transform& transform2) const {
RP3D_FORCE_INLINE bool Transform::operator!=(const Transform& transform2) const {
return !(*this == transform2);
}
// Assignment operator
inline Transform& Transform::operator=(const Transform& transform) {
if (&transform != this) {
mPosition = transform.mPosition;
mOrientation = transform.mOrientation;
}
return *this;
}
// Get the string representation
inline std::string Transform::to_string() const {
RP3D_FORCE_INLINE std::string Transform::to_string() const {
return "Transform(" + mPosition.to_string() + "," + mOrientation.to_string() + ")";
}

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -58,12 +58,6 @@ struct Vector2 {
/// Constructor with arguments
Vector2(decimal newX, decimal newY);
/// Copy-constructor
Vector2(const Vector2& vector);
/// Destructor
~Vector2() = default;
/// Set all the values of the vector
void setAllValues(decimal newX, decimal newY);
@ -130,9 +124,6 @@ struct Vector2 {
/// Overloaded operator for value access
const decimal& operator[] (int index) const;
/// Overloaded operator
Vector2& operator=(const Vector2& vector);
/// Overloaded less than operator for ordering to be used inside std::set for instance
bool operator<(const Vector2& vector) const;
@ -161,50 +152,44 @@ struct Vector2 {
};
// Constructor
inline Vector2::Vector2() : x(0.0), y(0.0) {
RP3D_FORCE_INLINE Vector2::Vector2() : x(0.0), y(0.0) {
}
// Constructor with arguments
inline Vector2::Vector2(decimal newX, decimal newY) : x(newX), y(newY) {
RP3D_FORCE_INLINE Vector2::Vector2(decimal newX, decimal newY) : x(newX), y(newY) {
}
// Copy-constructor
inline Vector2::Vector2(const Vector2& vector) : x(vector.x), y(vector.y) {
}
// Set the vector to zero
inline void Vector2::setToZero() {
RP3D_FORCE_INLINE void Vector2::setToZero() {
x = 0;
y = 0;
}
// Set all the values of the vector
inline void Vector2::setAllValues(decimal newX, decimal newY) {
RP3D_FORCE_INLINE void Vector2::setAllValues(decimal newX, decimal newY) {
x = newX;
y = newY;
}
// Return the length of the vector
inline decimal Vector2::length() const {
RP3D_FORCE_INLINE decimal Vector2::length() const {
return std::sqrt(x*x + y*y);
}
// Return the square of the length of the vector
inline decimal Vector2::lengthSquare() const {
RP3D_FORCE_INLINE decimal Vector2::lengthSquare() const {
return x*x + y*y;
}
// Scalar product of two vectors (inline)
inline decimal Vector2::dot(const Vector2& vector) const {
// Scalar product of two vectors (RP3D_FORCE_INLINE)
RP3D_FORCE_INLINE decimal Vector2::dot(const Vector2& vector) const {
return (x*vector.x + y*vector.y);
}
// Normalize the vector
inline void Vector2::normalize() {
RP3D_FORCE_INLINE void Vector2::normalize() {
decimal l = length();
if (l < MACHINE_EPSILON) {
return;
@ -214,68 +199,68 @@ inline void Vector2::normalize() {
}
// Return the corresponding absolute value vector
inline Vector2 Vector2::getAbsoluteVector() const {
RP3D_FORCE_INLINE Vector2 Vector2::getAbsoluteVector() const {
return Vector2(std::abs(x), std::abs(y));
}
// Return the axis with the minimal value
inline int Vector2::getMinAxis() const {
RP3D_FORCE_INLINE int Vector2::getMinAxis() const {
return (x < y ? 0 : 1);
}
// Return the axis with the maximal value
inline int Vector2::getMaxAxis() const {
RP3D_FORCE_INLINE int Vector2::getMaxAxis() const {
return (x < y ? 1 : 0);
}
// Return true if the vector is unit and false otherwise
inline bool Vector2::isUnit() const {
return approxEqual(lengthSquare(), 1.0);
RP3D_FORCE_INLINE bool Vector2::isUnit() const {
return reactphysics3d::approxEqual(lengthSquare(), decimal(1.0));
}
// Return true if the values are not NAN OR INF
inline bool Vector2::isFinite() const {
RP3D_FORCE_INLINE bool Vector2::isFinite() const {
return std::isfinite(x) && std::isfinite(y);
}
// Return true if the vector is the zero vector
inline bool Vector2::isZero() const {
return approxEqual(lengthSquare(), 0.0);
RP3D_FORCE_INLINE bool Vector2::isZero() const {
return reactphysics3d::approxEqual(lengthSquare(), decimal(0.0));
}
// Overloaded operator for the equality condition
inline bool Vector2::operator== (const Vector2& vector) const {
RP3D_FORCE_INLINE bool Vector2::operator== (const Vector2& vector) const {
return (x == vector.x && y == vector.y);
}
// Overloaded operator for the is different condition
inline bool Vector2::operator!= (const Vector2& vector) const {
RP3D_FORCE_INLINE bool Vector2::operator!= (const Vector2& vector) const {
return !(*this == vector);
}
// Overloaded operator for addition with assignment
inline Vector2& Vector2::operator+=(const Vector2& vector) {
RP3D_FORCE_INLINE Vector2& Vector2::operator+=(const Vector2& vector) {
x += vector.x;
y += vector.y;
return *this;
}
// Overloaded operator for substraction with assignment
inline Vector2& Vector2::operator-=(const Vector2& vector) {
RP3D_FORCE_INLINE Vector2& Vector2::operator-=(const Vector2& vector) {
x -= vector.x;
y -= vector.y;
return *this;
}
// Overloaded operator for multiplication with a number with assignment
inline Vector2& Vector2::operator*=(decimal number) {
RP3D_FORCE_INLINE Vector2& Vector2::operator*=(decimal number) {
x *= number;
y *= number;
return *this;
}
// Overloaded operator for division by a number with assignment
inline Vector2& Vector2::operator/=(decimal number) {
RP3D_FORCE_INLINE Vector2& Vector2::operator/=(decimal number) {
assert(number > std::numeric_limits<decimal>::epsilon());
x /= number;
y /= number;
@ -283,94 +268,90 @@ inline Vector2& Vector2::operator/=(decimal number) {
}
// Overloaded operator for value access
inline decimal& Vector2::operator[] (int index) {
RP3D_FORCE_INLINE decimal& Vector2::operator[] (int index) {
return (&x)[index];
}
// Overloaded operator for value access
inline const decimal& Vector2::operator[] (int index) const {
RP3D_FORCE_INLINE const decimal& Vector2::operator[] (int index) const {
return (&x)[index];
}
// Overloaded operator for addition
inline Vector2 operator+(const Vector2& vector1, const Vector2& vector2) {
RP3D_FORCE_INLINE Vector2 operator+(const Vector2& vector1, const Vector2& vector2) {
return Vector2(vector1.x + vector2.x, vector1.y + vector2.y);
}
// Overloaded operator for substraction
inline Vector2 operator-(const Vector2& vector1, const Vector2& vector2) {
RP3D_FORCE_INLINE Vector2 operator-(const Vector2& vector1, const Vector2& vector2) {
return Vector2(vector1.x - vector2.x, vector1.y - vector2.y);
}
// Overloaded operator for the negative of a vector
inline Vector2 operator-(const Vector2& vector) {
RP3D_FORCE_INLINE Vector2 operator-(const Vector2& vector) {
return Vector2(-vector.x, -vector.y);
}
// Overloaded operator for multiplication with a number
inline Vector2 operator*(const Vector2& vector, decimal number) {
RP3D_FORCE_INLINE Vector2 operator*(const Vector2& vector, decimal number) {
return Vector2(number * vector.x, number * vector.y);
}
// Overloaded operator for multiplication of two vectors
inline Vector2 operator*(const Vector2& vector1, const Vector2& vector2) {
RP3D_FORCE_INLINE Vector2 operator*(const Vector2& vector1, const Vector2& vector2) {
return Vector2(vector1.x * vector2.x, vector1.y * vector2.y);
}
// Overloaded operator for division by a number
inline Vector2 operator/(const Vector2& vector, decimal number) {
RP3D_FORCE_INLINE Vector2 operator/(const Vector2& vector, decimal number) {
assert(number > MACHINE_EPSILON);
return Vector2(vector.x / number, vector.y / number);
}
// Overload operator for division between two vectors
inline Vector2 operator/(const Vector2& vector1, const Vector2& vector2) {
RP3D_FORCE_INLINE Vector2 operator/(const Vector2& vector1, const Vector2& vector2) {
assert(vector2.x > MACHINE_EPSILON);
assert(vector2.y > MACHINE_EPSILON);
return Vector2(vector1.x / vector2.x, vector1.y / vector2.y);
}
// Overloaded operator for multiplication with a number
inline Vector2 operator*(decimal number, const Vector2& vector) {
RP3D_FORCE_INLINE Vector2 operator*(decimal number, const Vector2& vector) {
return vector * number;
}
// Assignment operator
inline Vector2& Vector2::operator=(const Vector2& vector) {
if (&vector != this) {
x = vector.x;
y = vector.y;
}
return *this;
}
// Overloaded less than operator for ordering to be used inside std::set for instance
inline bool Vector2::operator<(const Vector2& vector) const {
RP3D_FORCE_INLINE bool Vector2::operator<(const Vector2& vector) const {
return (x == vector.x ? y < vector.y : x < vector.x);
}
// Return a vector taking the minimum components of two vectors
inline Vector2 Vector2::min(const Vector2& vector1, const Vector2& vector2) {
RP3D_FORCE_INLINE Vector2 Vector2::min(const Vector2& vector1, const Vector2& vector2) {
return Vector2(std::min(vector1.x, vector2.x),
std::min(vector1.y, vector2.y));
}
// Return a vector taking the maximum components of two vectors
inline Vector2 Vector2::max(const Vector2& vector1, const Vector2& vector2) {
RP3D_FORCE_INLINE Vector2 Vector2::max(const Vector2& vector1, const Vector2& vector2) {
return Vector2(std::max(vector1.x, vector2.x),
std::max(vector1.y, vector2.y));
}
// Get the string representation
inline std::string Vector2::to_string() const {
RP3D_FORCE_INLINE std::string Vector2::to_string() const {
return "Vector2(" + std::to_string(x) + "," + std::to_string(y) + ")";
}
// Return the zero vector
inline Vector2 Vector2::zero() {
RP3D_FORCE_INLINE Vector2 Vector2::zero() {
return Vector2(0, 0);
}
// Function to test if two vectors are (almost) equal
RP3D_FORCE_INLINE bool approxEqual(const Vector2& vec1, const Vector2& vec2, decimal epsilon = MACHINE_EPSILON) {
return approxEqual(vec1.x, vec2.x, epsilon) && approxEqual(vec1.y, vec2.y, epsilon);
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
@ -28,8 +28,11 @@
// Libraries
#include <cassert>
#include <reactphysics3d/mathematics/mathematics_functions.h>
#include <cmath>
#include <algorithm>
#include <reactphysics3d/decimal.h>
#include <reactphysics3d/mathematics/mathematics_common.h>
#include <reactphysics3d/configuration.h>
/// ReactPhysics3D namespace
namespace reactphysics3d {
@ -61,12 +64,6 @@ struct Vector3 {
/// Constructor with arguments
Vector3(decimal newX, decimal newY, decimal newZ);
/// Copy-constructor
Vector3(const Vector3& vector);
/// Destructor
~Vector3() = default;
/// Set all the values of the vector
void setAllValues(decimal newX, decimal newY, decimal newZ);
@ -142,9 +139,6 @@ struct Vector3 {
/// Overloaded operator for value access
const decimal& operator[] (int index) const;
/// Overloaded operator
Vector3& operator=(const Vector3& vector);
/// Overloaded less than operator for ordering to be used inside std::set for instance
bool operator<(const Vector3& vector) const;
@ -173,58 +167,53 @@ struct Vector3 {
};
// Constructor of the struct Vector3
inline Vector3::Vector3() : x(0.0), y(0.0), z(0.0) {
RP3D_FORCE_INLINE Vector3::Vector3() : x(0.0), y(0.0), z(0.0) {
}
// Constructor with arguments
inline Vector3::Vector3(decimal newX, decimal newY, decimal newZ) : x(newX), y(newY), z(newZ) {
}
// Copy-constructor
inline Vector3::Vector3(const Vector3& vector) : x(vector.x), y(vector.y), z(vector.z) {
RP3D_FORCE_INLINE Vector3::Vector3(decimal newX, decimal newY, decimal newZ) : x(newX), y(newY), z(newZ) {
}
// Set the vector to zero
inline void Vector3::setToZero() {
RP3D_FORCE_INLINE void Vector3::setToZero() {
x = 0;
y = 0;
z = 0;
}
// Set all the values of the vector
inline void Vector3::setAllValues(decimal newX, decimal newY, decimal newZ) {
RP3D_FORCE_INLINE void Vector3::setAllValues(decimal newX, decimal newY, decimal newZ) {
x = newX;
y = newY;
z = newZ;
}
// Return the length of the vector
inline decimal Vector3::length() const {
RP3D_FORCE_INLINE decimal Vector3::length() const {
return std::sqrt(x*x + y*y + z*z);
}
// Return the square of the length of the vector
inline decimal Vector3::lengthSquare() const {
RP3D_FORCE_INLINE decimal Vector3::lengthSquare() const {
return x*x + y*y + z*z;
}
// Scalar product of two vectors (inline)
inline decimal Vector3::dot(const Vector3& vector) const {
// Scalar product of two vectors (RP3D_FORCE_INLINE)
RP3D_FORCE_INLINE decimal Vector3::dot(const Vector3& vector) const {
return (x*vector.x + y*vector.y + z*vector.z);
}
// Cross product of two vectors (inline)
inline Vector3 Vector3::cross(const Vector3& vector) const {
// Cross product of two vectors (RP3D_FORCE_INLINE)
RP3D_FORCE_INLINE Vector3 Vector3::cross(const Vector3& vector) const {
return Vector3(y * vector.z - z * vector.y,
z * vector.x - x * vector.z,
x * vector.y - y * vector.x);
}
// Normalize the vector
inline void Vector3::normalize() {
RP3D_FORCE_INLINE void Vector3::normalize() {
decimal l = length();
if (l < MACHINE_EPSILON) {
return;
@ -235,47 +224,47 @@ inline void Vector3::normalize() {
}
// Return the corresponding absolute value vector
inline Vector3 Vector3::getAbsoluteVector() const {
RP3D_FORCE_INLINE Vector3 Vector3::getAbsoluteVector() const {
return Vector3(std::abs(x), std::abs(y), std::abs(z));
}
// Return the axis with the minimal value
inline int Vector3::getMinAxis() const {
RP3D_FORCE_INLINE int Vector3::getMinAxis() const {
return (x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2));
}
// Return the axis with the maximal value
inline int Vector3::getMaxAxis() const {
RP3D_FORCE_INLINE int Vector3::getMaxAxis() const {
return (x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0));
}
// Return true if the vector is unit and false otherwise
inline bool Vector3::isUnit() const {
return approxEqual(lengthSquare(), 1.0);
RP3D_FORCE_INLINE bool Vector3::isUnit() const {
return reactphysics3d::approxEqual(lengthSquare(), decimal(1.0));
}
// Return true if the values are not NAN OR INF
inline bool Vector3::isFinite() const {
RP3D_FORCE_INLINE bool Vector3::isFinite() const {
return std::isfinite(x) && std::isfinite(y) && std::isfinite(z);
}
// Return true if the vector is the zero vector
inline bool Vector3::isZero() const {
return approxEqual(lengthSquare(), 0.0);
RP3D_FORCE_INLINE bool Vector3::isZero() const {
return reactphysics3d::approxEqual(lengthSquare(), decimal(0.0));
}
// Overloaded operator for the equality condition
inline bool Vector3::operator== (const Vector3& vector) const {
RP3D_FORCE_INLINE bool Vector3::operator== (const Vector3& vector) const {
return (x == vector.x && y == vector.y && z == vector.z);
}
// Overloaded operator for the is different condition
inline bool Vector3::operator!= (const Vector3& vector) const {
RP3D_FORCE_INLINE bool Vector3::operator!= (const Vector3& vector) const {
return !(*this == vector);
}
// Overloaded operator for addition with assignment
inline Vector3& Vector3::operator+=(const Vector3& vector) {
RP3D_FORCE_INLINE Vector3& Vector3::operator+=(const Vector3& vector) {
x += vector.x;
y += vector.y;
z += vector.z;
@ -283,7 +272,7 @@ inline Vector3& Vector3::operator+=(const Vector3& vector) {
}
// Overloaded operator for substraction with assignment
inline Vector3& Vector3::operator-=(const Vector3& vector) {
RP3D_FORCE_INLINE Vector3& Vector3::operator-=(const Vector3& vector) {
x -= vector.x;
y -= vector.y;
z -= vector.z;
@ -291,7 +280,7 @@ inline Vector3& Vector3::operator-=(const Vector3& vector) {
}
// Overloaded operator for multiplication with a number with assignment
inline Vector3& Vector3::operator*=(decimal number) {
RP3D_FORCE_INLINE Vector3& Vector3::operator*=(decimal number) {
x *= number;
y *= number;
z *= number;
@ -299,7 +288,7 @@ inline Vector3& Vector3::operator*=(decimal number) {
}
// Overloaded operator for division by a number with assignment
inline Vector3& Vector3::operator/=(decimal number) {
RP3D_FORCE_INLINE Vector3& Vector3::operator/=(decimal number) {
assert(number > std::numeric_limits<decimal>::epsilon());
x /= number;
y /= number;
@ -308,43 +297,43 @@ inline Vector3& Vector3::operator/=(decimal number) {
}
// Overloaded operator for value access
inline decimal& Vector3::operator[] (int index) {
RP3D_FORCE_INLINE decimal& Vector3::operator[] (int index) {
return (&x)[index];
}
// Overloaded operator for value access
inline const decimal& Vector3::operator[] (int index) const {
RP3D_FORCE_INLINE const decimal& Vector3::operator[] (int index) const {
return (&x)[index];
}
// Overloaded operator for addition
inline Vector3 operator+(const Vector3& vector1, const Vector3& vector2) {
RP3D_FORCE_INLINE Vector3 operator+(const Vector3& vector1, const Vector3& vector2) {
return Vector3(vector1.x + vector2.x, vector1.y + vector2.y, vector1.z + vector2.z);
}
// Overloaded operator for substraction
inline Vector3 operator-(const Vector3& vector1, const Vector3& vector2) {
RP3D_FORCE_INLINE Vector3 operator-(const Vector3& vector1, const Vector3& vector2) {
return Vector3(vector1.x - vector2.x, vector1.y - vector2.y, vector1.z - vector2.z);
}
// Overloaded operator for the negative of a vector
inline Vector3 operator-(const Vector3& vector) {
RP3D_FORCE_INLINE Vector3 operator-(const Vector3& vector) {
return Vector3(-vector.x, -vector.y, -vector.z);
}
// Overloaded operator for multiplication with a number
inline Vector3 operator*(const Vector3& vector, decimal number) {
RP3D_FORCE_INLINE Vector3 operator*(const Vector3& vector, decimal number) {
return Vector3(number * vector.x, number * vector.y, number * vector.z);
}
// Overloaded operator for division by a number
inline Vector3 operator/(const Vector3& vector, decimal number) {
RP3D_FORCE_INLINE Vector3 operator/(const Vector3& vector, decimal number) {
assert(number > MACHINE_EPSILON);
return Vector3(vector.x / number, vector.y / number, vector.z / number);
}
// Overload operator for division between two vectors
inline Vector3 operator/(const Vector3& vector1, const Vector3& vector2) {
RP3D_FORCE_INLINE Vector3 operator/(const Vector3& vector1, const Vector3& vector2) {
assert(vector2.x > MACHINE_EPSILON);
assert(vector2.y > MACHINE_EPSILON);
assert(vector2.z > MACHINE_EPSILON);
@ -352,64 +341,60 @@ inline Vector3 operator/(const Vector3& vector1, const Vector3& vector2) {
}
// Overloaded operator for multiplication with a number
inline Vector3 operator*(decimal number, const Vector3& vector) {
RP3D_FORCE_INLINE Vector3 operator*(decimal number, const Vector3& vector) {
return vector * number;
}
// Overload operator for multiplication between two vectors
inline Vector3 operator*(const Vector3& vector1, const Vector3& vector2) {
RP3D_FORCE_INLINE Vector3 operator*(const Vector3& vector1, const Vector3& vector2) {
return Vector3(vector1.x * vector2.x, vector1.y * vector2.y, vector1.z * vector2.z);
}
// Assignment operator
inline Vector3& Vector3::operator=(const Vector3& vector) {
if (&vector != this) {
x = vector.x;
y = vector.y;
z = vector.z;
}
return *this;
}
// Overloaded less than operator for ordering to be used inside std::set for instance
inline bool Vector3::operator<(const Vector3& vector) const {
RP3D_FORCE_INLINE bool Vector3::operator<(const Vector3& vector) const {
return (x == vector.x ? (y == vector.y ? z < vector.z : y < vector.y) : x < vector.x);
}
// Return a vector taking the minimum components of two vectors
inline Vector3 Vector3::min(const Vector3& vector1, const Vector3& vector2) {
RP3D_FORCE_INLINE Vector3 Vector3::min(const Vector3& vector1, const Vector3& vector2) {
return Vector3(std::min(vector1.x, vector2.x),
std::min(vector1.y, vector2.y),
std::min(vector1.z, vector2.z));
}
// Return a vector taking the maximum components of two vectors
inline Vector3 Vector3::max(const Vector3& vector1, const Vector3& vector2) {
RP3D_FORCE_INLINE Vector3 Vector3::max(const Vector3& vector1, const Vector3& vector2) {
return Vector3(std::max(vector1.x, vector2.x),
std::max(vector1.y, vector2.y),
std::max(vector1.z, vector2.z));
}
// Return the minimum value among the three components of a vector
inline decimal Vector3::getMinValue() const {
RP3D_FORCE_INLINE decimal Vector3::getMinValue() const {
return std::min(std::min(x, y), z);
}
// Return the maximum value among the three components of a vector
inline decimal Vector3::getMaxValue() const {
RP3D_FORCE_INLINE decimal Vector3::getMaxValue() const {
return std::max(std::max(x, y), z);
}
// Get the string representation
inline std::string Vector3::to_string() const {
RP3D_FORCE_INLINE std::string Vector3::to_string() const {
return "Vector3(" + std::to_string(x) + "," + std::to_string(y) + "," + std::to_string(z) + ")";
}
// Return the zero vector
inline Vector3 Vector3::zero() {
RP3D_FORCE_INLINE Vector3 Vector3::zero() {
return Vector3(0, 0, 0);
}
// Function to test if two vectors are (almost) equal
RP3D_FORCE_INLINE bool approxEqual(const Vector3& vec1, const Vector3& vec2, decimal epsilon = MACHINE_EPSILON) {
return approxEqual(vec1.x, vec2.x, epsilon) && approxEqual(vec1.y, vec2.y, epsilon) &&
approxEqual(vec1.z, vec2.z, epsilon);
}
}
#endif

View File

@ -1,6 +1,6 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2020 Daniel Chappuis *
* Copyright (c) 2010-2022 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *

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